Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[linux-2.6] / arch / arm / mach-omap1 / mcbsp.c
1 /*
2  * linux/arch/arm/mach-omap1/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 #include <mach/dsp_common.h>
27
28 #define DPS_RSTCT2_PER_EN       (1 << 0)
29 #define DSP_RSTCT2_WD_PER_EN    (1 << 1)
30
31 struct mcbsp_internal_clk {
32         struct clk clk;
33         struct clk **childs;
34         int n_childs;
35 };
36
37 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
38 static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
39 {
40         const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
41         int i;
42
43         mclk->n_childs = ARRAY_SIZE(clk_names);
44         mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
45                                 GFP_KERNEL);
46
47         for (i = 0; i < mclk->n_childs; i++) {
48                 /* We fake a platform device to get correct device id */
49                 struct platform_device pdev;
50
51                 pdev.dev.bus = &platform_bus_type;
52                 pdev.id = mclk->clk.id;
53                 mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
54                 if (IS_ERR(mclk->childs[i]))
55                         printk(KERN_ERR "Could not get clock %s (%d).\n",
56                                 clk_names[i], mclk->clk.id);
57         }
58 }
59
60 static int omap_mcbsp_clk_enable(struct clk *clk)
61 {
62         struct mcbsp_internal_clk *mclk = container_of(clk,
63                                         struct mcbsp_internal_clk, clk);
64         int i;
65
66         for (i = 0; i < mclk->n_childs; i++)
67                 clk_enable(mclk->childs[i]);
68         return 0;
69 }
70
71 static void omap_mcbsp_clk_disable(struct clk *clk)
72 {
73         struct mcbsp_internal_clk *mclk = container_of(clk,
74                                         struct mcbsp_internal_clk, clk);
75         int i;
76
77         for (i = 0; i < mclk->n_childs; i++)
78                 clk_disable(mclk->childs[i]);
79 }
80
81 static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
82         {
83                 .clk = {
84                         .name           = "mcbsp_clk",
85                         .id             = 1,
86                         .enable         = omap_mcbsp_clk_enable,
87                         .disable        = omap_mcbsp_clk_disable,
88                 },
89         },
90         {
91                 .clk = {
92                         .name           = "mcbsp_clk",
93                         .id             = 3,
94                         .enable         = omap_mcbsp_clk_enable,
95                         .disable        = omap_mcbsp_clk_disable,
96                 },
97         },
98 };
99
100 #define omap_mcbsp_clks_size    ARRAY_SIZE(omap_mcbsp_clks)
101 #else
102 #define omap_mcbsp_clks_size    0
103 static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
104 static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
105 { }
106 #endif
107
108 static void omap1_mcbsp_request(unsigned int id)
109 {
110         /*
111          * On 1510, 1610 and 1710, McBSP1 and McBSP3
112          * are DSP public peripherals.
113          */
114         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
115                 omap_dsp_request_mem();
116                 /*
117                  * DSP external peripheral reset
118                  * FIXME: This should be moved to dsp code
119                  */
120                 __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
121                                 DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
122         }
123 }
124
125 static void omap1_mcbsp_free(unsigned int id)
126 {
127         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
128                 omap_dsp_release_mem();
129 }
130
131 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
132         .request        = omap1_mcbsp_request,
133         .free           = omap1_mcbsp_free,
134 };
135
136 #ifdef CONFIG_ARCH_OMAP730
137 static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
138         {
139                 .phys_base      = OMAP730_MCBSP1_BASE,
140                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
141                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
142                 .rx_irq         = INT_730_McBSP1RX,
143                 .tx_irq         = INT_730_McBSP1TX,
144                 .ops            = &omap1_mcbsp_ops,
145         },
146         {
147                 .phys_base      = OMAP730_MCBSP2_BASE,
148                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
149                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
150                 .rx_irq         = INT_730_McBSP2RX,
151                 .tx_irq         = INT_730_McBSP2TX,
152                 .ops            = &omap1_mcbsp_ops,
153         },
154 };
155 #define OMAP730_MCBSP_PDATA_SZ          ARRAY_SIZE(omap730_mcbsp_pdata)
156 #else
157 #define omap730_mcbsp_pdata             NULL
158 #define OMAP730_MCBSP_PDATA_SZ          0
159 #endif
160
161 #ifdef CONFIG_ARCH_OMAP15XX
162 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
163         {
164                 .phys_base      = OMAP1510_MCBSP1_BASE,
165                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
166                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
167                 .rx_irq         = INT_McBSP1RX,
168                 .tx_irq         = INT_McBSP1TX,
169                 .ops            = &omap1_mcbsp_ops,
170                 .clk_name       = "mcbsp_clk",
171                 },
172         {
173                 .phys_base      = OMAP1510_MCBSP2_BASE,
174                 .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
175                 .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
176                 .rx_irq         = INT_1510_SPI_RX,
177                 .tx_irq         = INT_1510_SPI_TX,
178                 .ops            = &omap1_mcbsp_ops,
179         },
180         {
181                 .phys_base      = OMAP1510_MCBSP3_BASE,
182                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
183                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
184                 .rx_irq         = INT_McBSP3RX,
185                 .tx_irq         = INT_McBSP3TX,
186                 .ops            = &omap1_mcbsp_ops,
187                 .clk_name       = "mcbsp_clk",
188         },
189 };
190 #define OMAP15XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap15xx_mcbsp_pdata)
191 #else
192 #define omap15xx_mcbsp_pdata            NULL
193 #define OMAP15XX_MCBSP_PDATA_SZ         0
194 #endif
195
196 #ifdef CONFIG_ARCH_OMAP16XX
197 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
198         {
199                 .phys_base      = OMAP1610_MCBSP1_BASE,
200                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
201                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
202                 .rx_irq         = INT_McBSP1RX,
203                 .tx_irq         = INT_McBSP1TX,
204                 .ops            = &omap1_mcbsp_ops,
205                 .clk_name       = "mcbsp_clk",
206         },
207         {
208                 .phys_base      = OMAP1610_MCBSP2_BASE,
209                 .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
210                 .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
211                 .rx_irq         = INT_1610_McBSP2_RX,
212                 .tx_irq         = INT_1610_McBSP2_TX,
213                 .ops            = &omap1_mcbsp_ops,
214         },
215         {
216                 .phys_base      = OMAP1610_MCBSP3_BASE,
217                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
218                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
219                 .rx_irq         = INT_McBSP3RX,
220                 .tx_irq         = INT_McBSP3TX,
221                 .ops            = &omap1_mcbsp_ops,
222                 .clk_name       = "mcbsp_clk",
223         },
224 };
225 #define OMAP16XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap16xx_mcbsp_pdata)
226 #else
227 #define omap16xx_mcbsp_pdata            NULL
228 #define OMAP16XX_MCBSP_PDATA_SZ         0
229 #endif
230
231 int __init omap1_mcbsp_init(void)
232 {
233         int i;
234
235         for (i = 0; i < omap_mcbsp_clks_size; i++) {
236                 if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
237                         omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
238                         clk_register(&omap_mcbsp_clks[i].clk);
239                 }
240         }
241
242         if (cpu_is_omap730())
243                 omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
244         if (cpu_is_omap15xx())
245                 omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
246         if (cpu_is_omap16xx())
247                 omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
248
249         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
250                                                                 GFP_KERNEL);
251         if (!mcbsp_ptr)
252                 return -ENOMEM;
253
254         if (cpu_is_omap730())
255                 omap_mcbsp_register_board_cfg(omap730_mcbsp_pdata,
256                                                 OMAP730_MCBSP_PDATA_SZ);
257
258         if (cpu_is_omap15xx())
259                 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
260                                                 OMAP15XX_MCBSP_PDATA_SZ);
261
262         if (cpu_is_omap16xx())
263                 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
264                                                 OMAP16XX_MCBSP_PDATA_SZ);
265
266         return omap_mcbsp_init();
267 }
268
269 arch_initcall(omap1_mcbsp_init);