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 
omap1_mcbsp_request(unsigned int id)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 
omap1_mcbsp_free(unsigned int id)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 struct resource omap7xx_mcbsp_res[][6] = {
93 	{
94 		{
95 			.start = OMAP7XX_MCBSP1_BASE,
96 			.end   = OMAP7XX_MCBSP1_BASE + SZ_256,
97 			.flags = IORESOURCE_MEM,
98 		},
99 		{
100 			.name  = "rx",
101 			.start = INT_7XX_McBSP1RX,
102 			.flags = IORESOURCE_IRQ,
103 		},
104 		{
105 			.name  = "tx",
106 			.start = INT_7XX_McBSP1TX,
107 			.flags = IORESOURCE_IRQ,
108 		},
109 		{
110 			.name  = "rx",
111 			.start = 9,
112 			.flags = IORESOURCE_DMA,
113 		},
114 		{
115 			.name  = "tx",
116 			.start = 8,
117 			.flags = IORESOURCE_DMA,
118 		},
119 	},
120 	{
121 		{
122 			.start = OMAP7XX_MCBSP2_BASE,
123 			.end   = OMAP7XX_MCBSP2_BASE + SZ_256,
124 			.flags = IORESOURCE_MEM,
125 		},
126 		{
127 			.name  = "rx",
128 			.start = INT_7XX_McBSP2RX,
129 			.flags = IORESOURCE_IRQ,
130 		},
131 		{
132 			.name  = "tx",
133 			.start = INT_7XX_McBSP2TX,
134 			.flags = IORESOURCE_IRQ,
135 		},
136 		{
137 			.name  = "rx",
138 			.start = 11,
139 			.flags = IORESOURCE_DMA,
140 		},
141 		{
142 			.name  = "tx",
143 			.start = 10,
144 			.flags = IORESOURCE_DMA,
145 		},
146 	},
147 };
148 
149 #define omap7xx_mcbsp_res_0		omap7xx_mcbsp_res[0]
150 
151 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
152 	{
153 		.ops		= &omap1_mcbsp_ops,
154 	},
155 	{
156 		.ops		= &omap1_mcbsp_ops,
157 	},
158 };
159 #define OMAP7XX_MCBSP_RES_SZ		ARRAY_SIZE(omap7xx_mcbsp_res[1])
160 #define OMAP7XX_MCBSP_COUNT		ARRAY_SIZE(omap7xx_mcbsp_res)
161 
162 struct resource omap15xx_mcbsp_res[][6] = {
163 	{
164 		{
165 			.start = OMAP1510_MCBSP1_BASE,
166 			.end   = OMAP1510_MCBSP1_BASE + SZ_256,
167 			.flags = IORESOURCE_MEM,
168 		},
169 		{
170 			.name  = "rx",
171 			.start = INT_McBSP1RX,
172 			.flags = IORESOURCE_IRQ,
173 		},
174 		{
175 			.name  = "tx",
176 			.start = INT_McBSP1TX,
177 			.flags = IORESOURCE_IRQ,
178 		},
179 		{
180 			.name  = "rx",
181 			.start = 9,
182 			.flags = IORESOURCE_DMA,
183 		},
184 		{
185 			.name  = "tx",
186 			.start = 8,
187 			.flags = IORESOURCE_DMA,
188 		},
189 	},
190 	{
191 		{
192 			.start = OMAP1510_MCBSP2_BASE,
193 			.end   = OMAP1510_MCBSP2_BASE + SZ_256,
194 			.flags = IORESOURCE_MEM,
195 		},
196 		{
197 			.name  = "rx",
198 			.start = INT_1510_SPI_RX,
199 			.flags = IORESOURCE_IRQ,
200 		},
201 		{
202 			.name  = "tx",
203 			.start = INT_1510_SPI_TX,
204 			.flags = IORESOURCE_IRQ,
205 		},
206 		{
207 			.name  = "rx",
208 			.start = 17,
209 			.flags = IORESOURCE_DMA,
210 		},
211 		{
212 			.name  = "tx",
213 			.start = 16,
214 			.flags = IORESOURCE_DMA,
215 		},
216 	},
217 	{
218 		{
219 			.start = OMAP1510_MCBSP3_BASE,
220 			.end   = OMAP1510_MCBSP3_BASE + SZ_256,
221 			.flags = IORESOURCE_MEM,
222 		},
223 		{
224 			.name  = "rx",
225 			.start = INT_McBSP3RX,
226 			.flags = IORESOURCE_IRQ,
227 		},
228 		{
229 			.name  = "tx",
230 			.start = INT_McBSP3TX,
231 			.flags = IORESOURCE_IRQ,
232 		},
233 		{
234 			.name  = "rx",
235 			.start = 11,
236 			.flags = IORESOURCE_DMA,
237 		},
238 		{
239 			.name  = "tx",
240 			.start = 10,
241 			.flags = IORESOURCE_DMA,
242 		},
243 	},
244 };
245 
246 #define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
247 
248 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
249 	{
250 		.ops		= &omap1_mcbsp_ops,
251 	},
252 	{
253 		.ops		= &omap1_mcbsp_ops,
254 	},
255 	{
256 		.ops		= &omap1_mcbsp_ops,
257 	},
258 };
259 #define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
260 #define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
261 
262 struct resource omap16xx_mcbsp_res[][6] = {
263 	{
264 		{
265 			.start = OMAP1610_MCBSP1_BASE,
266 			.end   = OMAP1610_MCBSP1_BASE + SZ_256,
267 			.flags = IORESOURCE_MEM,
268 		},
269 		{
270 			.name  = "rx",
271 			.start = INT_McBSP1RX,
272 			.flags = IORESOURCE_IRQ,
273 		},
274 		{
275 			.name  = "tx",
276 			.start = INT_McBSP1TX,
277 			.flags = IORESOURCE_IRQ,
278 		},
279 		{
280 			.name  = "rx",
281 			.start = 9,
282 			.flags = IORESOURCE_DMA,
283 		},
284 		{
285 			.name  = "tx",
286 			.start = 8,
287 			.flags = IORESOURCE_DMA,
288 		},
289 	},
290 	{
291 		{
292 			.start = OMAP1610_MCBSP2_BASE,
293 			.end   = OMAP1610_MCBSP2_BASE + SZ_256,
294 			.flags = IORESOURCE_MEM,
295 		},
296 		{
297 			.name  = "rx",
298 			.start = INT_1610_McBSP2_RX,
299 			.flags = IORESOURCE_IRQ,
300 		},
301 		{
302 			.name  = "tx",
303 			.start = INT_1610_McBSP2_TX,
304 			.flags = IORESOURCE_IRQ,
305 		},
306 		{
307 			.name  = "rx",
308 			.start = 17,
309 			.flags = IORESOURCE_DMA,
310 		},
311 		{
312 			.name  = "tx",
313 			.start = 16,
314 			.flags = IORESOURCE_DMA,
315 		},
316 	},
317 	{
318 		{
319 			.start = OMAP1610_MCBSP3_BASE,
320 			.end   = OMAP1610_MCBSP3_BASE + SZ_256,
321 			.flags = IORESOURCE_MEM,
322 		},
323 		{
324 			.name  = "rx",
325 			.start = INT_McBSP3RX,
326 			.flags = IORESOURCE_IRQ,
327 		},
328 		{
329 			.name  = "tx",
330 			.start = INT_McBSP3TX,
331 			.flags = IORESOURCE_IRQ,
332 		},
333 		{
334 			.name  = "rx",
335 			.start = 11,
336 			.flags = IORESOURCE_DMA,
337 		},
338 		{
339 			.name  = "tx",
340 			.start = 10,
341 			.flags = IORESOURCE_DMA,
342 		},
343 	},
344 };
345 
346 #define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
347 
348 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
349 	{
350 		.ops		= &omap1_mcbsp_ops,
351 	},
352 	{
353 		.ops		= &omap1_mcbsp_ops,
354 	},
355 	{
356 		.ops		= &omap1_mcbsp_ops,
357 	},
358 };
359 #define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
360 #define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
361 
omap_mcbsp_register_board_cfg(struct resource * res,int res_count,struct omap_mcbsp_platform_data * config,int size)362 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
363 			struct omap_mcbsp_platform_data *config, int size)
364 {
365 	int i;
366 
367 	omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *),
368 				     GFP_KERNEL);
369 	if (!omap_mcbsp_devices) {
370 		printk(KERN_ERR "Could not register McBSP devices\n");
371 		return;
372 	}
373 
374 	for (i = 0; i < size; i++) {
375 		struct platform_device *new_mcbsp;
376 		int ret;
377 
378 		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
379 		if (!new_mcbsp)
380 			continue;
381 		platform_device_add_resources(new_mcbsp, &res[i * res_count],
382 					res_count);
383 		config[i].reg_size = 2;
384 		config[i].reg_step = 2;
385 		new_mcbsp->dev.platform_data = &config[i];
386 		ret = platform_device_add(new_mcbsp);
387 		if (ret) {
388 			platform_device_put(new_mcbsp);
389 			continue;
390 		}
391 		omap_mcbsp_devices[i] = new_mcbsp;
392 	}
393 }
394 
omap1_mcbsp_init(void)395 static int __init omap1_mcbsp_init(void)
396 {
397 	if (!cpu_class_is_omap1())
398 		return -ENODEV;
399 
400 	if (cpu_is_omap7xx())
401 		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
402 					OMAP7XX_MCBSP_RES_SZ,
403 					omap7xx_mcbsp_pdata,
404 					OMAP7XX_MCBSP_COUNT);
405 
406 	if (cpu_is_omap15xx())
407 		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
408 					OMAP15XX_MCBSP_RES_SZ,
409 					omap15xx_mcbsp_pdata,
410 					OMAP15XX_MCBSP_COUNT);
411 
412 	if (cpu_is_omap16xx())
413 		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
414 					OMAP16XX_MCBSP_RES_SZ,
415 					omap16xx_mcbsp_pdata,
416 					OMAP16XX_MCBSP_COUNT);
417 
418 	return 0;
419 }
420 
421 arch_initcall(omap1_mcbsp_init);
422