xref: /openbmc/linux/arch/arm/mach-omap2/mcbsp.c (revision 4800cd83)
1 /*
2  * linux/arch/arm/mach-omap2/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/module.h>
14 #include <linux/init.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
17 #include <linux/io.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 
21 #include <mach/irqs.h>
22 #include <plat/dma.h>
23 #include <plat/cpu.h>
24 #include <plat/mcbsp.h>
25 
26 #include "control.h"
27 
28 
29 /* McBSP internal signal muxing functions */
30 
31 void omap2_mcbsp1_mux_clkr_src(u8 mux)
32 {
33 	u32 v;
34 
35 	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
36 	if (mux == CLKR_SRC_CLKR)
37 		v &= ~OMAP2_MCBSP1_CLKR_MASK;
38 	else if (mux == CLKR_SRC_CLKX)
39 		v |= OMAP2_MCBSP1_CLKR_MASK;
40 	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
41 }
42 EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
43 
44 void omap2_mcbsp1_mux_fsr_src(u8 mux)
45 {
46 	u32 v;
47 
48 	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
49 	if (mux == FSR_SRC_FSR)
50 		v &= ~OMAP2_MCBSP1_FSR_MASK;
51 	else if (mux == FSR_SRC_FSX)
52 		v |= OMAP2_MCBSP1_FSR_MASK;
53 	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
54 }
55 EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
56 
57 /* McBSP CLKS source switching function */
58 
59 int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
60 {
61 	struct omap_mcbsp *mcbsp;
62 	struct clk *fck_src;
63 	char *fck_src_name;
64 	int r;
65 
66 	if (!omap_mcbsp_check_valid_id(id)) {
67 		pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
68 		return -EINVAL;
69 	}
70 	mcbsp = id_to_mcbsp_ptr(id);
71 
72 	if (fck_src_id == MCBSP_CLKS_PAD_SRC)
73 		fck_src_name = "pad_fck";
74 	else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
75 		fck_src_name = "prcm_fck";
76 	else
77 		return -EINVAL;
78 
79 	fck_src = clk_get(mcbsp->dev, fck_src_name);
80 	if (IS_ERR_OR_NULL(fck_src)) {
81 		pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
82 		       fck_src_name);
83 		return -EINVAL;
84 	}
85 
86 	clk_disable(mcbsp->fclk);
87 
88 	r = clk_set_parent(mcbsp->fclk, fck_src);
89 	if (IS_ERR_VALUE(r)) {
90 		pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
91 		       "clks", fck_src_name);
92 		clk_put(fck_src);
93 		return -EINVAL;
94 	}
95 
96 	clk_enable(mcbsp->fclk);
97 
98 	clk_put(fck_src);
99 
100 	return 0;
101 }
102 EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
103 
104 
105 /* Platform data */
106 
107 #ifdef CONFIG_ARCH_OMAP2420
108 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
109 	{
110 		.phys_base	= OMAP24XX_MCBSP1_BASE,
111 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
112 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
113 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
114 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
115 	},
116 	{
117 		.phys_base	= OMAP24XX_MCBSP2_BASE,
118 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
119 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
120 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
121 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
122 	},
123 };
124 #define OMAP2420_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2420_mcbsp_pdata)
125 #define OMAP2420_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
126 #else
127 #define omap2420_mcbsp_pdata		NULL
128 #define OMAP2420_MCBSP_PDATA_SZ		0
129 #define OMAP2420_MCBSP_REG_NUM		0
130 #endif
131 
132 #ifdef CONFIG_ARCH_OMAP2430
133 static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
134 	{
135 		.phys_base	= OMAP24XX_MCBSP1_BASE,
136 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
137 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
138 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
139 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
140 	},
141 	{
142 		.phys_base	= OMAP24XX_MCBSP2_BASE,
143 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
144 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
145 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
146 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
147 	},
148 	{
149 		.phys_base	= OMAP2430_MCBSP3_BASE,
150 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
151 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
152 		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
153 		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
154 	},
155 	{
156 		.phys_base	= OMAP2430_MCBSP4_BASE,
157 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
158 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
159 		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
160 		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
161 	},
162 	{
163 		.phys_base	= OMAP2430_MCBSP5_BASE,
164 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
165 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
166 		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
167 		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
168 	},
169 };
170 #define OMAP2430_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2430_mcbsp_pdata)
171 #define OMAP2430_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
172 #else
173 #define omap2430_mcbsp_pdata		NULL
174 #define OMAP2430_MCBSP_PDATA_SZ		0
175 #define OMAP2430_MCBSP_REG_NUM		0
176 #endif
177 
178 #ifdef CONFIG_ARCH_OMAP3
179 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
180 	{
181 		.phys_base	= OMAP34XX_MCBSP1_BASE,
182 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
183 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
184 		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
185 		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
186 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
187 	},
188 	{
189 		.phys_base	= OMAP34XX_MCBSP2_BASE,
190 		.phys_base_st	= OMAP34XX_MCBSP2_ST_BASE,
191 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
192 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
193 		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
194 		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
195 		.buffer_size	= 0x500, /* The FIFO has 1024 + 256 locations */
196 	},
197 	{
198 		.phys_base	= OMAP34XX_MCBSP3_BASE,
199 		.phys_base_st	= OMAP34XX_MCBSP3_ST_BASE,
200 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
201 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
202 		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
203 		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
204 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
205 	},
206 	{
207 		.phys_base	= OMAP34XX_MCBSP4_BASE,
208 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
209 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
210 		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
211 		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
212 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
213 	},
214 	{
215 		.phys_base	= OMAP34XX_MCBSP5_BASE,
216 		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
217 		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
218 		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
219 		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
220 		.buffer_size	= 0x80, /* The FIFO has 128 locations */
221 	},
222 };
223 #define OMAP34XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap34xx_mcbsp_pdata)
224 #define OMAP34XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
225 #else
226 #define omap34xx_mcbsp_pdata		NULL
227 #define OMAP34XX_MCBSP_PDATA_SZ		0
228 #define OMAP34XX_MCBSP_REG_NUM		0
229 #endif
230 
231 static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
232 	{
233 		.phys_base      = OMAP44XX_MCBSP1_BASE,
234 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP1_RX,
235 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP1_TX,
236 		.tx_irq         = OMAP44XX_IRQ_MCBSP1,
237 	},
238 	{
239 		.phys_base      = OMAP44XX_MCBSP2_BASE,
240 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP2_RX,
241 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP2_TX,
242 		.tx_irq         = OMAP44XX_IRQ_MCBSP2,
243 	},
244 	{
245 		.phys_base      = OMAP44XX_MCBSP3_BASE,
246 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP3_RX,
247 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP3_TX,
248 		.tx_irq         = OMAP44XX_IRQ_MCBSP3,
249 	},
250 	{
251 		.phys_base      = OMAP44XX_MCBSP4_BASE,
252 		.dma_rx_sync    = OMAP44XX_DMA_MCBSP4_RX,
253 		.dma_tx_sync    = OMAP44XX_DMA_MCBSP4_TX,
254 		.tx_irq         = OMAP44XX_IRQ_MCBSP4,
255 	},
256 };
257 #define OMAP44XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap44xx_mcbsp_pdata)
258 #define OMAP44XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
259 
260 static int __init omap2_mcbsp_init(void)
261 {
262 	if (cpu_is_omap2420()) {
263 		omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
264 		omap_mcbsp_cache_size = OMAP2420_MCBSP_REG_NUM * sizeof(u16);
265 	} else if (cpu_is_omap2430()) {
266 		omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
267 		omap_mcbsp_cache_size = OMAP2430_MCBSP_REG_NUM * sizeof(u32);
268 	} else if (cpu_is_omap34xx()) {
269 		omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
270 		omap_mcbsp_cache_size = OMAP34XX_MCBSP_REG_NUM * sizeof(u32);
271 	} else if (cpu_is_omap44xx()) {
272 		omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ;
273 		omap_mcbsp_cache_size = OMAP44XX_MCBSP_REG_NUM * sizeof(u32);
274 	}
275 
276 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
277 								GFP_KERNEL);
278 	if (!mcbsp_ptr)
279 		return -ENOMEM;
280 
281 	if (cpu_is_omap2420())
282 		omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
283 						OMAP2420_MCBSP_PDATA_SZ);
284 	if (cpu_is_omap2430())
285 		omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
286 						OMAP2430_MCBSP_PDATA_SZ);
287 	if (cpu_is_omap34xx())
288 		omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
289 						OMAP34XX_MCBSP_PDATA_SZ);
290 	if (cpu_is_omap44xx())
291 		omap_mcbsp_register_board_cfg(omap44xx_mcbsp_pdata,
292 						OMAP44XX_MCBSP_PDATA_SZ);
293 
294 	return omap_mcbsp_init();
295 }
296 arch_initcall(omap2_mcbsp_init);
297