Commit | Line | Data |
---|---|---|
44ec9a33 EV |
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 | */ | |
3cf32bba | 13 | #include <linux/ioport.h> |
44ec9a33 EV |
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> | |
5a0e3ad6 | 20 | #include <linux/slab.h> |
44ec9a33 | 21 | |
45c3eb7d | 22 | #include <linux/omap-dma.h> |
70c494c3 | 23 | #include <mach/mux.h> |
e4c060db | 24 | #include "soc.h" |
2203747c | 25 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
44ec9a33 | 26 | |
2e3ee9f4 TL |
27 | #include <mach/irqs.h> |
28 | ||
29 | #include "iomap.h" | |
30 | ||
44ec9a33 EV |
31 | #define DPS_RSTCT2_PER_EN (1 << 0) |
32 | #define DSP_RSTCT2_WD_PER_EN (1 << 1) | |
33 | ||
b820ce4e RK |
34 | static int dsp_use; |
35 | static struct clk *api_clk; | |
36 | static struct clk *dsp_clk; | |
40246e00 | 37 | static struct platform_device **omap_mcbsp_devices; |
44ec9a33 | 38 | |
44ec9a33 EV |
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 | */ | |
fd1ee391 | 45 | if (id == 0 || id == 2) { |
b820ce4e | 46 | if (dsp_use++ == 0) { |
d53eb737 AK |
47 | api_clk = clk_get(NULL, "api_ck"); |
48 | dsp_clk = clk_get(NULL, "dsp_ck"); | |
b820ce4e RK |
49 | if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) { |
50 | clk_enable(api_clk); | |
51 | clk_enable(dsp_clk); | |
52 | ||
b820ce4e RK |
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 | } | |
44ec9a33 EV |
61 | } |
62 | } | |
63 | ||
64 | static void omap1_mcbsp_free(unsigned int id) | |
65 | { | |
fd1ee391 | 66 | if (id == 0 || id == 2) { |
b820ce4e | 67 | if (--dsp_use == 0) { |
b820ce4e RK |
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 | } | |
44ec9a33 EV |
78 | } |
79 | ||
80 | static struct omap_mcbsp_ops omap1_mcbsp_ops = { | |
44ec9a33 EV |
81 | .request = omap1_mcbsp_request, |
82 | .free = omap1_mcbsp_free, | |
83 | }; | |
84 | ||
6e574123 JN |
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 | ||
bf1cb7eb | 96 | #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) |
3cf32bba KVA |
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", | |
c821c462 | 116 | .start = 9, |
3cf32bba KVA |
117 | .flags = IORESOURCE_DMA, |
118 | }, | |
119 | { | |
120 | .name = "tx", | |
c821c462 | 121 | .start = 8, |
3cf32bba KVA |
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", | |
c821c462 | 143 | .start = 11, |
3cf32bba KVA |
144 | .flags = IORESOURCE_DMA, |
145 | }, | |
146 | { | |
147 | .name = "tx", | |
c821c462 | 148 | .start = 10, |
3cf32bba KVA |
149 | .flags = IORESOURCE_DMA, |
150 | }, | |
151 | }, | |
152 | }; | |
153 | ||
e7916740 PW |
154 | #define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0] |
155 | ||
7c006926 | 156 | static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = { |
44ec9a33 | 157 | { |
44ec9a33 EV |
158 | .ops = &omap1_mcbsp_ops, |
159 | }, | |
160 | { | |
44ec9a33 EV |
161 | .ops = &omap1_mcbsp_ops, |
162 | }, | |
163 | }; | |
3cf32bba KVA |
164 | #define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1]) |
165 | #define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res) | |
44ec9a33 | 166 | #else |
e7916740 | 167 | #define omap7xx_mcbsp_res_0 NULL |
7c006926 | 168 | #define omap7xx_mcbsp_pdata NULL |
3cf32bba KVA |
169 | #define OMAP7XX_MCBSP_RES_SZ 0 |
170 | #define OMAP7XX_MCBSP_COUNT 0 | |
44ec9a33 EV |
171 | #endif |
172 | ||
173 | #ifdef CONFIG_ARCH_OMAP15XX | |
3cf32bba KVA |
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", | |
c821c462 | 193 | .start = 9, |
3cf32bba KVA |
194 | .flags = IORESOURCE_DMA, |
195 | }, | |
196 | { | |
197 | .name = "tx", | |
c821c462 | 198 | .start = 8, |
3cf32bba KVA |
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", | |
c821c462 | 220 | .start = 17, |
3cf32bba KVA |
221 | .flags = IORESOURCE_DMA, |
222 | }, | |
223 | { | |
224 | .name = "tx", | |
c821c462 | 225 | .start = 16, |
3cf32bba KVA |
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", | |
c821c462 | 247 | .start = 11, |
3cf32bba KVA |
248 | .flags = IORESOURCE_DMA, |
249 | }, | |
250 | { | |
251 | .name = "tx", | |
c821c462 | 252 | .start = 10, |
3cf32bba KVA |
253 | .flags = IORESOURCE_DMA, |
254 | }, | |
255 | }, | |
256 | }; | |
257 | ||
e7916740 PW |
258 | #define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0] |
259 | ||
44ec9a33 EV |
260 | static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { |
261 | { | |
44ec9a33 | 262 | .ops = &omap1_mcbsp_ops, |
06151158 | 263 | }, |
44ec9a33 | 264 | { |
44ec9a33 EV |
265 | .ops = &omap1_mcbsp_ops, |
266 | }, | |
267 | { | |
44ec9a33 | 268 | .ops = &omap1_mcbsp_ops, |
44ec9a33 EV |
269 | }, |
270 | }; | |
3cf32bba KVA |
271 | #define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1]) |
272 | #define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res) | |
44ec9a33 | 273 | #else |
e7916740 | 274 | #define omap15xx_mcbsp_res_0 NULL |
44ec9a33 | 275 | #define omap15xx_mcbsp_pdata NULL |
3cf32bba KVA |
276 | #define OMAP15XX_MCBSP_RES_SZ 0 |
277 | #define OMAP15XX_MCBSP_COUNT 0 | |
44ec9a33 EV |
278 | #endif |
279 | ||
280 | #ifdef CONFIG_ARCH_OMAP16XX | |
3cf32bba KVA |
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", | |
c821c462 | 300 | .start = 9, |
3cf32bba KVA |
301 | .flags = IORESOURCE_DMA, |
302 | }, | |
303 | { | |
304 | .name = "tx", | |
c821c462 | 305 | .start = 8, |
3cf32bba KVA |
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", | |
c821c462 | 327 | .start = 17, |
3cf32bba KVA |
328 | .flags = IORESOURCE_DMA, |
329 | }, | |
330 | { | |
331 | .name = "tx", | |
c821c462 | 332 | .start = 16, |
3cf32bba KVA |
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", | |
c821c462 | 354 | .start = 11, |
3cf32bba KVA |
355 | .flags = IORESOURCE_DMA, |
356 | }, | |
357 | { | |
358 | .name = "tx", | |
c821c462 | 359 | .start = 10, |
3cf32bba KVA |
360 | .flags = IORESOURCE_DMA, |
361 | }, | |
362 | }, | |
363 | }; | |
364 | ||
e7916740 PW |
365 | #define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0] |
366 | ||
44ec9a33 EV |
367 | static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { |
368 | { | |
44ec9a33 | 369 | .ops = &omap1_mcbsp_ops, |
44ec9a33 EV |
370 | }, |
371 | { | |
44ec9a33 EV |
372 | .ops = &omap1_mcbsp_ops, |
373 | }, | |
374 | { | |
44ec9a33 | 375 | .ops = &omap1_mcbsp_ops, |
44ec9a33 EV |
376 | }, |
377 | }; | |
3cf32bba KVA |
378 | #define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1]) |
379 | #define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res) | |
44ec9a33 | 380 | #else |
e7916740 | 381 | #define omap16xx_mcbsp_res_0 NULL |
44ec9a33 | 382 | #define omap16xx_mcbsp_pdata NULL |
3cf32bba KVA |
383 | #define OMAP16XX_MCBSP_RES_SZ 0 |
384 | #define OMAP16XX_MCBSP_COUNT 0 | |
44ec9a33 EV |
385 | #endif |
386 | ||
40246e00 JN |
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 = kzalloc(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); | |
cdc71514 JN |
408 | config[i].reg_size = 2; |
409 | config[i].reg_step = 2; | |
40246e00 JN |
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 | ||
e6f16821 | 420 | static int __init omap1_mcbsp_init(void) |
44ec9a33 | 421 | { |
7f9187c2 TL |
422 | if (!cpu_class_is_omap1()) |
423 | return -ENODEV; | |
424 | ||
bf1cb7eb | 425 | if (cpu_is_omap7xx()) |
e7916740 | 426 | omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0, |
3cf32bba KVA |
427 | OMAP7XX_MCBSP_RES_SZ, |
428 | omap7xx_mcbsp_pdata, | |
429 | OMAP7XX_MCBSP_COUNT); | |
44ec9a33 EV |
430 | |
431 | if (cpu_is_omap15xx()) | |
e7916740 | 432 | omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0, |
3cf32bba KVA |
433 | OMAP15XX_MCBSP_RES_SZ, |
434 | omap15xx_mcbsp_pdata, | |
435 | OMAP15XX_MCBSP_COUNT); | |
44ec9a33 EV |
436 | |
437 | if (cpu_is_omap16xx()) | |
e7916740 | 438 | omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0, |
3cf32bba KVA |
439 | OMAP16XX_MCBSP_RES_SZ, |
440 | omap16xx_mcbsp_pdata, | |
441 | OMAP16XX_MCBSP_COUNT); | |
44ec9a33 | 442 | |
0210dc4e | 443 | return 0; |
44ec9a33 EV |
444 | } |
445 | ||
446 | arch_initcall(omap1_mcbsp_init); |