xref: /linux/arch/arm/mach-omap1/mcbsp.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
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 struct resource omap15xx_mcbsp_res[][6] = {
93 	{
94 		{
95 			.start = OMAP1510_MCBSP1_BASE,
96 			.end   = OMAP1510_MCBSP1_BASE + SZ_256,
97 			.flags = IORESOURCE_MEM,
98 		},
99 		{
100 			.name  = "rx",
101 			.start = INT_McBSP1RX,
102 			.flags = IORESOURCE_IRQ,
103 		},
104 		{
105 			.name  = "tx",
106 			.start = INT_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 = OMAP1510_MCBSP2_BASE,
123 			.end   = OMAP1510_MCBSP2_BASE + SZ_256,
124 			.flags = IORESOURCE_MEM,
125 		},
126 		{
127 			.name  = "rx",
128 			.start = INT_1510_SPI_RX,
129 			.flags = IORESOURCE_IRQ,
130 		},
131 		{
132 			.name  = "tx",
133 			.start = INT_1510_SPI_TX,
134 			.flags = IORESOURCE_IRQ,
135 		},
136 		{
137 			.name  = "rx",
138 			.start = 17,
139 			.flags = IORESOURCE_DMA,
140 		},
141 		{
142 			.name  = "tx",
143 			.start = 16,
144 			.flags = IORESOURCE_DMA,
145 		},
146 	},
147 	{
148 		{
149 			.start = OMAP1510_MCBSP3_BASE,
150 			.end   = OMAP1510_MCBSP3_BASE + SZ_256,
151 			.flags = IORESOURCE_MEM,
152 		},
153 		{
154 			.name  = "rx",
155 			.start = INT_McBSP3RX,
156 			.flags = IORESOURCE_IRQ,
157 		},
158 		{
159 			.name  = "tx",
160 			.start = INT_McBSP3TX,
161 			.flags = IORESOURCE_IRQ,
162 		},
163 		{
164 			.name  = "rx",
165 			.start = 11,
166 			.flags = IORESOURCE_DMA,
167 		},
168 		{
169 			.name  = "tx",
170 			.start = 10,
171 			.flags = IORESOURCE_DMA,
172 		},
173 	},
174 };
175 
176 #define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
177 
178 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
179 	{
180 		.ops		= &omap1_mcbsp_ops,
181 	},
182 	{
183 		.ops		= &omap1_mcbsp_ops,
184 	},
185 	{
186 		.ops		= &omap1_mcbsp_ops,
187 	},
188 };
189 #define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
190 #define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
191 
192 struct resource omap16xx_mcbsp_res[][6] = {
193 	{
194 		{
195 			.start = OMAP1610_MCBSP1_BASE,
196 			.end   = OMAP1610_MCBSP1_BASE + SZ_256,
197 			.flags = IORESOURCE_MEM,
198 		},
199 		{
200 			.name  = "rx",
201 			.start = INT_McBSP1RX,
202 			.flags = IORESOURCE_IRQ,
203 		},
204 		{
205 			.name  = "tx",
206 			.start = INT_McBSP1TX,
207 			.flags = IORESOURCE_IRQ,
208 		},
209 		{
210 			.name  = "rx",
211 			.start = 9,
212 			.flags = IORESOURCE_DMA,
213 		},
214 		{
215 			.name  = "tx",
216 			.start = 8,
217 			.flags = IORESOURCE_DMA,
218 		},
219 	},
220 	{
221 		{
222 			.start = OMAP1610_MCBSP2_BASE,
223 			.end   = OMAP1610_MCBSP2_BASE + SZ_256,
224 			.flags = IORESOURCE_MEM,
225 		},
226 		{
227 			.name  = "rx",
228 			.start = INT_1610_McBSP2_RX,
229 			.flags = IORESOURCE_IRQ,
230 		},
231 		{
232 			.name  = "tx",
233 			.start = INT_1610_McBSP2_TX,
234 			.flags = IORESOURCE_IRQ,
235 		},
236 		{
237 			.name  = "rx",
238 			.start = 17,
239 			.flags = IORESOURCE_DMA,
240 		},
241 		{
242 			.name  = "tx",
243 			.start = 16,
244 			.flags = IORESOURCE_DMA,
245 		},
246 	},
247 	{
248 		{
249 			.start = OMAP1610_MCBSP3_BASE,
250 			.end   = OMAP1610_MCBSP3_BASE + SZ_256,
251 			.flags = IORESOURCE_MEM,
252 		},
253 		{
254 			.name  = "rx",
255 			.start = INT_McBSP3RX,
256 			.flags = IORESOURCE_IRQ,
257 		},
258 		{
259 			.name  = "tx",
260 			.start = INT_McBSP3TX,
261 			.flags = IORESOURCE_IRQ,
262 		},
263 		{
264 			.name  = "rx",
265 			.start = 11,
266 			.flags = IORESOURCE_DMA,
267 		},
268 		{
269 			.name  = "tx",
270 			.start = 10,
271 			.flags = IORESOURCE_DMA,
272 		},
273 	},
274 };
275 
276 #define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
277 
278 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
279 	{
280 		.ops		= &omap1_mcbsp_ops,
281 	},
282 	{
283 		.ops		= &omap1_mcbsp_ops,
284 	},
285 	{
286 		.ops		= &omap1_mcbsp_ops,
287 	},
288 };
289 #define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
290 #define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
291 
292 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
293 			struct omap_mcbsp_platform_data *config, int size)
294 {
295 	int i;
296 
297 	omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *),
298 				     GFP_KERNEL);
299 	if (!omap_mcbsp_devices) {
300 		printk(KERN_ERR "Could not register McBSP devices\n");
301 		return;
302 	}
303 
304 	for (i = 0; i < size; i++) {
305 		struct platform_device *new_mcbsp;
306 		int ret;
307 
308 		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
309 		if (!new_mcbsp)
310 			continue;
311 		platform_device_add_resources(new_mcbsp, &res[i * res_count],
312 					res_count);
313 		config[i].reg_size = 2;
314 		config[i].reg_step = 2;
315 		new_mcbsp->dev.platform_data = &config[i];
316 		ret = platform_device_add(new_mcbsp);
317 		if (ret) {
318 			platform_device_put(new_mcbsp);
319 			continue;
320 		}
321 		omap_mcbsp_devices[i] = new_mcbsp;
322 	}
323 }
324 
325 static int __init omap1_mcbsp_init(void)
326 {
327 	if (!cpu_class_is_omap1())
328 		return -ENODEV;
329 
330 	if (cpu_is_omap15xx())
331 		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
332 					OMAP15XX_MCBSP_RES_SZ,
333 					omap15xx_mcbsp_pdata,
334 					OMAP15XX_MCBSP_COUNT);
335 
336 	if (cpu_is_omap16xx())
337 		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
338 					OMAP16XX_MCBSP_RES_SZ,
339 					omap16xx_mcbsp_pdata,
340 					OMAP16XX_MCBSP_COUNT);
341 
342 	return 0;
343 }
344 
345 arch_initcall(omap1_mcbsp_init);
346