]> 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/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_OMAP24XX
149 static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
150         {
151                 .virt_base      = OMAP2_IO_ADDRESS(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                 .virt_base      = OMAP2_IO_ADDRESS(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 OMAP24XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap24xx_mcbsp_pdata)
170 #else
171 #define omap24xx_mcbsp_pdata            NULL
172 #define OMAP24XX_MCBSP_PDATA_SZ         0
173 #endif
174
175 #ifdef CONFIG_ARCH_OMAP34XX
176 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
177         {
178                 .virt_base      = OMAP2_IO_ADDRESS(OMAP34XX_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                 .virt_base      = OMAP2_IO_ADDRESS(OMAP34XX_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                 .virt_base      = OMAP2_IO_ADDRESS(OMAP34XX_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                 .virt_base      = OMAP2_IO_ADDRESS(OMAP34XX_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                 .virt_base      = OMAP2_IO_ADDRESS(OMAP34XX_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 OMAP34XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap34xx_mcbsp_pdata)
218 #else
219 #define omap34xx_mcbsp_pdata            NULL
220 #define OMAP34XX_MCBSP_PDATA_SZ         0
221 #endif
222
223 static int __init omap2_mcbsp_init(void)
224 {
225         int i;
226
227         for (i = 0; i < omap_mcbsp_clks_size; i++) {
228                 /* Once we call clk_get inside init, we do not register it */
229                 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
230                 clk_register(&omap_mcbsp_clks[i].clk);
231         }
232
233         if (cpu_is_omap24xx())
234                 omap_mcbsp_count = OMAP24XX_MCBSP_PDATA_SZ;
235         if (cpu_is_omap34xx())
236                 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
237
238         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
239                                                                 GFP_KERNEL);
240         if (!mcbsp_ptr)
241                 return -ENOMEM;
242
243         if (cpu_is_omap24xx())
244                 omap_mcbsp_register_board_cfg(omap24xx_mcbsp_pdata,
245                                                 OMAP24XX_MCBSP_PDATA_SZ);
246         if (cpu_is_omap34xx())
247                 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
248                                                 OMAP34XX_MCBSP_PDATA_SZ);
249
250         return omap_mcbsp_init();
251 }
252 arch_initcall(omap2_mcbsp_init);