aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2412/dma.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-01-28 07:01:20 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-28 08:20:50 -0500
commitc6709e8ef5752314c22c75bc7575f9be390e215b (patch)
treeb263b43370faf705141dfee1bd2d8300c00fe2c5 /arch/arm/mach-s3c2412/dma.c
parent67d729adc0e76e21c82a2c59853f25f5f784ca79 (diff)
[ARM] 4780/1: S3C2412: Allow for seperate DMA channels for TX and RX
The current S3C24XX DMA code does not allow for an peripheral that has one channel for RX and another for TX. This patch adds a per-cpu dma operation to select the transmit or receive channel, and adds support to the S3C2412 for the seperate DMA channels for TX and RX. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-s3c2412/dma.c')
-rw-r--r--arch/arm/mach-s3c2412/dma.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index c9cd51439126..1dd864993566 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -40,106 +40,141 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
40 [DMACH_XD0] = { 40 [DMACH_XD0] = {
41 .name = "xdreq0", 41 .name = "xdreq0",
42 .channels = MAP(S3C2412_DMAREQSEL_XDREQ0), 42 .channels = MAP(S3C2412_DMAREQSEL_XDREQ0),
43 .channels_rx = MAP(S3C2412_DMAREQSEL_XDREQ0),
43 }, 44 },
44 [DMACH_XD1] = { 45 [DMACH_XD1] = {
45 .name = "xdreq1", 46 .name = "xdreq1",
46 .channels = MAP(S3C2412_DMAREQSEL_XDREQ1), 47 .channels = MAP(S3C2412_DMAREQSEL_XDREQ1),
48 .channels_rx = MAP(S3C2412_DMAREQSEL_XDREQ1),
47 }, 49 },
48 [DMACH_SDI] = { 50 [DMACH_SDI] = {
49 .name = "sdi", 51 .name = "sdi",
50 .channels = MAP(S3C2412_DMAREQSEL_SDI), 52 .channels = MAP(S3C2412_DMAREQSEL_SDI),
53 .channels_rx = MAP(S3C2412_DMAREQSEL_SDI),
51 .hw_addr.to = S3C2410_PA_SDI + S3C2410_SDIDATA, 54 .hw_addr.to = S3C2410_PA_SDI + S3C2410_SDIDATA,
52 .hw_addr.from = S3C2410_PA_SDI + S3C2410_SDIDATA, 55 .hw_addr.from = S3C2410_PA_SDI + S3C2410_SDIDATA,
53 }, 56 },
54 [DMACH_SPI0] = { 57 [DMACH_SPI0] = {
55 .name = "spi0", 58 .name = "spi0",
56 .channels = MAP(S3C2412_DMAREQSEL_SPI0TX), 59 .channels = MAP(S3C2412_DMAREQSEL_SPI0TX),
60 .channels_rx = MAP(S3C2412_DMAREQSEL_SPI0RX),
57 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT, 61 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
58 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT, 62 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
59 }, 63 },
60 [DMACH_SPI1] = { 64 [DMACH_SPI1] = {
61 .name = "spi1", 65 .name = "spi1",
62 .channels = MAP(S3C2412_DMAREQSEL_SPI1TX), 66 .channels = MAP(S3C2412_DMAREQSEL_SPI1TX),
67 .channels_rx = MAP(S3C2412_DMAREQSEL_SPI1RX),
63 .hw_addr.to = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT, 68 .hw_addr.to = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPTDAT,
64 .hw_addr.from = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPRDAT, 69 .hw_addr.from = S3C2410_PA_SPI + S3C2412_SPI1 + S3C2410_SPRDAT,
65 }, 70 },
66 [DMACH_UART0] = { 71 [DMACH_UART0] = {
67 .name = "uart0", 72 .name = "uart0",
68 .channels = MAP(S3C2412_DMAREQSEL_UART0_0), 73 .channels = MAP(S3C2412_DMAREQSEL_UART0_0),
74 .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_0),
69 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, 75 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
70 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, 76 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
71 }, 77 },
72 [DMACH_UART1] = { 78 [DMACH_UART1] = {
73 .name = "uart1", 79 .name = "uart1",
74 .channels = MAP(S3C2412_DMAREQSEL_UART1_0), 80 .channels = MAP(S3C2412_DMAREQSEL_UART1_0),
81 .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_0),
75 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, 82 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
76 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, 83 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
77 }, 84 },
78 [DMACH_UART2] = { 85 [DMACH_UART2] = {
79 .name = "uart2", 86 .name = "uart2",
80 .channels = MAP(S3C2412_DMAREQSEL_UART2_0), 87 .channels = MAP(S3C2412_DMAREQSEL_UART2_0),
88 .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_0),
81 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, 89 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
82 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, 90 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
83 }, 91 },
84 [DMACH_UART0_SRC2] = { 92 [DMACH_UART0_SRC2] = {
85 .name = "uart0", 93 .name = "uart0",
86 .channels = MAP(S3C2412_DMAREQSEL_UART0_1), 94 .channels = MAP(S3C2412_DMAREQSEL_UART0_1),
95 .channels_rx = MAP(S3C2412_DMAREQSEL_UART0_1),
87 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH, 96 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
88 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH, 97 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
89 }, 98 },
90 [DMACH_UART1_SRC2] = { 99 [DMACH_UART1_SRC2] = {
91 .name = "uart1", 100 .name = "uart1",
92 .channels = MAP(S3C2412_DMAREQSEL_UART1_1), 101 .channels = MAP(S3C2412_DMAREQSEL_UART1_1),
102 .channels_rx = MAP(S3C2412_DMAREQSEL_UART1_1),
93 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH, 103 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
94 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH, 104 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
95 }, 105 },
96 [DMACH_UART2_SRC2] = { 106 [DMACH_UART2_SRC2] = {
97 .name = "uart2", 107 .name = "uart2",
98 .channels = MAP(S3C2412_DMAREQSEL_UART2_1), 108 .channels = MAP(S3C2412_DMAREQSEL_UART2_1),
109 .channels_rx = MAP(S3C2412_DMAREQSEL_UART2_1),
99 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH, 110 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
100 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH, 111 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
101 }, 112 },
102 [DMACH_TIMER] = { 113 [DMACH_TIMER] = {
103 .name = "timer", 114 .name = "timer",
104 .channels = MAP(S3C2412_DMAREQSEL_TIMER), 115 .channels = MAP(S3C2412_DMAREQSEL_TIMER),
116 .channels_rx = MAP(S3C2412_DMAREQSEL_TIMER),
105 }, 117 },
106 [DMACH_I2S_IN] = { 118 [DMACH_I2S_IN] = {
107 .name = "i2s-sdi", 119 .name = "i2s-sdi",
108 .channels = MAP(S3C2412_DMAREQSEL_I2SRX), 120 .channels = MAP(S3C2412_DMAREQSEL_I2SRX),
121 .channels_rx = MAP(S3C2412_DMAREQSEL_I2SRX),
109 .hw_addr.from = S3C2410_PA_IIS + S3C2412_IISRXD, 122 .hw_addr.from = S3C2410_PA_IIS + S3C2412_IISRXD,
110 }, 123 },
111 [DMACH_I2S_OUT] = { 124 [DMACH_I2S_OUT] = {
112 .name = "i2s-sdo", 125 .name = "i2s-sdo",
113 .channels = MAP(S3C2412_DMAREQSEL_I2STX), 126 .channels = MAP(S3C2412_DMAREQSEL_I2STX),
127 .channels_rx = MAP(S3C2412_DMAREQSEL_I2STX),
114 .hw_addr.to = S3C2410_PA_IIS + S3C2412_IISTXD, 128 .hw_addr.to = S3C2410_PA_IIS + S3C2412_IISTXD,
115 }, 129 },
116 [DMACH_USB_EP1] = { 130 [DMACH_USB_EP1] = {
117 .name = "usb-ep1", 131 .name = "usb-ep1",
118 .channels = MAP(S3C2412_DMAREQSEL_USBEP1), 132 .channels = MAP(S3C2412_DMAREQSEL_USBEP1),
133 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP1),
119 }, 134 },
120 [DMACH_USB_EP2] = { 135 [DMACH_USB_EP2] = {
121 .name = "usb-ep2", 136 .name = "usb-ep2",
122 .channels = MAP(S3C2412_DMAREQSEL_USBEP2), 137 .channels = MAP(S3C2412_DMAREQSEL_USBEP2),
138 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP2),
123 }, 139 },
124 [DMACH_USB_EP3] = { 140 [DMACH_USB_EP3] = {
125 .name = "usb-ep3", 141 .name = "usb-ep3",
126 .channels = MAP(S3C2412_DMAREQSEL_USBEP3), 142 .channels = MAP(S3C2412_DMAREQSEL_USBEP3),
143 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP3),
127 }, 144 },
128 [DMACH_USB_EP4] = { 145 [DMACH_USB_EP4] = {
129 .name = "usb-ep4", 146 .name = "usb-ep4",
130 .channels = MAP(S3C2412_DMAREQSEL_USBEP4), 147 .channels = MAP(S3C2412_DMAREQSEL_USBEP4),
148 .channels_rx = MAP(S3C2412_DMAREQSEL_USBEP4),
131 }, 149 },
132}; 150};
133 151
152static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
153 struct s3c24xx_dma_map *map,
154 enum s3c2410_dmasrc dir)
155{
156 unsigned long chsel;
157
158 if (dir == S3C2410_DMASRC_HW)
159 chsel = map->channels_rx[0];
160 else
161 chsel = map->channels[0];
162
163 chsel &= ~DMA_CH_VALID;
164 chsel |= S3C2412_DMAREQSEL_HW;
165
166 writel(chsel, chan->regs + S3C2412_DMA_DMAREQSEL);
167}
168
134static void s3c2412_dma_select(struct s3c2410_dma_chan *chan, 169static void s3c2412_dma_select(struct s3c2410_dma_chan *chan,
135 struct s3c24xx_dma_map *map) 170 struct s3c24xx_dma_map *map)
136{ 171{
137 writel(map->channels[0] | S3C2412_DMAREQSEL_HW, 172 s3c2412_dma_direction(chan, map, chan->source);
138 chan->regs + S3C2412_DMA_DMAREQSEL);
139} 173}
140 174
141static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = { 175static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
142 .select = s3c2412_dma_select, 176 .select = s3c2412_dma_select,
177 .direction = s3c2412_dma_direction,
143 .dcon_mask = 0, 178 .dcon_mask = 0,
144 .map = s3c2412_dma_mappings, 179 .map = s3c2412_dma_mappings,
145 .map_size = ARRAY_SIZE(s3c2412_dma_mappings), 180 .map_size = ARRAY_SIZE(s3c2412_dma_mappings),