blob: acdc709901cd1ca55f231ac79be495e1e0e67dc7 [file] [log] [blame]
Eduardo Valentin78673bc2008-07-03 12:24:40 +03001/*
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
Russell Kinga09e64f2008-08-05 16:14:15 +010020#include <mach/dma.h>
Russell King80b02c12009-01-08 10:01:47 +000021#include <mach/irqs.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010022#include <mach/mux.h>
23#include <mach/cpu.h>
24#include <mach/mcbsp.h>
Eduardo Valentin78673bc2008-07-03 12:24:40 +030025
26struct mcbsp_internal_clk {
27 struct clk clk;
28 struct clk **childs;
29 int n_childs;
30};
31
Chandra Shekhar9c8e3a02008-10-08 10:01:40 +030032#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
Eduardo Valentin78673bc2008-07-03 12:24:40 +030033static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
34{
35 const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
36 int i;
37
38 mclk->n_childs = ARRAY_SIZE(clk_names);
39 mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
40 GFP_KERNEL);
41
42 for (i = 0; i < mclk->n_childs; i++) {
43 /* We fake a platform device to get correct device id */
44 struct platform_device pdev;
45
46 pdev.dev.bus = &platform_bus_type;
47 pdev.id = mclk->clk.id;
48 mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
49 if (IS_ERR(mclk->childs[i]))
50 printk(KERN_ERR "Could not get clock %s (%d).\n",
51 clk_names[i], mclk->clk.id);
52 }
53}
54
55static int omap_mcbsp_clk_enable(struct clk *clk)
56{
57 struct mcbsp_internal_clk *mclk = container_of(clk,
58 struct mcbsp_internal_clk, clk);
59 int i;
60
61 for (i = 0; i < mclk->n_childs; i++)
62 clk_enable(mclk->childs[i]);
63 return 0;
64}
65
66static void omap_mcbsp_clk_disable(struct clk *clk)
67{
68 struct mcbsp_internal_clk *mclk = container_of(clk,
69 struct mcbsp_internal_clk, clk);
70 int i;
71
72 for (i = 0; i < mclk->n_childs; i++)
73 clk_disable(mclk->childs[i]);
74}
75
76static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
77 {
78 .clk = {
79 .name = "mcbsp_clk",
80 .id = 1,
81 .enable = omap_mcbsp_clk_enable,
82 .disable = omap_mcbsp_clk_disable,
83 },
84 },
85 {
86 .clk = {
87 .name = "mcbsp_clk",
88 .id = 2,
89 .enable = omap_mcbsp_clk_enable,
90 .disable = omap_mcbsp_clk_disable,
91 },
92 },
Chandra Shekhar9c8e3a02008-10-08 10:01:40 +030093 {
94 .clk = {
95 .name = "mcbsp_clk",
96 .id = 3,
97 .enable = omap_mcbsp_clk_enable,
98 .disable = omap_mcbsp_clk_disable,
99 },
100 },
101 {
102 .clk = {
103 .name = "mcbsp_clk",
104 .id = 4,
105 .enable = omap_mcbsp_clk_enable,
106 .disable = omap_mcbsp_clk_disable,
107 },
108 },
109 {
110 .clk = {
111 .name = "mcbsp_clk",
112 .id = 5,
113 .enable = omap_mcbsp_clk_enable,
114 .disable = omap_mcbsp_clk_disable,
115 },
116 },
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300117};
118
119#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks)
120#else
121#define omap_mcbsp_clks_size 0
122static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
123static inline void omap_mcbsp_clk_init(struct clk *clk)
124{ }
125#endif
126
127static void omap2_mcbsp2_mux_setup(void)
128{
129 omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
130 omap_cfg_reg(R14_24XX_MCBSP2_FSX);
131 omap_cfg_reg(W15_24XX_MCBSP2_DR);
132 omap_cfg_reg(V15_24XX_MCBSP2_DX);
133 omap_cfg_reg(V14_24XX_GPIO117);
134 /*
135 * TODO: Need to add MUX settings for OMAP 2430 SDP
136 */
137}
138
139static void omap2_mcbsp_request(unsigned int id)
140{
141 if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
142 omap2_mcbsp2_mux_setup();
143}
144
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300145static struct omap_mcbsp_ops omap2_mcbsp_ops = {
146 .request = omap2_mcbsp_request,
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300147};
148
Jarkko Nikula05228c32008-10-08 10:01:40 +0300149#ifdef CONFIG_ARCH_OMAP2420
150static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300151 {
Russell King65846902008-09-03 23:46:18 +0100152 .phys_base = OMAP24XX_MCBSP1_BASE,
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300153 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
154 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
155 .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
156 .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
157 .ops = &omap2_mcbsp_ops,
158 .clk_name = "mcbsp_clk",
159 },
160 {
Russell King65846902008-09-03 23:46:18 +0100161 .phys_base = OMAP24XX_MCBSP2_BASE,
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300162 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
163 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
164 .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
165 .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
166 .ops = &omap2_mcbsp_ops,
167 .clk_name = "mcbsp_clk",
168 },
169};
Jarkko Nikula05228c32008-10-08 10:01:40 +0300170#define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata)
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300171#else
Jarkko Nikula05228c32008-10-08 10:01:40 +0300172#define omap2420_mcbsp_pdata NULL
173#define OMAP2420_MCBSP_PDATA_SZ 0
174#endif
175
176#ifdef CONFIG_ARCH_OMAP2430
177static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
178 {
179 .phys_base = OMAP24XX_MCBSP1_BASE,
180 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
181 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
182 .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
183 .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
184 .ops = &omap2_mcbsp_ops,
185 .clk_name = "mcbsp_clk",
186 },
187 {
188 .phys_base = OMAP24XX_MCBSP2_BASE,
189 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
190 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
191 .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
192 .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
193 .ops = &omap2_mcbsp_ops,
194 .clk_name = "mcbsp_clk",
195 },
196 {
197 .phys_base = OMAP2430_MCBSP3_BASE,
198 .dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX,
199 .dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX,
200 .rx_irq = INT_24XX_MCBSP3_IRQ_RX,
201 .tx_irq = INT_24XX_MCBSP3_IRQ_TX,
202 .ops = &omap2_mcbsp_ops,
203 .clk_name = "mcbsp_clk",
204 },
205 {
206 .phys_base = OMAP2430_MCBSP4_BASE,
207 .dma_rx_sync = OMAP24XX_DMA_MCBSP4_RX,
208 .dma_tx_sync = OMAP24XX_DMA_MCBSP4_TX,
209 .rx_irq = INT_24XX_MCBSP4_IRQ_RX,
210 .tx_irq = INT_24XX_MCBSP4_IRQ_TX,
211 .ops = &omap2_mcbsp_ops,
212 .clk_name = "mcbsp_clk",
213 },
214 {
215 .phys_base = OMAP2430_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 .ops = &omap2_mcbsp_ops,
221 .clk_name = "mcbsp_clk",
222 },
223};
224#define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata)
225#else
226#define omap2430_mcbsp_pdata NULL
227#define OMAP2430_MCBSP_PDATA_SZ 0
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300228#endif
229
230#ifdef CONFIG_ARCH_OMAP34XX
231static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
232 {
Russell King65846902008-09-03 23:46:18 +0100233 .phys_base = OMAP34XX_MCBSP1_BASE,
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300234 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
235 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
236 .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
237 .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
238 .ops = &omap2_mcbsp_ops,
239 .clk_name = "mcbsp_clk",
240 },
241 {
Russell King65846902008-09-03 23:46:18 +0100242 .phys_base = OMAP34XX_MCBSP2_BASE,
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300243 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
244 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
245 .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
246 .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
247 .ops = &omap2_mcbsp_ops,
248 .clk_name = "mcbsp_clk",
249 },
Chandra Shekhar9c8e3a02008-10-08 10:01:40 +0300250 {
251 .phys_base = OMAP34XX_MCBSP3_BASE,
252 .dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX,
253 .dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX,
254 .rx_irq = INT_24XX_MCBSP3_IRQ_RX,
255 .tx_irq = INT_24XX_MCBSP3_IRQ_TX,
256 .ops = &omap2_mcbsp_ops,
257 .clk_name = "mcbsp_clk",
258 },
259 {
260 .phys_base = OMAP34XX_MCBSP4_BASE,
261 .dma_rx_sync = OMAP24XX_DMA_MCBSP4_RX,
262 .dma_tx_sync = OMAP24XX_DMA_MCBSP4_TX,
263 .rx_irq = INT_24XX_MCBSP4_IRQ_RX,
264 .tx_irq = INT_24XX_MCBSP4_IRQ_TX,
265 .ops = &omap2_mcbsp_ops,
266 .clk_name = "mcbsp_clk",
267 },
268 {
269 .phys_base = OMAP34XX_MCBSP5_BASE,
270 .dma_rx_sync = OMAP24XX_DMA_MCBSP5_RX,
271 .dma_tx_sync = OMAP24XX_DMA_MCBSP5_TX,
272 .rx_irq = INT_24XX_MCBSP5_IRQ_RX,
273 .tx_irq = INT_24XX_MCBSP5_IRQ_TX,
274 .ops = &omap2_mcbsp_ops,
275 .clk_name = "mcbsp_clk",
276 },
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300277};
278#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)
279#else
280#define omap34xx_mcbsp_pdata NULL
281#define OMAP34XX_MCBSP_PDATA_SZ 0
282#endif
283
Chandra Shekharb4b58f52008-10-08 10:01:39 +0300284static int __init omap2_mcbsp_init(void)
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300285{
286 int i;
287
288 for (i = 0; i < omap_mcbsp_clks_size; i++) {
289 /* Once we call clk_get inside init, we do not register it */
290 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
291 clk_register(&omap_mcbsp_clks[i].clk);
292 }
293
Jarkko Nikula05228c32008-10-08 10:01:40 +0300294 if (cpu_is_omap2420())
295 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
296 if (cpu_is_omap2430())
297 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
Chandra Shekharb4b58f52008-10-08 10:01:39 +0300298 if (cpu_is_omap34xx())
299 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
300
301 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
302 GFP_KERNEL);
303 if (!mcbsp_ptr)
304 return -ENOMEM;
305
Jarkko Nikula05228c32008-10-08 10:01:40 +0300306 if (cpu_is_omap2420())
307 omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
308 OMAP2420_MCBSP_PDATA_SZ);
309 if (cpu_is_omap2430())
310 omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
311 OMAP2430_MCBSP_PDATA_SZ);
Chandra Shekhar9c8e3a02008-10-08 10:01:40 +0300312 if (cpu_is_omap34xx())
313 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
314 OMAP34XX_MCBSP_PDATA_SZ);
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300315
Eduardo Valentin78673bc2008-07-03 12:24:40 +0300316 return omap_mcbsp_init();
317}
318arch_initcall(omap2_mcbsp_init);