Merge remote-tracking branch 'spi/topic/core' into spi-next
[sfrench/cifs-2.6.git] / arch / arm / mach-s3c64xx / pl080.c
1 /*
2  * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
3  *
4  * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/amba/bus.h>
13 #include <linux/amba/pl080.h>
14 #include <linux/amba/pl08x.h>
15 #include <linux/of.h>
16
17 #include <plat/cpu.h>
18 #include <mach/irqs.h>
19 #include <mach/map.h>
20
21 #include "regs-sys.h"
22
23 static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
24 {
25         return cd->min_signal;
26 }
27
28 static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
29 {
30 }
31
32 /*
33  * DMA0
34  */
35
36 static struct pl08x_channel_data s3c64xx_dma0_info[] = {
37         {
38                 .bus_id = "uart0_tx",
39                 .min_signal = 0,
40                 .max_signal = 0,
41                 .periph_buses = PL08X_AHB2,
42         }, {
43                 .bus_id = "uart0_rx",
44                 .min_signal = 1,
45                 .max_signal = 1,
46                 .periph_buses = PL08X_AHB2,
47         }, {
48                 .bus_id = "uart1_tx",
49                 .min_signal = 2,
50                 .max_signal = 2,
51                 .periph_buses = PL08X_AHB2,
52         }, {
53                 .bus_id = "uart1_rx",
54                 .min_signal = 3,
55                 .max_signal = 3,
56                 .periph_buses = PL08X_AHB2,
57         }, {
58                 .bus_id = "uart2_tx",
59                 .min_signal = 4,
60                 .max_signal = 4,
61                 .periph_buses = PL08X_AHB2,
62         }, {
63                 .bus_id = "uart2_rx",
64                 .min_signal = 5,
65                 .max_signal = 5,
66                 .periph_buses = PL08X_AHB2,
67         }, {
68                 .bus_id = "uart3_tx",
69                 .min_signal = 6,
70                 .max_signal = 6,
71                 .periph_buses = PL08X_AHB2,
72         }, {
73                 .bus_id = "uart3_rx",
74                 .min_signal = 7,
75                 .max_signal = 7,
76                 .periph_buses = PL08X_AHB2,
77         }, {
78                 .bus_id = "pcm0_tx",
79                 .min_signal = 8,
80                 .max_signal = 8,
81                 .periph_buses = PL08X_AHB2,
82         }, {
83                 .bus_id = "pcm0_rx",
84                 .min_signal = 9,
85                 .max_signal = 9,
86                 .periph_buses = PL08X_AHB2,
87         }, {
88                 .bus_id = "i2s0_tx",
89                 .min_signal = 10,
90                 .max_signal = 10,
91                 .periph_buses = PL08X_AHB2,
92         }, {
93                 .bus_id = "i2s0_rx",
94                 .min_signal = 11,
95                 .max_signal = 11,
96                 .periph_buses = PL08X_AHB2,
97         }, {
98                 .bus_id = "spi0_tx",
99                 .min_signal = 12,
100                 .max_signal = 12,
101                 .periph_buses = PL08X_AHB2,
102         }, {
103                 .bus_id = "spi0_rx",
104                 .min_signal = 13,
105                 .max_signal = 13,
106                 .periph_buses = PL08X_AHB2,
107         }, {
108                 .bus_id = "i2s2_tx",
109                 .min_signal = 14,
110                 .max_signal = 14,
111                 .periph_buses = PL08X_AHB2,
112         }, {
113                 .bus_id = "i2s2_rx",
114                 .min_signal = 15,
115                 .max_signal = 15,
116                 .periph_buses = PL08X_AHB2,
117         }
118 };
119
120 static const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
121         { "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] },
122         { "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] },
123         { "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] },
124         { "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] },
125         { "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] },
126         { "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] },
127         { "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] },
128         { "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] },
129         { "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] },
130         { "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] },
131         { "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] },
132         { "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] },
133         { "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] },
134         { "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] },
135         { "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] },
136         { "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] },
137 };
138
139 struct pl08x_platform_data s3c64xx_dma0_plat_data = {
140         .memcpy_channel = {
141                 .bus_id = "memcpy",
142                 .cctl_memcpy =
143                         (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
144                         PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
145                         PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
146                         PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
147                         PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
148                         PL080_CONTROL_PROT_SYS),
149         },
150         .lli_buses = PL08X_AHB1,
151         .mem_buses = PL08X_AHB1,
152         .get_xfer_signal = pl08x_get_xfer_signal,
153         .put_xfer_signal = pl08x_put_xfer_signal,
154         .slave_channels = s3c64xx_dma0_info,
155         .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
156         .slave_map = s3c64xx_dma0_slave_map,
157         .slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map),
158 };
159
160 static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
161                         0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
162
163 /*
164  * DMA1
165  */
166
167 static struct pl08x_channel_data s3c64xx_dma1_info[] = {
168         {
169                 .bus_id = "pcm1_tx",
170                 .min_signal = 0,
171                 .max_signal = 0,
172                 .periph_buses = PL08X_AHB2,
173         }, {
174                 .bus_id = "pcm1_rx",
175                 .min_signal = 1,
176                 .max_signal = 1,
177                 .periph_buses = PL08X_AHB2,
178         }, {
179                 .bus_id = "i2s1_tx",
180                 .min_signal = 2,
181                 .max_signal = 2,
182                 .periph_buses = PL08X_AHB2,
183         }, {
184                 .bus_id = "i2s1_rx",
185                 .min_signal = 3,
186                 .max_signal = 3,
187                 .periph_buses = PL08X_AHB2,
188         }, {
189                 .bus_id = "spi1_tx",
190                 .min_signal = 4,
191                 .max_signal = 4,
192                 .periph_buses = PL08X_AHB2,
193         }, {
194                 .bus_id = "spi1_rx",
195                 .min_signal = 5,
196                 .max_signal = 5,
197                 .periph_buses = PL08X_AHB2,
198         }, {
199                 .bus_id = "ac97_out",
200                 .min_signal = 6,
201                 .max_signal = 6,
202                 .periph_buses = PL08X_AHB2,
203         }, {
204                 .bus_id = "ac97_in",
205                 .min_signal = 7,
206                 .max_signal = 7,
207                 .periph_buses = PL08X_AHB2,
208         }, {
209                 .bus_id = "ac97_mic",
210                 .min_signal = 8,
211                 .max_signal = 8,
212                 .periph_buses = PL08X_AHB2,
213         }, {
214                 .bus_id = "pwm",
215                 .min_signal = 9,
216                 .max_signal = 9,
217                 .periph_buses = PL08X_AHB2,
218         }, {
219                 .bus_id = "irda",
220                 .min_signal = 10,
221                 .max_signal = 10,
222                 .periph_buses = PL08X_AHB2,
223         }, {
224                 .bus_id = "external",
225                 .min_signal = 11,
226                 .max_signal = 11,
227                 .periph_buses = PL08X_AHB2,
228         },
229 };
230
231 static const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
232         { "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] },
233         { "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] },
234         { "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] },
235         { "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] },
236         { "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] },
237         { "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] },
238 };
239
240 struct pl08x_platform_data s3c64xx_dma1_plat_data = {
241         .memcpy_channel = {
242                 .bus_id = "memcpy",
243                 .cctl_memcpy =
244                         (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
245                         PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
246                         PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
247                         PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
248                         PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
249                         PL080_CONTROL_PROT_SYS),
250         },
251         .lli_buses = PL08X_AHB1,
252         .mem_buses = PL08X_AHB1,
253         .get_xfer_signal = pl08x_get_xfer_signal,
254         .put_xfer_signal = pl08x_put_xfer_signal,
255         .slave_channels = s3c64xx_dma1_info,
256         .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
257         .slave_map = s3c64xx_dma1_slave_map,
258         .slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map),
259 };
260
261 static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
262                         0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
263
264 static int __init s3c64xx_pl080_init(void)
265 {
266         if (!soc_is_s3c64xx())
267                 return 0;
268
269         /* Set all DMA configuration to be DMA, not SDMA */
270         writel(0xffffff, S3C64XX_SDMA_SEL);
271
272         if (of_have_populated_dt())
273                 return 0;
274
275         amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
276         amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
277
278         return 0;
279 }
280 arch_initcall(s3c64xx_pl080_init);