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