Merge branch 'fix' of git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6
[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/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 static int dsp_use;
31 static struct clk *api_clk;
32 static struct clk *dsp_clk;
33
34 static void omap1_mcbsp_request(unsigned int id)
35 {
36         /*
37          * On 1510, 1610 and 1710, McBSP1 and McBSP3
38          * are DSP public peripherals.
39          */
40         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
41                 if (dsp_use++ == 0) {
42                         api_clk = clk_get(NULL, "api_ck");
43                         dsp_clk = clk_get(NULL, "dsp_ck");
44                         if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
45                                 clk_enable(api_clk);
46                                 clk_enable(dsp_clk);
47
48                                 omap_dsp_request_mem();
49                                 /*
50                                  * DSP external peripheral reset
51                                  * FIXME: This should be moved to dsp code
52                                  */
53                                 __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
54                                                 DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
55                         }
56                 }
57         }
58 }
59
60 static void omap1_mcbsp_free(unsigned int id)
61 {
62         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
63                 if (--dsp_use == 0) {
64                         omap_dsp_release_mem();
65                         if (!IS_ERR(api_clk)) {
66                                 clk_disable(api_clk);
67                                 clk_put(api_clk);
68                         }
69                         if (!IS_ERR(dsp_clk)) {
70                                 clk_disable(dsp_clk);
71                                 clk_put(dsp_clk);
72                         }
73                 }
74         }
75 }
76
77 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
78         .request        = omap1_mcbsp_request,
79         .free           = omap1_mcbsp_free,
80 };
81
82 #ifdef CONFIG_ARCH_OMAP730
83 static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
84         {
85                 .phys_base      = OMAP730_MCBSP1_BASE,
86                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
87                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
88                 .rx_irq         = INT_730_McBSP1RX,
89                 .tx_irq         = INT_730_McBSP1TX,
90                 .ops            = &omap1_mcbsp_ops,
91         },
92         {
93                 .phys_base      = OMAP730_MCBSP2_BASE,
94                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
95                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
96                 .rx_irq         = INT_730_McBSP2RX,
97                 .tx_irq         = INT_730_McBSP2TX,
98                 .ops            = &omap1_mcbsp_ops,
99         },
100 };
101 #define OMAP730_MCBSP_PDATA_SZ          ARRAY_SIZE(omap730_mcbsp_pdata)
102 #else
103 #define omap730_mcbsp_pdata             NULL
104 #define OMAP730_MCBSP_PDATA_SZ          0
105 #endif
106
107 #ifdef CONFIG_ARCH_OMAP15XX
108 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
109         {
110                 .phys_base      = OMAP1510_MCBSP1_BASE,
111                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
112                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
113                 .rx_irq         = INT_McBSP1RX,
114                 .tx_irq         = INT_McBSP1TX,
115                 .ops            = &omap1_mcbsp_ops,
116         },
117         {
118                 .phys_base      = OMAP1510_MCBSP2_BASE,
119                 .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
120                 .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
121                 .rx_irq         = INT_1510_SPI_RX,
122                 .tx_irq         = INT_1510_SPI_TX,
123                 .ops            = &omap1_mcbsp_ops,
124         },
125         {
126                 .phys_base      = OMAP1510_MCBSP3_BASE,
127                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
128                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
129                 .rx_irq         = INT_McBSP3RX,
130                 .tx_irq         = INT_McBSP3TX,
131                 .ops            = &omap1_mcbsp_ops,
132         },
133 };
134 #define OMAP15XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap15xx_mcbsp_pdata)
135 #else
136 #define omap15xx_mcbsp_pdata            NULL
137 #define OMAP15XX_MCBSP_PDATA_SZ         0
138 #endif
139
140 #ifdef CONFIG_ARCH_OMAP16XX
141 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
142         {
143                 .phys_base      = OMAP1610_MCBSP1_BASE,
144                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
145                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
146                 .rx_irq         = INT_McBSP1RX,
147                 .tx_irq         = INT_McBSP1TX,
148                 .ops            = &omap1_mcbsp_ops,
149         },
150         {
151                 .phys_base      = OMAP1610_MCBSP2_BASE,
152                 .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
153                 .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
154                 .rx_irq         = INT_1610_McBSP2_RX,
155                 .tx_irq         = INT_1610_McBSP2_TX,
156                 .ops            = &omap1_mcbsp_ops,
157         },
158         {
159                 .phys_base      = OMAP1610_MCBSP3_BASE,
160                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
161                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
162                 .rx_irq         = INT_McBSP3RX,
163                 .tx_irq         = INT_McBSP3TX,
164                 .ops            = &omap1_mcbsp_ops,
165         },
166 };
167 #define OMAP16XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap16xx_mcbsp_pdata)
168 #else
169 #define omap16xx_mcbsp_pdata            NULL
170 #define OMAP16XX_MCBSP_PDATA_SZ         0
171 #endif
172
173 int __init omap1_mcbsp_init(void)
174 {
175         if (cpu_is_omap730())
176                 omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
177         if (cpu_is_omap15xx())
178                 omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
179         if (cpu_is_omap16xx())
180                 omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
181
182         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
183                                                                 GFP_KERNEL);
184         if (!mcbsp_ptr)
185                 return -ENOMEM;
186
187         if (cpu_is_omap730())
188                 omap_mcbsp_register_board_cfg(omap730_mcbsp_pdata,
189                                                 OMAP730_MCBSP_PDATA_SZ);
190
191         if (cpu_is_omap15xx())
192                 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
193                                                 OMAP15XX_MCBSP_PDATA_SZ);
194
195         if (cpu_is_omap16xx())
196                 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
197                                                 OMAP16XX_MCBSP_PDATA_SZ);
198
199         return omap_mcbsp_init();
200 }
201
202 arch_initcall(omap1_mcbsp_init);