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