Merge tag 'sound-fix-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[sfrench/cifs-2.6.git] / arch / arm / mach-omap1 / mcbsp.c
1 /*
2  * linux/arch/arm/mach-omap1/mcbsp.c
3  *
4  * Copyright (C) 2008 Instituto Nokia de Tecnologia
5  * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * Multichannel mode not supported.
12  */
13 #include <linux/ioport.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/clk.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19 #include <linux/platform_device.h>
20 #include <linux/slab.h>
21
22 #include <linux/omap-dma.h>
23 #include <mach/mux.h>
24 #include "soc.h"
25 #include <linux/platform_data/asoc-ti-mcbsp.h>
26
27 #include <mach/irqs.h>
28
29 #include "iomap.h"
30
31 #define DPS_RSTCT2_PER_EN       (1 << 0)
32 #define DSP_RSTCT2_WD_PER_EN    (1 << 1)
33
34 static int dsp_use;
35 static struct clk *api_clk;
36 static struct clk *dsp_clk;
37 static struct platform_device **omap_mcbsp_devices;
38
39 static void omap1_mcbsp_request(unsigned int id)
40 {
41         /*
42          * On 1510, 1610 and 1710, McBSP1 and McBSP3
43          * are DSP public peripherals.
44          */
45         if (id == 0 || id == 2) {
46                 if (dsp_use++ == 0) {
47                         api_clk = clk_get(NULL, "api_ck");
48                         dsp_clk = clk_get(NULL, "dsp_ck");
49                         if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
50                                 clk_enable(api_clk);
51                                 clk_enable(dsp_clk);
52
53                                 /*
54                                  * DSP external peripheral reset
55                                  * FIXME: This should be moved to dsp code
56                                  */
57                                 __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
58                                                 DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
59                         }
60                 }
61         }
62 }
63
64 static void omap1_mcbsp_free(unsigned int id)
65 {
66         if (id == 0 || id == 2) {
67                 if (--dsp_use == 0) {
68                         if (!IS_ERR(api_clk)) {
69                                 clk_disable(api_clk);
70                                 clk_put(api_clk);
71                         }
72                         if (!IS_ERR(dsp_clk)) {
73                                 clk_disable(dsp_clk);
74                                 clk_put(dsp_clk);
75                         }
76                 }
77         }
78 }
79
80 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
81         .request        = omap1_mcbsp_request,
82         .free           = omap1_mcbsp_free,
83 };
84
85 #define OMAP7XX_MCBSP1_BASE     0xfffb1000
86 #define OMAP7XX_MCBSP2_BASE     0xfffb1800
87
88 #define OMAP1510_MCBSP1_BASE    0xe1011800
89 #define OMAP1510_MCBSP2_BASE    0xfffb1000
90 #define OMAP1510_MCBSP3_BASE    0xe1017000
91
92 #define OMAP1610_MCBSP1_BASE    0xe1011800
93 #define OMAP1610_MCBSP2_BASE    0xfffb1000
94 #define OMAP1610_MCBSP3_BASE    0xe1017000
95
96 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
97 struct resource omap7xx_mcbsp_res[][6] = {
98         {
99                 {
100                         .start = OMAP7XX_MCBSP1_BASE,
101                         .end   = OMAP7XX_MCBSP1_BASE + SZ_256,
102                         .flags = IORESOURCE_MEM,
103                 },
104                 {
105                         .name  = "rx",
106                         .start = INT_7XX_McBSP1RX,
107                         .flags = IORESOURCE_IRQ,
108                 },
109                 {
110                         .name  = "tx",
111                         .start = INT_7XX_McBSP1TX,
112                         .flags = IORESOURCE_IRQ,
113                 },
114                 {
115                         .name  = "rx",
116                         .start = 9,
117                         .flags = IORESOURCE_DMA,
118                 },
119                 {
120                         .name  = "tx",
121                         .start = 8,
122                         .flags = IORESOURCE_DMA,
123                 },
124         },
125         {
126                 {
127                         .start = OMAP7XX_MCBSP2_BASE,
128                         .end   = OMAP7XX_MCBSP2_BASE + SZ_256,
129                         .flags = IORESOURCE_MEM,
130                 },
131                 {
132                         .name  = "rx",
133                         .start = INT_7XX_McBSP2RX,
134                         .flags = IORESOURCE_IRQ,
135                 },
136                 {
137                         .name  = "tx",
138                         .start = INT_7XX_McBSP2TX,
139                         .flags = IORESOURCE_IRQ,
140                 },
141                 {
142                         .name  = "rx",
143                         .start = 11,
144                         .flags = IORESOURCE_DMA,
145                 },
146                 {
147                         .name  = "tx",
148                         .start = 10,
149                         .flags = IORESOURCE_DMA,
150                 },
151         },
152 };
153
154 #define omap7xx_mcbsp_res_0             omap7xx_mcbsp_res[0]
155
156 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
157         {
158                 .ops            = &omap1_mcbsp_ops,
159         },
160         {
161                 .ops            = &omap1_mcbsp_ops,
162         },
163 };
164 #define OMAP7XX_MCBSP_RES_SZ            ARRAY_SIZE(omap7xx_mcbsp_res[1])
165 #define OMAP7XX_MCBSP_COUNT             ARRAY_SIZE(omap7xx_mcbsp_res)
166 #else
167 #define omap7xx_mcbsp_res_0             NULL
168 #define omap7xx_mcbsp_pdata             NULL
169 #define OMAP7XX_MCBSP_RES_SZ            0
170 #define OMAP7XX_MCBSP_COUNT             0
171 #endif
172
173 #ifdef CONFIG_ARCH_OMAP15XX
174 struct resource omap15xx_mcbsp_res[][6] = {
175         {
176                 {
177                         .start = OMAP1510_MCBSP1_BASE,
178                         .end   = OMAP1510_MCBSP1_BASE + SZ_256,
179                         .flags = IORESOURCE_MEM,
180                 },
181                 {
182                         .name  = "rx",
183                         .start = INT_McBSP1RX,
184                         .flags = IORESOURCE_IRQ,
185                 },
186                 {
187                         .name  = "tx",
188                         .start = INT_McBSP1TX,
189                         .flags = IORESOURCE_IRQ,
190                 },
191                 {
192                         .name  = "rx",
193                         .start = 9,
194                         .flags = IORESOURCE_DMA,
195                 },
196                 {
197                         .name  = "tx",
198                         .start = 8,
199                         .flags = IORESOURCE_DMA,
200                 },
201         },
202         {
203                 {
204                         .start = OMAP1510_MCBSP2_BASE,
205                         .end   = OMAP1510_MCBSP2_BASE + SZ_256,
206                         .flags = IORESOURCE_MEM,
207                 },
208                 {
209                         .name  = "rx",
210                         .start = INT_1510_SPI_RX,
211                         .flags = IORESOURCE_IRQ,
212                 },
213                 {
214                         .name  = "tx",
215                         .start = INT_1510_SPI_TX,
216                         .flags = IORESOURCE_IRQ,
217                 },
218                 {
219                         .name  = "rx",
220                         .start = 17,
221                         .flags = IORESOURCE_DMA,
222                 },
223                 {
224                         .name  = "tx",
225                         .start = 16,
226                         .flags = IORESOURCE_DMA,
227                 },
228         },
229         {
230                 {
231                         .start = OMAP1510_MCBSP3_BASE,
232                         .end   = OMAP1510_MCBSP3_BASE + SZ_256,
233                         .flags = IORESOURCE_MEM,
234                 },
235                 {
236                         .name  = "rx",
237                         .start = INT_McBSP3RX,
238                         .flags = IORESOURCE_IRQ,
239                 },
240                 {
241                         .name  = "tx",
242                         .start = INT_McBSP3TX,
243                         .flags = IORESOURCE_IRQ,
244                 },
245                 {
246                         .name  = "rx",
247                         .start = 11,
248                         .flags = IORESOURCE_DMA,
249                 },
250                 {
251                         .name  = "tx",
252                         .start = 10,
253                         .flags = IORESOURCE_DMA,
254                 },
255         },
256 };
257
258 #define omap15xx_mcbsp_res_0            omap15xx_mcbsp_res[0]
259
260 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
261         {
262                 .ops            = &omap1_mcbsp_ops,
263         },
264         {
265                 .ops            = &omap1_mcbsp_ops,
266         },
267         {
268                 .ops            = &omap1_mcbsp_ops,
269         },
270 };
271 #define OMAP15XX_MCBSP_RES_SZ           ARRAY_SIZE(omap15xx_mcbsp_res[1])
272 #define OMAP15XX_MCBSP_COUNT            ARRAY_SIZE(omap15xx_mcbsp_res)
273 #else
274 #define omap15xx_mcbsp_res_0            NULL
275 #define omap15xx_mcbsp_pdata            NULL
276 #define OMAP15XX_MCBSP_RES_SZ           0
277 #define OMAP15XX_MCBSP_COUNT            0
278 #endif
279
280 #ifdef CONFIG_ARCH_OMAP16XX
281 struct resource omap16xx_mcbsp_res[][6] = {
282         {
283                 {
284                         .start = OMAP1610_MCBSP1_BASE,
285                         .end   = OMAP1610_MCBSP1_BASE + SZ_256,
286                         .flags = IORESOURCE_MEM,
287                 },
288                 {
289                         .name  = "rx",
290                         .start = INT_McBSP1RX,
291                         .flags = IORESOURCE_IRQ,
292                 },
293                 {
294                         .name  = "tx",
295                         .start = INT_McBSP1TX,
296                         .flags = IORESOURCE_IRQ,
297                 },
298                 {
299                         .name  = "rx",
300                         .start = 9,
301                         .flags = IORESOURCE_DMA,
302                 },
303                 {
304                         .name  = "tx",
305                         .start = 8,
306                         .flags = IORESOURCE_DMA,
307                 },
308         },
309         {
310                 {
311                         .start = OMAP1610_MCBSP2_BASE,
312                         .end   = OMAP1610_MCBSP2_BASE + SZ_256,
313                         .flags = IORESOURCE_MEM,
314                 },
315                 {
316                         .name  = "rx",
317                         .start = INT_1610_McBSP2_RX,
318                         .flags = IORESOURCE_IRQ,
319                 },
320                 {
321                         .name  = "tx",
322                         .start = INT_1610_McBSP2_TX,
323                         .flags = IORESOURCE_IRQ,
324                 },
325                 {
326                         .name  = "rx",
327                         .start = 17,
328                         .flags = IORESOURCE_DMA,
329                 },
330                 {
331                         .name  = "tx",
332                         .start = 16,
333                         .flags = IORESOURCE_DMA,
334                 },
335         },
336         {
337                 {
338                         .start = OMAP1610_MCBSP3_BASE,
339                         .end   = OMAP1610_MCBSP3_BASE + SZ_256,
340                         .flags = IORESOURCE_MEM,
341                 },
342                 {
343                         .name  = "rx",
344                         .start = INT_McBSP3RX,
345                         .flags = IORESOURCE_IRQ,
346                 },
347                 {
348                         .name  = "tx",
349                         .start = INT_McBSP3TX,
350                         .flags = IORESOURCE_IRQ,
351                 },
352                 {
353                         .name  = "rx",
354                         .start = 11,
355                         .flags = IORESOURCE_DMA,
356                 },
357                 {
358                         .name  = "tx",
359                         .start = 10,
360                         .flags = IORESOURCE_DMA,
361                 },
362         },
363 };
364
365 #define omap16xx_mcbsp_res_0            omap16xx_mcbsp_res[0]
366
367 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
368         {
369                 .ops            = &omap1_mcbsp_ops,
370         },
371         {
372                 .ops            = &omap1_mcbsp_ops,
373         },
374         {
375                 .ops            = &omap1_mcbsp_ops,
376         },
377 };
378 #define OMAP16XX_MCBSP_RES_SZ           ARRAY_SIZE(omap16xx_mcbsp_res[1])
379 #define OMAP16XX_MCBSP_COUNT            ARRAY_SIZE(omap16xx_mcbsp_res)
380 #else
381 #define omap16xx_mcbsp_res_0            NULL
382 #define omap16xx_mcbsp_pdata            NULL
383 #define OMAP16XX_MCBSP_RES_SZ           0
384 #define OMAP16XX_MCBSP_COUNT            0
385 #endif
386
387 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
388                         struct omap_mcbsp_platform_data *config, int size)
389 {
390         int i;
391
392         omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *),
393                                      GFP_KERNEL);
394         if (!omap_mcbsp_devices) {
395                 printk(KERN_ERR "Could not register McBSP devices\n");
396                 return;
397         }
398
399         for (i = 0; i < size; i++) {
400                 struct platform_device *new_mcbsp;
401                 int ret;
402
403                 new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
404                 if (!new_mcbsp)
405                         continue;
406                 platform_device_add_resources(new_mcbsp, &res[i * res_count],
407                                         res_count);
408                 config[i].reg_size = 2;
409                 config[i].reg_step = 2;
410                 new_mcbsp->dev.platform_data = &config[i];
411                 ret = platform_device_add(new_mcbsp);
412                 if (ret) {
413                         platform_device_put(new_mcbsp);
414                         continue;
415                 }
416                 omap_mcbsp_devices[i] = new_mcbsp;
417         }
418 }
419
420 static int __init omap1_mcbsp_init(void)
421 {
422         if (!cpu_class_is_omap1())
423                 return -ENODEV;
424
425         if (cpu_is_omap7xx())
426                 omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
427                                         OMAP7XX_MCBSP_RES_SZ,
428                                         omap7xx_mcbsp_pdata,
429                                         OMAP7XX_MCBSP_COUNT);
430
431         if (cpu_is_omap15xx())
432                 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
433                                         OMAP15XX_MCBSP_RES_SZ,
434                                         omap15xx_mcbsp_pdata,
435                                         OMAP15XX_MCBSP_COUNT);
436
437         if (cpu_is_omap16xx())
438                 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
439                                         OMAP16XX_MCBSP_RES_SZ,
440                                         omap16xx_mcbsp_pdata,
441                                         OMAP16XX_MCBSP_COUNT);
442
443         return 0;
444 }
445
446 arch_initcall(omap1_mcbsp_init);