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