ARM: OMAP: Add support for OMAP2430 in McBSP
[pandora-kernel.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/mux.h>
22 #include <mach/cpu.h>
23 #include <mach/mcbsp.h>
24
25 struct mcbsp_internal_clk {
26         struct clk clk;
27         struct clk **childs;
28         int n_childs;
29 };
30
31 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
32 static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
33 {
34         const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
35         int i;
36
37         mclk->n_childs = ARRAY_SIZE(clk_names);
38         mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
39                                 GFP_KERNEL);
40
41         for (i = 0; i < mclk->n_childs; i++) {
42                 /* We fake a platform device to get correct device id */
43                 struct platform_device pdev;
44
45                 pdev.dev.bus = &platform_bus_type;
46                 pdev.id = mclk->clk.id;
47                 mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
48                 if (IS_ERR(mclk->childs[i]))
49                         printk(KERN_ERR "Could not get clock %s (%d).\n",
50                                 clk_names[i], mclk->clk.id);
51         }
52 }
53
54 static int omap_mcbsp_clk_enable(struct clk *clk)
55 {
56         struct mcbsp_internal_clk *mclk = container_of(clk,
57                                         struct mcbsp_internal_clk, clk);
58         int i;
59
60         for (i = 0; i < mclk->n_childs; i++)
61                 clk_enable(mclk->childs[i]);
62         return 0;
63 }
64
65 static void omap_mcbsp_clk_disable(struct clk *clk)
66 {
67         struct mcbsp_internal_clk *mclk = container_of(clk,
68                                         struct mcbsp_internal_clk, clk);
69         int i;
70
71         for (i = 0; i < mclk->n_childs; i++)
72                 clk_disable(mclk->childs[i]);
73 }
74
75 static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
76         {
77                 .clk = {
78                         .name           = "mcbsp_clk",
79                         .id             = 1,
80                         .enable         = omap_mcbsp_clk_enable,
81                         .disable        = omap_mcbsp_clk_disable,
82                 },
83         },
84         {
85                 .clk = {
86                         .name           = "mcbsp_clk",
87                         .id             = 2,
88                         .enable         = omap_mcbsp_clk_enable,
89                         .disable        = omap_mcbsp_clk_disable,
90                 },
91         },
92         {
93                 .clk = {
94                         .name           = "mcbsp_clk",
95                         .id             = 3,
96                         .enable         = omap_mcbsp_clk_enable,
97                         .disable        = omap_mcbsp_clk_disable,
98                 },
99         },
100         {
101                 .clk = {
102                         .name           = "mcbsp_clk",
103                         .id             = 4,
104                         .enable         = omap_mcbsp_clk_enable,
105                         .disable        = omap_mcbsp_clk_disable,
106                 },
107         },
108         {
109                 .clk = {
110                         .name           = "mcbsp_clk",
111                         .id             = 5,
112                         .enable         = omap_mcbsp_clk_enable,
113                         .disable        = omap_mcbsp_clk_disable,
114                 },
115         },
116 };
117
118 #define omap_mcbsp_clks_size    ARRAY_SIZE(omap_mcbsp_clks)
119 #else
120 #define omap_mcbsp_clks_size    0
121 static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
122 static inline void omap_mcbsp_clk_init(struct clk *clk)
123 { }
124 #endif
125
126 static void omap2_mcbsp2_mux_setup(void)
127 {
128         omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
129         omap_cfg_reg(R14_24XX_MCBSP2_FSX);
130         omap_cfg_reg(W15_24XX_MCBSP2_DR);
131         omap_cfg_reg(V15_24XX_MCBSP2_DX);
132         omap_cfg_reg(V14_24XX_GPIO117);
133         /*
134          * TODO: Need to add MUX settings for OMAP 2430 SDP
135          */
136 }
137
138 static void omap2_mcbsp_request(unsigned int id)
139 {
140         if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
141                 omap2_mcbsp2_mux_setup();
142 }
143
144 static struct omap_mcbsp_ops omap2_mcbsp_ops = {
145         .request        = omap2_mcbsp_request,
146 };
147
148 #ifdef CONFIG_ARCH_OMAP2420
149 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
150         {
151                 .phys_base      = OMAP24XX_MCBSP1_BASE,
152                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
153                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
154                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
155                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
156                 .ops            = &omap2_mcbsp_ops,
157                 .clk_name       = "mcbsp_clk",
158         },
159         {
160                 .phys_base      = OMAP24XX_MCBSP2_BASE,
161                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
162                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
163                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
164                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
165                 .ops            = &omap2_mcbsp_ops,
166                 .clk_name       = "mcbsp_clk",
167         },
168 };
169 #define OMAP2420_MCBSP_PDATA_SZ         ARRAY_SIZE(omap2420_mcbsp_pdata)
170 #else
171 #define omap2420_mcbsp_pdata            NULL
172 #define OMAP2420_MCBSP_PDATA_SZ         0
173 #endif
174
175 #ifdef CONFIG_ARCH_OMAP2430
176 static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
177         {
178                 .phys_base      = OMAP24XX_MCBSP1_BASE,
179                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
180                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
181                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
182                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
183                 .ops            = &omap2_mcbsp_ops,
184                 .clk_name       = "mcbsp_clk",
185         },
186         {
187                 .phys_base      = OMAP24XX_MCBSP2_BASE,
188                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
189                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
190                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
191                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
192                 .ops            = &omap2_mcbsp_ops,
193                 .clk_name       = "mcbsp_clk",
194         },
195         {
196                 .phys_base      = OMAP2430_MCBSP3_BASE,
197                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
198                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
199                 .ops            = &omap2_mcbsp_ops,
200                 .clk_name       = "mcbsp_clk",
201         },
202         {
203                 .phys_base      = OMAP2430_MCBSP4_BASE,
204                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
205                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
206                 .ops            = &omap2_mcbsp_ops,
207                 .clk_name       = "mcbsp_clk",
208         },
209         {
210                 .phys_base      = OMAP2430_MCBSP5_BASE,
211                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
212                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
213                 .ops            = &omap2_mcbsp_ops,
214                 .clk_name       = "mcbsp_clk",
215         },
216 };
217 #define OMAP2430_MCBSP_PDATA_SZ         ARRAY_SIZE(omap2430_mcbsp_pdata)
218 #else
219 #define omap2430_mcbsp_pdata            NULL
220 #define OMAP2430_MCBSP_PDATA_SZ         0
221 #endif
222
223 #ifdef CONFIG_ARCH_OMAP34XX
224 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
225         {
226                 .phys_base      = OMAP34XX_MCBSP1_BASE,
227                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
228                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
229                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
230                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
231                 .ops            = &omap2_mcbsp_ops,
232                 .clk_name       = "mcbsp_clk",
233         },
234         {
235                 .phys_base      = OMAP34XX_MCBSP2_BASE,
236                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
237                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
238                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
239                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
240                 .ops            = &omap2_mcbsp_ops,
241                 .clk_name       = "mcbsp_clk",
242         },
243         {
244                 .phys_base      = OMAP34XX_MCBSP3_BASE,
245                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
246                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
247                 .ops            = &omap2_mcbsp_ops,
248                 .clk_name       = "mcbsp_clk",
249         },
250         {
251                 .phys_base      = OMAP34XX_MCBSP4_BASE,
252                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
253                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
254                 .ops            = &omap2_mcbsp_ops,
255                 .clk_name       = "mcbsp_clk",
256         },
257         {
258                 .phys_base      = OMAP34XX_MCBSP5_BASE,
259                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
260                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
261                 .ops            = &omap2_mcbsp_ops,
262                 .clk_name       = "mcbsp_clk",
263         },
264 };
265 #define OMAP34XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap34xx_mcbsp_pdata)
266 #else
267 #define omap34xx_mcbsp_pdata            NULL
268 #define OMAP34XX_MCBSP_PDATA_SZ         0
269 #endif
270
271 static int __init omap2_mcbsp_init(void)
272 {
273         int i;
274
275         for (i = 0; i < omap_mcbsp_clks_size; i++) {
276                 /* Once we call clk_get inside init, we do not register it */
277                 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
278                 clk_register(&omap_mcbsp_clks[i].clk);
279         }
280
281         if (cpu_is_omap2420())
282                 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
283         if (cpu_is_omap2430())
284                 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
285         if (cpu_is_omap34xx())
286                 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
287
288         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
289                                                                 GFP_KERNEL);
290         if (!mcbsp_ptr)
291                 return -ENOMEM;
292
293         if (cpu_is_omap2420())
294                 omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
295                                                 OMAP2420_MCBSP_PDATA_SZ);
296         if (cpu_is_omap2430())
297                 omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
298                                                 OMAP2430_MCBSP_PDATA_SZ);
299         if (cpu_is_omap34xx())
300                 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
301                                                 OMAP34XX_MCBSP_PDATA_SZ);
302
303         return omap_mcbsp_init();
304 }
305 arch_initcall(omap2_mcbsp_init);