xref: /openbmc/linux/arch/arm/mach-omap1/mcbsp.c (revision 31af04cd)
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);
447