blob: 36ab5d83327e1f0bd90a557def090d8550269b80 [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 Lindgrendd7667a2009-01-15 13:09:51 +020022#include <mach/irqs.h>
Tony Lindgrence491cf2009-10-20 09:40:47 -070023#include <plat/dma.h>
24#include <plat/mux.h>
25#include <plat/cpu.h>
26#include <plat/mcbsp.h>
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030027
28#define DPS_RSTCT2_PER_EN (1 << 0)
29#define DSP_RSTCT2_WD_PER_EN (1 << 1)
30
Russell Kingb820ce42009-01-23 10:26:46 +000031static int dsp_use;
32static struct clk *api_clk;
33static struct clk *dsp_clk;
Jarkko Nikula40246e02011-09-26 10:45:38 +030034static struct platform_device **omap_mcbsp_devices;
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030035
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030036static void omap1_mcbsp_request(unsigned int id)
37{
38 /*
39 * On 1510, 1610 and 1710, McBSP1 and McBSP3
40 * are DSP public peripherals.
41 */
Jarkko Nikulafd1ee392011-07-01 08:52:27 +000042 if (id == 0 || id == 2) {
Russell Kingb820ce42009-01-23 10:26:46 +000043 if (dsp_use++ == 0) {
Arun KSd53eb732009-04-23 21:11:07 -060044 api_clk = clk_get(NULL, "api_ck");
45 dsp_clk = clk_get(NULL, "dsp_ck");
Russell Kingb820ce42009-01-23 10:26:46 +000046 if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
47 clk_enable(api_clk);
48 clk_enable(dsp_clk);
49
Russell Kingb820ce42009-01-23 10:26:46 +000050 /*
51 * DSP external peripheral reset
52 * FIXME: This should be moved to dsp code
53 */
54 __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
55 DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
56 }
57 }
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030058 }
59}
60
61static void omap1_mcbsp_free(unsigned int id)
62{
Jarkko Nikulafd1ee392011-07-01 08:52:27 +000063 if (id == 0 || id == 2) {
Russell Kingb820ce42009-01-23 10:26:46 +000064 if (--dsp_use == 0) {
Russell Kingb820ce42009-01-23 10:26:46 +000065 if (!IS_ERR(api_clk)) {
66 clk_disable(api_clk);
67 clk_put(api_clk);
68 }
69 if (!IS_ERR(dsp_clk)) {
70 clk_disable(dsp_clk);
71 clk_put(dsp_clk);
72 }
73 }
74 }
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030075}
76
77static struct omap_mcbsp_ops omap1_mcbsp_ops = {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030078 .request = omap1_mcbsp_request,
79 .free = omap1_mcbsp_free,
80};
81
Alistair Buxtonbf1cb7e2009-09-22 06:49:35 +010082#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -080083struct resource omap7xx_mcbsp_res[][6] = {
84 {
85 {
86 .start = OMAP7XX_MCBSP1_BASE,
87 .end = OMAP7XX_MCBSP1_BASE + SZ_256,
88 .flags = IORESOURCE_MEM,
89 },
90 {
91 .name = "rx",
92 .start = INT_7XX_McBSP1RX,
93 .flags = IORESOURCE_IRQ,
94 },
95 {
96 .name = "tx",
97 .start = INT_7XX_McBSP1TX,
98 .flags = IORESOURCE_IRQ,
99 },
100 {
101 .name = "rx",
102 .start = OMAP_DMA_MCBSP1_RX,
103 .flags = IORESOURCE_DMA,
104 },
105 {
106 .name = "tx",
107 .start = OMAP_DMA_MCBSP1_TX,
108 .flags = IORESOURCE_DMA,
109 },
110 },
111 {
112 {
113 .start = OMAP7XX_MCBSP2_BASE,
114 .end = OMAP7XX_MCBSP2_BASE + SZ_256,
115 .flags = IORESOURCE_MEM,
116 },
117 {
118 .name = "rx",
119 .start = INT_7XX_McBSP2RX,
120 .flags = IORESOURCE_IRQ,
121 },
122 {
123 .name = "tx",
124 .start = INT_7XX_McBSP2TX,
125 .flags = IORESOURCE_IRQ,
126 },
127 {
128 .name = "rx",
129 .start = OMAP_DMA_MCBSP3_RX,
130 .flags = IORESOURCE_DMA,
131 },
132 {
133 .name = "tx",
134 .start = OMAP_DMA_MCBSP3_TX,
135 .flags = IORESOURCE_DMA,
136 },
137 },
138};
139
Paul Walmsleye7916742011-03-04 22:36:46 +0000140#define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0]
141
Alistair Buxton7c006922009-09-22 10:02:58 +0100142static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300143 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300144 .ops = &omap1_mcbsp_ops,
145 },
146 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300147 .ops = &omap1_mcbsp_ops,
148 },
149};
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800150#define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1])
151#define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300152#else
Paul Walmsleye7916742011-03-04 22:36:46 +0000153#define omap7xx_mcbsp_res_0 NULL
Alistair Buxton7c006922009-09-22 10:02:58 +0100154#define omap7xx_mcbsp_pdata NULL
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800155#define OMAP7XX_MCBSP_RES_SZ 0
156#define OMAP7XX_MCBSP_COUNT 0
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300157#endif
158
159#ifdef CONFIG_ARCH_OMAP15XX
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800160struct resource omap15xx_mcbsp_res[][6] = {
161 {
162 {
163 .start = OMAP1510_MCBSP1_BASE,
164 .end = OMAP1510_MCBSP1_BASE + SZ_256,
165 .flags = IORESOURCE_MEM,
166 },
167 {
168 .name = "rx",
169 .start = INT_McBSP1RX,
170 .flags = IORESOURCE_IRQ,
171 },
172 {
173 .name = "tx",
174 .start = INT_McBSP1TX,
175 .flags = IORESOURCE_IRQ,
176 },
177 {
178 .name = "rx",
179 .start = OMAP_DMA_MCBSP1_RX,
180 .flags = IORESOURCE_DMA,
181 },
182 {
183 .name = "tx",
184 .start = OMAP_DMA_MCBSP1_TX,
185 .flags = IORESOURCE_DMA,
186 },
187 },
188 {
189 {
190 .start = OMAP1510_MCBSP2_BASE,
191 .end = OMAP1510_MCBSP2_BASE + SZ_256,
192 .flags = IORESOURCE_MEM,
193 },
194 {
195 .name = "rx",
196 .start = INT_1510_SPI_RX,
197 .flags = IORESOURCE_IRQ,
198 },
199 {
200 .name = "tx",
201 .start = INT_1510_SPI_TX,
202 .flags = IORESOURCE_IRQ,
203 },
204 {
205 .name = "rx",
206 .start = OMAP_DMA_MCBSP2_RX,
207 .flags = IORESOURCE_DMA,
208 },
209 {
210 .name = "tx",
211 .start = OMAP_DMA_MCBSP2_TX,
212 .flags = IORESOURCE_DMA,
213 },
214 },
215 {
216 {
217 .start = OMAP1510_MCBSP3_BASE,
218 .end = OMAP1510_MCBSP3_BASE + SZ_256,
219 .flags = IORESOURCE_MEM,
220 },
221 {
222 .name = "rx",
223 .start = INT_McBSP3RX,
224 .flags = IORESOURCE_IRQ,
225 },
226 {
227 .name = "tx",
228 .start = INT_McBSP3TX,
229 .flags = IORESOURCE_IRQ,
230 },
231 {
232 .name = "rx",
233 .start = OMAP_DMA_MCBSP3_RX,
234 .flags = IORESOURCE_DMA,
235 },
236 {
237 .name = "tx",
238 .start = OMAP_DMA_MCBSP3_TX,
239 .flags = IORESOURCE_DMA,
240 },
241 },
242};
243
Paul Walmsleye7916742011-03-04 22:36:46 +0000244#define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0]
245
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300246static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
247 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300248 .ops = &omap1_mcbsp_ops,
Stanley.Miao06151152009-01-29 08:57:12 -0800249 },
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300250 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300251 .ops = &omap1_mcbsp_ops,
252 },
253 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300254 .ops = &omap1_mcbsp_ops,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300255 },
256};
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800257#define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1])
258#define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300259#else
Paul Walmsleye7916742011-03-04 22:36:46 +0000260#define omap15xx_mcbsp_res_0 NULL
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300261#define omap15xx_mcbsp_pdata NULL
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800262#define OMAP15XX_MCBSP_RES_SZ 0
263#define OMAP15XX_MCBSP_COUNT 0
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300264#endif
265
266#ifdef CONFIG_ARCH_OMAP16XX
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800267struct resource omap16xx_mcbsp_res[][6] = {
268 {
269 {
270 .start = OMAP1610_MCBSP1_BASE,
271 .end = OMAP1610_MCBSP1_BASE + SZ_256,
272 .flags = IORESOURCE_MEM,
273 },
274 {
275 .name = "rx",
276 .start = INT_McBSP1RX,
277 .flags = IORESOURCE_IRQ,
278 },
279 {
280 .name = "tx",
281 .start = INT_McBSP1TX,
282 .flags = IORESOURCE_IRQ,
283 },
284 {
285 .name = "rx",
286 .start = OMAP_DMA_MCBSP1_RX,
287 .flags = IORESOURCE_DMA,
288 },
289 {
290 .name = "tx",
291 .start = OMAP_DMA_MCBSP1_TX,
292 .flags = IORESOURCE_DMA,
293 },
294 },
295 {
296 {
297 .start = OMAP1610_MCBSP2_BASE,
298 .end = OMAP1610_MCBSP2_BASE + SZ_256,
299 .flags = IORESOURCE_MEM,
300 },
301 {
302 .name = "rx",
303 .start = INT_1610_McBSP2_RX,
304 .flags = IORESOURCE_IRQ,
305 },
306 {
307 .name = "tx",
308 .start = INT_1610_McBSP2_TX,
309 .flags = IORESOURCE_IRQ,
310 },
311 {
312 .name = "rx",
313 .start = OMAP_DMA_MCBSP2_RX,
314 .flags = IORESOURCE_DMA,
315 },
316 {
317 .name = "tx",
318 .start = OMAP_DMA_MCBSP2_TX,
319 .flags = IORESOURCE_DMA,
320 },
321 },
322 {
323 {
324 .start = OMAP1610_MCBSP3_BASE,
325 .end = OMAP1610_MCBSP3_BASE + SZ_256,
326 .flags = IORESOURCE_MEM,
327 },
328 {
329 .name = "rx",
330 .start = INT_McBSP3RX,
331 .flags = IORESOURCE_IRQ,
332 },
333 {
334 .name = "tx",
335 .start = INT_McBSP3TX,
336 .flags = IORESOURCE_IRQ,
337 },
338 {
339 .name = "rx",
340 .start = OMAP_DMA_MCBSP3_RX,
341 .flags = IORESOURCE_DMA,
342 },
343 {
344 .name = "tx",
345 .start = OMAP_DMA_MCBSP3_TX,
346 .flags = IORESOURCE_DMA,
347 },
348 },
349};
350
Paul Walmsleye7916742011-03-04 22:36:46 +0000351#define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0]
352
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300353static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
354 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300355 .ops = &omap1_mcbsp_ops,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300356 },
357 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300358 .ops = &omap1_mcbsp_ops,
359 },
360 {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300361 .ops = &omap1_mcbsp_ops,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300362 },
363};
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800364#define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1])
365#define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300366#else
Paul Walmsleye7916742011-03-04 22:36:46 +0000367#define omap16xx_mcbsp_res_0 NULL
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300368#define omap16xx_mcbsp_pdata NULL
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800369#define OMAP16XX_MCBSP_RES_SZ 0
370#define OMAP16XX_MCBSP_COUNT 0
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300371#endif
372
Jarkko Nikula40246e02011-09-26 10:45:38 +0300373static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
374 struct omap_mcbsp_platform_data *config, int size)
375{
376 int i;
377
378 omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
379 GFP_KERNEL);
380 if (!omap_mcbsp_devices) {
381 printk(KERN_ERR "Could not register McBSP devices\n");
382 return;
383 }
384
385 for (i = 0; i < size; i++) {
386 struct platform_device *new_mcbsp;
387 int ret;
388
389 new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
390 if (!new_mcbsp)
391 continue;
392 platform_device_add_resources(new_mcbsp, &res[i * res_count],
393 res_count);
Jarkko Nikulacdc715142011-09-26 10:45:39 +0300394 config[i].reg_size = 2;
395 config[i].reg_step = 2;
Jarkko Nikula40246e02011-09-26 10:45:38 +0300396 new_mcbsp->dev.platform_data = &config[i];
397 ret = platform_device_add(new_mcbsp);
398 if (ret) {
399 platform_device_put(new_mcbsp);
400 continue;
401 }
402 omap_mcbsp_devices[i] = new_mcbsp;
403 }
404}
405
Aaro Koskinene6f16822010-11-18 19:59:47 +0200406static int __init omap1_mcbsp_init(void)
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300407{
Tony Lindgren7f9187c2010-12-10 09:46:24 -0800408 if (!cpu_class_is_omap1())
409 return -ENODEV;
410
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800411 if (cpu_is_omap7xx())
412 omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
413 else if (cpu_is_omap15xx())
414 omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
415 else if (cpu_is_omap16xx())
416 omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
Chandra Shekharb4b58f52008-10-08 10:01:39 +0300417
418 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
419 GFP_KERNEL);
420 if (!mcbsp_ptr)
421 return -ENOMEM;
422
Alistair Buxtonbf1cb7e2009-09-22 06:49:35 +0100423 if (cpu_is_omap7xx())
Paul Walmsleye7916742011-03-04 22:36:46 +0000424 omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800425 OMAP7XX_MCBSP_RES_SZ,
426 omap7xx_mcbsp_pdata,
427 OMAP7XX_MCBSP_COUNT);
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300428
429 if (cpu_is_omap15xx())
Paul Walmsleye7916742011-03-04 22:36:46 +0000430 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800431 OMAP15XX_MCBSP_RES_SZ,
432 omap15xx_mcbsp_pdata,
433 OMAP15XX_MCBSP_COUNT);
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300434
435 if (cpu_is_omap16xx())
Paul Walmsleye7916742011-03-04 22:36:46 +0000436 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
Kishon Vijay Abraham I3cf32bb2011-02-24 12:51:45 -0800437 OMAP16XX_MCBSP_RES_SZ,
438 omap16xx_mcbsp_pdata,
439 OMAP16XX_MCBSP_COUNT);
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300440
441 return omap_mcbsp_init();
442}
443
444arch_initcall(omap1_mcbsp_init);