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