]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - arch/arm/mach-omap2/mcbsp.c
Merge branches 'topic/fix/hda' and 'topic/fix/misc' into for-linus
[linux-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/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                 .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
200                 .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
201                 .ops            = &omap2_mcbsp_ops,
202                 .clk_name       = "mcbsp_clk",
203         },
204         {
205                 .phys_base      = OMAP2430_MCBSP4_BASE,
206                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
207                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
208                 .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
209                 .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
210                 .ops            = &omap2_mcbsp_ops,
211                 .clk_name       = "mcbsp_clk",
212         },
213         {
214                 .phys_base      = OMAP2430_MCBSP5_BASE,
215                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
216                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
217                 .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
218                 .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
219                 .ops            = &omap2_mcbsp_ops,
220                 .clk_name       = "mcbsp_clk",
221         },
222 };
223 #define OMAP2430_MCBSP_PDATA_SZ         ARRAY_SIZE(omap2430_mcbsp_pdata)
224 #else
225 #define omap2430_mcbsp_pdata            NULL
226 #define OMAP2430_MCBSP_PDATA_SZ         0
227 #endif
228
229 #ifdef CONFIG_ARCH_OMAP34XX
230 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
231         {
232                 .phys_base      = OMAP34XX_MCBSP1_BASE,
233                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
234                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
235                 .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
236                 .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
237                 .ops            = &omap2_mcbsp_ops,
238                 .clk_name       = "mcbsp_clk",
239         },
240         {
241                 .phys_base      = OMAP34XX_MCBSP2_BASE,
242                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
243                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
244                 .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
245                 .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
246                 .ops            = &omap2_mcbsp_ops,
247                 .clk_name       = "mcbsp_clk",
248         },
249         {
250                 .phys_base      = OMAP34XX_MCBSP3_BASE,
251                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
252                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
253                 .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
254                 .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
255                 .ops            = &omap2_mcbsp_ops,
256                 .clk_name       = "mcbsp_clk",
257         },
258         {
259                 .phys_base      = OMAP34XX_MCBSP4_BASE,
260                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
261                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
262                 .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
263                 .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
264                 .ops            = &omap2_mcbsp_ops,
265                 .clk_name       = "mcbsp_clk",
266         },
267         {
268                 .phys_base      = OMAP34XX_MCBSP5_BASE,
269                 .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
270                 .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
271                 .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
272                 .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
273                 .ops            = &omap2_mcbsp_ops,
274                 .clk_name       = "mcbsp_clk",
275         },
276 };
277 #define OMAP34XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap34xx_mcbsp_pdata)
278 #else
279 #define omap34xx_mcbsp_pdata            NULL
280 #define OMAP34XX_MCBSP_PDATA_SZ         0
281 #endif
282
283 static int __init omap2_mcbsp_init(void)
284 {
285         int i;
286
287         for (i = 0; i < omap_mcbsp_clks_size; i++) {
288                 /* Once we call clk_get inside init, we do not register it */
289                 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
290                 clk_register(&omap_mcbsp_clks[i].clk);
291         }
292
293         if (cpu_is_omap2420())
294                 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
295         if (cpu_is_omap2430())
296                 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
297         if (cpu_is_omap34xx())
298                 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
299
300         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
301                                                                 GFP_KERNEL);
302         if (!mcbsp_ptr)
303                 return -ENOMEM;
304
305         if (cpu_is_omap2420())
306                 omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
307                                                 OMAP2420_MCBSP_PDATA_SZ);
308         if (cpu_is_omap2430())
309                 omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
310                                                 OMAP2430_MCBSP_PDATA_SZ);
311         if (cpu_is_omap34xx())
312                 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
313                                                 OMAP34XX_MCBSP_PDATA_SZ);
314
315         return omap_mcbsp_init();
316 }
317 arch_initcall(omap2_mcbsp_init);