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 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  
omap_mcbsp_register_board_cfg(struct resource * res,int res_count,struct omap_mcbsp_platform_data * config,int size)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  
omap1_mcbsp_init(void)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