PageRenderTime 60ms CodeModel.GetById 13ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/arm/mach-omap1/mcbsp.c

https://github.com/AICP/kernel_asus_grouper
C | 410 lines | 366 code | 24 blank | 20 comment | 27 complexity | d9f1585979959eb786528b38b8ae9970 MD5 | raw file
  1/*
  2 * linux/arch/arm/mach-omap1/mcbsp.c
  3 *
  4 * Copyright (C) 2008 Instituto Nokia de Tecnologia
  5 * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
  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 <mach/irqs.h>
 23#include <plat/dma.h>
 24#include <plat/mux.h>
 25#include <plat/cpu.h>
 26#include <plat/mcbsp.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;
 34
 35static 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_enable(api_clk);
 47				clk_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
 60static 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(api_clk);
 66				clk_put(api_clk);
 67			}
 68			if (!IS_ERR(dsp_clk)) {
 69				clk_disable(dsp_clk);
 70				clk_put(dsp_clk);
 71			}
 72		}
 73	}
 74}
 75
 76static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 77	.request	= omap1_mcbsp_request,
 78	.free		= omap1_mcbsp_free,
 79};
 80
 81#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 82struct resource omap7xx_mcbsp_res[][6] = {
 83	{
 84		{
 85			.start = OMAP7XX_MCBSP1_BASE,
 86			.end   = OMAP7XX_MCBSP1_BASE + SZ_256,
 87			.flags = IORESOURCE_MEM,
 88		},
 89		{
 90			.name  = "rx",
 91			.start = INT_7XX_McBSP1RX,
 92			.flags = IORESOURCE_IRQ,
 93		},
 94		{
 95			.name  = "tx",
 96			.start = INT_7XX_McBSP1TX,
 97			.flags = IORESOURCE_IRQ,
 98		},
 99		{
100			.name  = "rx",
101			.start = OMAP_DMA_MCBSP1_RX,
102			.flags = IORESOURCE_DMA,
103		},
104		{
105			.name  = "tx",
106			.start = OMAP_DMA_MCBSP1_TX,
107			.flags = IORESOURCE_DMA,
108		},
109	},
110	{
111		{
112			.start = OMAP7XX_MCBSP2_BASE,
113			.end   = OMAP7XX_MCBSP2_BASE + SZ_256,
114			.flags = IORESOURCE_MEM,
115		},
116		{
117			.name  = "rx",
118			.start = INT_7XX_McBSP2RX,
119			.flags = IORESOURCE_IRQ,
120		},
121		{
122			.name  = "tx",
123			.start = INT_7XX_McBSP2TX,
124			.flags = IORESOURCE_IRQ,
125		},
126		{
127			.name  = "rx",
128			.start = OMAP_DMA_MCBSP3_RX,
129			.flags = IORESOURCE_DMA,
130		},
131		{
132			.name  = "tx",
133			.start = OMAP_DMA_MCBSP3_TX,
134			.flags = IORESOURCE_DMA,
135		},
136	},
137};
138
139#define omap7xx_mcbsp_res_0		omap7xx_mcbsp_res[0]
140
141static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
142	{
143		.ops		= &omap1_mcbsp_ops,
144	},
145	{
146		.ops		= &omap1_mcbsp_ops,
147	},
148};
149#define OMAP7XX_MCBSP_RES_SZ		ARRAY_SIZE(omap7xx_mcbsp_res[1])
150#define OMAP7XX_MCBSP_COUNT		ARRAY_SIZE(omap7xx_mcbsp_res)
151#else
152#define omap7xx_mcbsp_res_0		NULL
153#define omap7xx_mcbsp_pdata		NULL
154#define OMAP7XX_MCBSP_RES_SZ		0
155#define OMAP7XX_MCBSP_COUNT		0
156#endif
157
158#ifdef CONFIG_ARCH_OMAP15XX
159struct resource omap15xx_mcbsp_res[][6] = {
160	{
161		{
162			.start = OMAP1510_MCBSP1_BASE,
163			.end   = OMAP1510_MCBSP1_BASE + SZ_256,
164			.flags = IORESOURCE_MEM,
165		},
166		{
167			.name  = "rx",
168			.start = INT_McBSP1RX,
169			.flags = IORESOURCE_IRQ,
170		},
171		{
172			.name  = "tx",
173			.start = INT_McBSP1TX,
174			.flags = IORESOURCE_IRQ,
175		},
176		{
177			.name  = "rx",
178			.start = OMAP_DMA_MCBSP1_RX,
179			.flags = IORESOURCE_DMA,
180		},
181		{
182			.name  = "tx",
183			.start = OMAP_DMA_MCBSP1_TX,
184			.flags = IORESOURCE_DMA,
185		},
186	},
187	{
188		{
189			.start = OMAP1510_MCBSP2_BASE,
190			.end   = OMAP1510_MCBSP2_BASE + SZ_256,
191			.flags = IORESOURCE_MEM,
192		},
193		{
194			.name  = "rx",
195			.start = INT_1510_SPI_RX,
196			.flags = IORESOURCE_IRQ,
197		},
198		{
199			.name  = "tx",
200			.start = INT_1510_SPI_TX,
201			.flags = IORESOURCE_IRQ,
202		},
203		{
204			.name  = "rx",
205			.start = OMAP_DMA_MCBSP2_RX,
206			.flags = IORESOURCE_DMA,
207		},
208		{
209			.name  = "tx",
210			.start = OMAP_DMA_MCBSP2_TX,
211			.flags = IORESOURCE_DMA,
212		},
213	},
214	{
215		{
216			.start = OMAP1510_MCBSP3_BASE,
217			.end   = OMAP1510_MCBSP3_BASE + SZ_256,
218			.flags = IORESOURCE_MEM,
219		},
220		{
221			.name  = "rx",
222			.start = INT_McBSP3RX,
223			.flags = IORESOURCE_IRQ,
224		},
225		{
226			.name  = "tx",
227			.start = INT_McBSP3TX,
228			.flags = IORESOURCE_IRQ,
229		},
230		{
231			.name  = "rx",
232			.start = OMAP_DMA_MCBSP3_RX,
233			.flags = IORESOURCE_DMA,
234		},
235		{
236			.name  = "tx",
237			.start = OMAP_DMA_MCBSP3_TX,
238			.flags = IORESOURCE_DMA,
239		},
240	},
241};
242
243#define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
244
245static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
246	{
247		.ops		= &omap1_mcbsp_ops,
248	},
249	{
250		.ops		= &omap1_mcbsp_ops,
251	},
252	{
253		.ops		= &omap1_mcbsp_ops,
254	},
255};
256#define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
257#define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
258#else
259#define omap15xx_mcbsp_res_0		NULL
260#define omap15xx_mcbsp_pdata		NULL
261#define OMAP15XX_MCBSP_RES_SZ		0
262#define OMAP15XX_MCBSP_COUNT		0
263#endif
264
265#ifdef CONFIG_ARCH_OMAP16XX
266struct resource omap16xx_mcbsp_res[][6] = {
267	{
268		{
269			.start = OMAP1610_MCBSP1_BASE,
270			.end   = OMAP1610_MCBSP1_BASE + SZ_256,
271			.flags = IORESOURCE_MEM,
272		},
273		{
274			.name  = "rx",
275			.start = INT_McBSP1RX,
276			.flags = IORESOURCE_IRQ,
277		},
278		{
279			.name  = "tx",
280			.start = INT_McBSP1TX,
281			.flags = IORESOURCE_IRQ,
282		},
283		{
284			.name  = "rx",
285			.start = OMAP_DMA_MCBSP1_RX,
286			.flags = IORESOURCE_DMA,
287		},
288		{
289			.name  = "tx",
290			.start = OMAP_DMA_MCBSP1_TX,
291			.flags = IORESOURCE_DMA,
292		},
293	},
294	{
295		{
296			.start = OMAP1610_MCBSP2_BASE,
297			.end   = OMAP1610_MCBSP2_BASE + SZ_256,
298			.flags = IORESOURCE_MEM,
299		},
300		{
301			.name  = "rx",
302			.start = INT_1610_McBSP2_RX,
303			.flags = IORESOURCE_IRQ,
304		},
305		{
306			.name  = "tx",
307			.start = INT_1610_McBSP2_TX,
308			.flags = IORESOURCE_IRQ,
309		},
310		{
311			.name  = "rx",
312			.start = OMAP_DMA_MCBSP2_RX,
313			.flags = IORESOURCE_DMA,
314		},
315		{
316			.name  = "tx",
317			.start = OMAP_DMA_MCBSP2_TX,
318			.flags = IORESOURCE_DMA,
319		},
320	},
321	{
322		{
323			.start = OMAP1610_MCBSP3_BASE,
324			.end   = OMAP1610_MCBSP3_BASE + SZ_256,
325			.flags = IORESOURCE_MEM,
326		},
327		{
328			.name  = "rx",
329			.start = INT_McBSP3RX,
330			.flags = IORESOURCE_IRQ,
331		},
332		{
333			.name  = "tx",
334			.start = INT_McBSP3TX,
335			.flags = IORESOURCE_IRQ,
336		},
337		{
338			.name  = "rx",
339			.start = OMAP_DMA_MCBSP3_RX,
340			.flags = IORESOURCE_DMA,
341		},
342		{
343			.name  = "tx",
344			.start = OMAP_DMA_MCBSP3_TX,
345			.flags = IORESOURCE_DMA,
346		},
347	},
348};
349
350#define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
351
352static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
353	{
354		.ops		= &omap1_mcbsp_ops,
355	},
356	{
357		.ops		= &omap1_mcbsp_ops,
358	},
359	{
360		.ops		= &omap1_mcbsp_ops,
361	},
362};
363#define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
364#define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
365#else
366#define omap16xx_mcbsp_res_0		NULL
367#define omap16xx_mcbsp_pdata		NULL
368#define OMAP16XX_MCBSP_RES_SZ		0
369#define OMAP16XX_MCBSP_COUNT		0
370#endif
371
372static int __init omap1_mcbsp_init(void)
373{
374	if (!cpu_class_is_omap1())
375		return -ENODEV;
376
377	if (cpu_is_omap7xx())
378		omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
379	else if (cpu_is_omap15xx())
380		omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
381	else if (cpu_is_omap16xx())
382		omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
383
384	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
385								GFP_KERNEL);
386	if (!mcbsp_ptr)
387		return -ENOMEM;
388
389	if (cpu_is_omap7xx())
390		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
391					OMAP7XX_MCBSP_RES_SZ,
392					omap7xx_mcbsp_pdata,
393					OMAP7XX_MCBSP_COUNT);
394
395	if (cpu_is_omap15xx())
396		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
397					OMAP15XX_MCBSP_RES_SZ,
398					omap15xx_mcbsp_pdata,
399					OMAP15XX_MCBSP_COUNT);
400
401	if (cpu_is_omap16xx())
402		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
403					OMAP16XX_MCBSP_RES_SZ,
404					omap16xx_mcbsp_pdata,
405					OMAP16XX_MCBSP_COUNT);
406
407	return omap_mcbsp_init();
408}
409
410arch_initcall(omap1_mcbsp_init);