xref: /openbmc/linux/arch/arm/mach-omap1/mcbsp.c (revision e4c060db)
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 <plat-omap/dma-omap.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 #include "dma.h"
31 
32 #define DPS_RSTCT2_PER_EN	(1 << 0)
33 #define DSP_RSTCT2_WD_PER_EN	(1 << 1)
34 
35 static int dsp_use;
36 static struct clk *api_clk;
37 static struct clk *dsp_clk;
38 static struct platform_device **omap_mcbsp_devices;
39 
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 	 */
46 	if (id == 0 || id == 2) {
47 		if (dsp_use++ == 0) {
48 			api_clk = clk_get(NULL, "api_ck");
49 			dsp_clk = clk_get(NULL, "dsp_ck");
50 			if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
51 				clk_enable(api_clk);
52 				clk_enable(dsp_clk);
53 
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 		}
62 	}
63 }
64 
65 static void omap1_mcbsp_free(unsigned int id)
66 {
67 	if (id == 0 || id == 2) {
68 		if (--dsp_use == 0) {
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 	}
79 }
80 
81 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
82 	.request	= omap1_mcbsp_request,
83 	.free		= omap1_mcbsp_free,
84 };
85 
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 
97 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
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 
155 #define omap7xx_mcbsp_res_0		omap7xx_mcbsp_res[0]
156 
157 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
158 	{
159 		.ops		= &omap1_mcbsp_ops,
160 	},
161 	{
162 		.ops		= &omap1_mcbsp_ops,
163 	},
164 };
165 #define OMAP7XX_MCBSP_RES_SZ		ARRAY_SIZE(omap7xx_mcbsp_res[1])
166 #define OMAP7XX_MCBSP_COUNT		ARRAY_SIZE(omap7xx_mcbsp_res)
167 #else
168 #define omap7xx_mcbsp_res_0		NULL
169 #define omap7xx_mcbsp_pdata		NULL
170 #define OMAP7XX_MCBSP_RES_SZ		0
171 #define OMAP7XX_MCBSP_COUNT		0
172 #endif
173 
174 #ifdef CONFIG_ARCH_OMAP15XX
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 
259 #define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
260 
261 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
262 	{
263 		.ops		= &omap1_mcbsp_ops,
264 	},
265 	{
266 		.ops		= &omap1_mcbsp_ops,
267 	},
268 	{
269 		.ops		= &omap1_mcbsp_ops,
270 	},
271 };
272 #define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
273 #define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
274 #else
275 #define omap15xx_mcbsp_res_0		NULL
276 #define omap15xx_mcbsp_pdata		NULL
277 #define OMAP15XX_MCBSP_RES_SZ		0
278 #define OMAP15XX_MCBSP_COUNT		0
279 #endif
280 
281 #ifdef CONFIG_ARCH_OMAP16XX
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 
366 #define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
367 
368 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
369 	{
370 		.ops		= &omap1_mcbsp_ops,
371 	},
372 	{
373 		.ops		= &omap1_mcbsp_ops,
374 	},
375 	{
376 		.ops		= &omap1_mcbsp_ops,
377 	},
378 };
379 #define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
380 #define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
381 #else
382 #define omap16xx_mcbsp_res_0		NULL
383 #define omap16xx_mcbsp_pdata		NULL
384 #define OMAP16XX_MCBSP_RES_SZ		0
385 #define OMAP16XX_MCBSP_COUNT		0
386 #endif
387 
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);
409 		config[i].reg_size = 2;
410 		config[i].reg_step = 2;
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 
421 static int __init omap1_mcbsp_init(void)
422 {
423 	if (!cpu_class_is_omap1())
424 		return -ENODEV;
425 
426 	if (cpu_is_omap7xx())
427 		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
428 					OMAP7XX_MCBSP_RES_SZ,
429 					omap7xx_mcbsp_pdata,
430 					OMAP7XX_MCBSP_COUNT);
431 
432 	if (cpu_is_omap15xx())
433 		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
434 					OMAP15XX_MCBSP_RES_SZ,
435 					omap15xx_mcbsp_pdata,
436 					OMAP15XX_MCBSP_COUNT);
437 
438 	if (cpu_is_omap16xx())
439 		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
440 					OMAP16XX_MCBSP_RES_SZ,
441 					omap16xx_mcbsp_pdata,
442 					OMAP16XX_MCBSP_COUNT);
443 
444 	return 0;
445 }
446 
447 arch_initcall(omap1_mcbsp_init);
448