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