blob: b0d4723c9a90718ccbef119dfdf95412b33c4109 [file] [log] [blame]
Eduardo Valentin44ec9a32008-07-03 12:24:40 +03001/*
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 */
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -080013#include <linux/ioport.h>
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030014#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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030021
Tony Lindgren45c3eb72012-11-30 08:41:50 -080022#include <linux/omap-dma.h>
Tony Lindgren70c494c2012-09-19 10:46:56 -070023#include <mach/mux.h>
Tony Lindgrene4c060d2012-10-05 13:25:59 -070024#include "soc.h"
Arnd Bergmann22037472012-08-24 15:21:06 +020025#include <linux/platform_data/asoc-ti-mcbsp.h>
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030026
Tony Lindgren2e3ee9f2012-02-24 10:34:34 -080027#include <mach/irqs.h>
28
29#include "iomap.h"
Lokesh Vutla8c4cc002012-10-15 14:01:01 -070030#include "dma.h"
Tony Lindgren2e3ee9f2012-02-24 10:34:34 -080031
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030032#define DPS_RSTCT2_PER_EN (1 << 0)
33#define DSP_RSTCT2_WD_PER_EN (1 << 1)
34
Russell Kingb820ce42009-01-23 10:26:46 +000035static int dsp_use;
36static struct clk *api_clk;
37static struct clk *dsp_clk;
Jarkko Nikula40246e02011-09-26 10:45:38 +030038static struct platform_device **omap_mcbsp_devices;
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030039
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030040static void omap1_mcbsp_request(unsigned int id)
41{
42 /*
43 * On 1510, 1610 and 1710, McBSP1 and McBSP3
44 * are DSP public peripherals.
45 */
Jarkko Nikulafd1ee392011-07-01 08:52:27 +000046 if (id == 0 || id == 2) {
Russell Kingb820ce42009-01-23 10:26:46 +000047 if (dsp_use++ == 0) {
Arun KSd53eb732009-04-23 21:11:07 -060048 api_clk = clk_get(NULL, "api_ck");
49 dsp_clk = clk_get(NULL, "dsp_ck");
Russell Kingb820ce42009-01-23 10:26:46 +000050 if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
51 clk_enable(api_clk);
52 clk_enable(dsp_clk);
53
Russell Kingb820ce42009-01-23 10:26:46 +000054 /*
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 }
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030062 }
63}
64
65static void omap1_mcbsp_free(unsigned int id)
66{
Jarkko Nikulafd1ee392011-07-01 08:52:27 +000067 if (id == 0 || id == 2) {
Russell Kingb820ce42009-01-23 10:26:46 +000068 if (--dsp_use == 0) {
Russell Kingb820ce42009-01-23 10:26:46 +000069 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 }
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030079}
80
81static struct omap_mcbsp_ops omap1_mcbsp_ops = {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030082 .request = omap1_mcbsp_request,
83 .free = omap1_mcbsp_free,
84};
85
Jarkko Nikula6e574122011-09-26 10:45:47 +030086#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
Alistair Buxtonbf1cb7e2009-09-22 06:49:35 +010097#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -080098struct 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
Paul Walmsleye7916742011-03-04 22:36:46 +0000155#define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0]
156
Alistair Buxton7c006922009-09-22 10:02:58 +0100157static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300158 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300159 .ops = &omap1_mcbsp_ops,
160 },
161 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300162 .ops = &omap1_mcbsp_ops,
163 },
164};
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800165#define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1])
166#define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300167#else
Paul Walmsleye7916742011-03-04 22:36:46 +0000168#define omap7xx_mcbsp_res_0 NULL
Alistair Buxton7c006922009-09-22 10:02:58 +0100169#define omap7xx_mcbsp_pdata NULL
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800170#define OMAP7XX_MCBSP_RES_SZ 0
171#define OMAP7XX_MCBSP_COUNT 0
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300172#endif
173
174#ifdef CONFIG_ARCH_OMAP15XX
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800175struct 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
Paul Walmsleye7916742011-03-04 22:36:46 +0000259#define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0]
260
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300261static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
262 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300263 .ops = &omap1_mcbsp_ops,
Stanley.Miao06151152009-01-29 08:57:12 -0800264 },
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300265 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300266 .ops = &omap1_mcbsp_ops,
267 },
268 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300269 .ops = &omap1_mcbsp_ops,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300270 },
271};
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800272#define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1])
273#define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300274#else
Paul Walmsleye7916742011-03-04 22:36:46 +0000275#define omap15xx_mcbsp_res_0 NULL
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300276#define omap15xx_mcbsp_pdata NULL
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800277#define OMAP15XX_MCBSP_RES_SZ 0
278#define OMAP15XX_MCBSP_COUNT 0
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300279#endif
280
281#ifdef CONFIG_ARCH_OMAP16XX
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800282struct 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
Paul Walmsleye7916742011-03-04 22:36:46 +0000366#define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0]
367
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300368static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
369 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300370 .ops = &omap1_mcbsp_ops,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300371 },
372 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300373 .ops = &omap1_mcbsp_ops,
374 },
375 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300376 .ops = &omap1_mcbsp_ops,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300377 },
378};
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800379#define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1])
380#define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300381#else
Paul Walmsleye7916742011-03-04 22:36:46 +0000382#define omap16xx_mcbsp_res_0 NULL
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300383#define omap16xx_mcbsp_pdata NULL
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800384#define OMAP16XX_MCBSP_RES_SZ 0
385#define OMAP16XX_MCBSP_COUNT 0
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300386#endif
387
Jarkko Nikula40246e02011-09-26 10:45:38 +0300388static 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);
Jarkko Nikulacdc715142011-09-26 10:45:39 +0300409 config[i].reg_size = 2;
410 config[i].reg_step = 2;
Jarkko Nikula40246e02011-09-26 10:45:38 +0300411 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
Aaro Koskinene6f16822010-11-18 19:59:47 +0200421static int __init omap1_mcbsp_init(void)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300422{
Tony Lindgren7f9187c2010-12-10 09:46:24 -0800423 if (!cpu_class_is_omap1())
424 return -ENODEV;
425
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800426 if (cpu_is_omap7xx())
Paul Walmsleye7916742011-03-04 22:36:46 +0000427 omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800428 OMAP7XX_MCBSP_RES_SZ,
429 omap7xx_mcbsp_pdata,
430 OMAP7XX_MCBSP_COUNT);
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300431
432 if (cpu_is_omap15xx())
Paul Walmsleye7916742011-03-04 22:36:46 +0000433 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800434 OMAP15XX_MCBSP_RES_SZ,
435 omap15xx_mcbsp_pdata,
436 OMAP15XX_MCBSP_COUNT);
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300437
438 if (cpu_is_omap16xx())
Paul Walmsleye7916742011-03-04 22:36:46 +0000439 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800440 OMAP16XX_MCBSP_RES_SZ,
441 omap16xx_mcbsp_pdata,
442 OMAP16XX_MCBSP_COUNT);
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300443
Peter Ujfalusi0210dc42012-01-26 12:38:31 +0200444 return 0;
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300445}
446
447arch_initcall(omap1_mcbsp_init);