]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/mcbsp.c
usb: musb: fix bug in musbhsdma programming
[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/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                         .clkdm          = { .name = "virt_opp_clkdm" },
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                         .clkdm          = { .name = "virt_opp_clkdm" },
90                         .enable         = omap_mcbsp_clk_enable,
91                         .disable        = omap_mcbsp_clk_disable,
92                 },
93         },
94         {
95                 .clk = {
96                         .name           = "mcbsp_clk",
97                         .id             = 3,
98                         .clkdm          = { .name = "virt_opp_clkdm" },
99                         .enable         = omap_mcbsp_clk_enable,
100                         .disable        = omap_mcbsp_clk_disable,
101                 },
102         },
103         {
104                 .clk = {
105                         .name           = "mcbsp_clk",
106                         .id             = 4,
107                         .clkdm          = { .name = "virt_opp_clkdm" },
108                         .enable         = omap_mcbsp_clk_enable,
109                         .disable        = omap_mcbsp_clk_disable,
110                 },
111         },
112         {
113                 .clk = {
114                         .name           = "mcbsp_clk",
115                         .id             = 5,
116                         .clkdm          = { .name = "virt_opp_clkdm" },
117                         .enable         = omap_mcbsp_clk_enable,
118                         .disable        = omap_mcbsp_clk_disable,
119                 },
120         },
121 };
122
123 #define omap_mcbsp_clks_size    ARRAY_SIZE(omap_mcbsp_clks)
124 #else
125 #define omap_mcbsp_clks_size    0
126 static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
127 static inline void omap_mcbsp_clk_init(struct clk *clk)
128 { }
129 #endif
130
131 static void omap2_mcbsp2_mux_setup(void)
132 {
133         omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
134         omap_cfg_reg(R14_24XX_MCBSP2_FSX);
135         omap_cfg_reg(W15_24XX_MCBSP2_DR);
136         omap_cfg_reg(V15_24XX_MCBSP2_DX);
137         omap_cfg_reg(V14_24XX_GPIO117);
138         /*
139          * TODO: Need to add MUX settings for OMAP 2430 SDP
140          */
141 }
142
143 static void omap2_mcbsp_request(unsigned int id)
144 {
145         if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
146                 omap2_mcbsp2_mux_setup();
147 }
148
149 static struct omap_mcbsp_ops omap2_mcbsp_ops = {
150         .request        = omap2_mcbsp_request,
151 };
152
153 #ifdef CONFIG_ARCH_OMAP2420
154 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
155         {
156                 .phys_base      = OMAP24XX_MCBSP1_BASE,
157                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
158                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
159                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
160                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
161                 .ops            = &omap2_mcbsp_ops,
162                 .clk_name       = "mcbsp_clk",
163         },
164         {
165                 .phys_base      = OMAP24XX_MCBSP2_BASE,
166                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
167                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
168                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
169                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
170                 .ops            = &omap2_mcbsp_ops,
171                 .clk_name       = "mcbsp_clk",
172         },
173 };
174 #define OMAP2420_MCBSP_PDATA_SZ         ARRAY_SIZE(omap2420_mcbsp_pdata)
175 #else
176 #define omap2420_mcbsp_pdata            NULL
177 #define OMAP2420_MCBSP_PDATA_SZ         0
178 #endif
179
180 #ifdef CONFIG_ARCH_OMAP2430
181 static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
182         {
183                 .phys_base      = OMAP24XX_MCBSP1_BASE,
184                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
185                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
186                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
187                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
188                 .ops            = &omap2_mcbsp_ops,
189                 .clk_name       = "mcbsp_clk",
190         },
191         {
192                 .phys_base      = OMAP24XX_MCBSP2_BASE,
193                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
194                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
195                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
196                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
197                 .ops            = &omap2_mcbsp_ops,
198                 .clk_name       = "mcbsp_clk",
199         },
200         {
201                 .phys_base      = OMAP2430_MCBSP3_BASE,
202                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
203                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
204                 .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
205                 .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
206                 .ops            = &omap2_mcbsp_ops,
207                 .clk_name       = "mcbsp_clk",
208         },
209         {
210                 .phys_base      = OMAP2430_MCBSP4_BASE,
211                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
212                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
213                 .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
214                 .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
215                 .ops            = &omap2_mcbsp_ops,
216                 .clk_name       = "mcbsp_clk",
217         },
218         {
219                 .phys_base      = OMAP2430_MCBSP5_BASE,
220                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
221                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
222                 .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
223                 .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
224                 .ops            = &omap2_mcbsp_ops,
225                 .clk_name       = "mcbsp_clk",
226         },
227 };
228 #define OMAP2430_MCBSP_PDATA_SZ         ARRAY_SIZE(omap2430_mcbsp_pdata)
229 #else
230 #define omap2430_mcbsp_pdata            NULL
231 #define OMAP2430_MCBSP_PDATA_SZ         0
232 #endif
233
234 #ifdef CONFIG_ARCH_OMAP34XX
235 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
236         {
237                 .phys_base      = OMAP34XX_MCBSP1_BASE,
238                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
239                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
240                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
241                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
242                 .ops            = &omap2_mcbsp_ops,
243                 .clk_name       = "mcbsp_clk",
244         },
245         {
246                 .phys_base      = OMAP34XX_MCBSP2_BASE,
247                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
248                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
249                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
250                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
251                 .ops            = &omap2_mcbsp_ops,
252                 .clk_name       = "mcbsp_clk",
253         },
254         {
255                 .phys_base      = OMAP34XX_MCBSP3_BASE,
256                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
257                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
258                 .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
259                 .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
260                 .ops            = &omap2_mcbsp_ops,
261                 .clk_name       = "mcbsp_clk",
262         },
263         {
264                 .phys_base      = OMAP34XX_MCBSP4_BASE,
265                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
266                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
267                 .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
268                 .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
269                 .ops            = &omap2_mcbsp_ops,
270                 .clk_name       = "mcbsp_clk",
271         },
272         {
273                 .phys_base      = OMAP34XX_MCBSP5_BASE,
274                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
275                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
276                 .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
277                 .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
278                 .ops            = &omap2_mcbsp_ops,
279                 .clk_name       = "mcbsp_clk",
280         },
281 };
282 #define OMAP34XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap34xx_mcbsp_pdata)
283 #else
284 #define omap34xx_mcbsp_pdata            NULL
285 #define OMAP34XX_MCBSP_PDATA_SZ         0
286 #endif
287
288 static int __init omap2_mcbsp_init(void)
289 {
290         int i;
291
292         for (i = 0; i < omap_mcbsp_clks_size; i++) {
293                 /* Once we call clk_get inside init, we do not register it */
294                 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
295                 clk_register(&omap_mcbsp_clks[i].clk);
296         }
297
298         if (cpu_is_omap2420())
299                 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
300         if (cpu_is_omap2430())
301                 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
302         if (cpu_is_omap34xx())
303                 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
304
305         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
306                                                                 GFP_KERNEL);
307         if (!mcbsp_ptr)
308                 return -ENOMEM;
309
310         if (cpu_is_omap2420())
311                 omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
312                                                 OMAP2420_MCBSP_PDATA_SZ);
313         if (cpu_is_omap2430())
314                 omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
315                                                 OMAP2430_MCBSP_PDATA_SZ);
316         if (cpu_is_omap34xx())
317                 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
318                                                 OMAP34XX_MCBSP_PDATA_SZ);
319
320         return omap_mcbsp_init();
321 }
322 arch_initcall(omap2_mcbsp_init);