Merge branch 'devel'
[sfrench/cifs-2.6.git] / arch / arm / mach-omap2 / mcbsp.c
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
20 #include <mach/dma.h>
21 #include <mach/irqs.h>
22 #include <mach/mux.h>
23 #include <mach/cpu.h>
24 #include <mach/mcbsp.h>
25
26 struct mcbsp_internal_clk {
27         struct clk clk;
28         struct clk **childs;
29         int n_childs;
30 };
31
32 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
33 static 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
55 static 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
66 static 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
76 static 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         },
93         {
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         },
117 };
118
119 #define omap_mcbsp_clks_size    ARRAY_SIZE(omap_mcbsp_clks)
120 #else
121 #define omap_mcbsp_clks_size    0
122 static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
123 static inline void omap_mcbsp_clk_init(struct clk *clk)
124 { }
125 #endif
126
127 static 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
139 static void omap2_mcbsp_request(unsigned int id)
140 {
141         if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
142                 omap2_mcbsp2_mux_setup();
143 }
144
145 static struct omap_mcbsp_ops omap2_mcbsp_ops = {
146         .request        = omap2_mcbsp_request,
147 };
148
149 #ifdef CONFIG_ARCH_OMAP2420
150 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
151         {
152                 .phys_base      = OMAP24XX_MCBSP1_BASE,
153                 .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         {
161                 .phys_base      = OMAP24XX_MCBSP2_BASE,
162                 .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 };
170 #define OMAP2420_MCBSP_PDATA_SZ         ARRAY_SIZE(omap2420_mcbsp_pdata)
171 #else
172 #define omap2420_mcbsp_pdata            NULL
173 #define OMAP2420_MCBSP_PDATA_SZ         0
174 #endif
175
176 #ifdef CONFIG_ARCH_OMAP2430
177 static 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
228 #endif
229
230 #ifdef CONFIG_ARCH_OMAP34XX
231 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
232         {
233                 .phys_base      = OMAP34XX_MCBSP1_BASE,
234                 .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         {
242                 .phys_base      = OMAP34XX_MCBSP2_BASE,
243                 .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         },
250         {
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         },
277 };
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
284 static int __init omap2_mcbsp_init(void)
285 {
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
294         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;
298         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
306         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);
312         if (cpu_is_omap34xx())
313                 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
314                                                 OMAP34XX_MCBSP_PDATA_SZ);
315
316         return omap_mcbsp_init();
317 }
318 arch_initcall(omap2_mcbsp_init);