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