omap: McBSP: Introduce caching in register write operations
[linux-2.6.git] / 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 <plat/dma.h>
22 #include <plat/mux.h>
23 #include <plat/cpu.h>
24 #include <plat/mcbsp.h>
25 #include <plat/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 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
83 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
84         {
85                 .phys_base      = OMAP7XX_MCBSP1_BASE,
86                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
87                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
88                 .rx_irq         = INT_7XX_McBSP1RX,
89                 .tx_irq         = INT_7XX_McBSP1TX,
90                 .ops            = &omap1_mcbsp_ops,
91         },
92         {
93                 .phys_base      = OMAP7XX_MCBSP2_BASE,
94                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
95                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
96                 .rx_irq         = INT_7XX_McBSP2RX,
97                 .tx_irq         = INT_7XX_McBSP2TX,
98                 .ops            = &omap1_mcbsp_ops,
99         },
100 };
101 #define OMAP7XX_MCBSP_PDATA_SZ          ARRAY_SIZE(omap7xx_mcbsp_pdata)
102 #define OMAP7XX_MCBSP_REG_NUM           (OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
103 #else
104 #define omap7xx_mcbsp_pdata             NULL
105 #define OMAP7XX_MCBSP_PDATA_SZ          0
106 #define OMAP7XX_MCBSP_REG_NUM           0
107 #endif
108
109 #ifdef CONFIG_ARCH_OMAP15XX
110 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
111         {
112                 .phys_base      = OMAP1510_MCBSP1_BASE,
113                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
114                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
115                 .rx_irq         = INT_McBSP1RX,
116                 .tx_irq         = INT_McBSP1TX,
117                 .ops            = &omap1_mcbsp_ops,
118         },
119         {
120                 .phys_base      = OMAP1510_MCBSP2_BASE,
121                 .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
122                 .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
123                 .rx_irq         = INT_1510_SPI_RX,
124                 .tx_irq         = INT_1510_SPI_TX,
125                 .ops            = &omap1_mcbsp_ops,
126         },
127         {
128                 .phys_base      = OMAP1510_MCBSP3_BASE,
129                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
130                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
131                 .rx_irq         = INT_McBSP3RX,
132                 .tx_irq         = INT_McBSP3TX,
133                 .ops            = &omap1_mcbsp_ops,
134         },
135 };
136 #define OMAP15XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap15xx_mcbsp_pdata)
137 #define OMAP15XX_MCBSP_REG_NUM          (OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
138 #else
139 #define omap15xx_mcbsp_pdata            NULL
140 #define OMAP15XX_MCBSP_PDATA_SZ         0
141 #define OMAP15XX_MCBSP_REG_NUM          0
142 #endif
143
144 #ifdef CONFIG_ARCH_OMAP16XX
145 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
146         {
147                 .phys_base      = OMAP1610_MCBSP1_BASE,
148                 .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
149                 .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
150                 .rx_irq         = INT_McBSP1RX,
151                 .tx_irq         = INT_McBSP1TX,
152                 .ops            = &omap1_mcbsp_ops,
153         },
154         {
155                 .phys_base      = OMAP1610_MCBSP2_BASE,
156                 .dma_rx_sync    = OMAP_DMA_MCBSP2_RX,
157                 .dma_tx_sync    = OMAP_DMA_MCBSP2_TX,
158                 .rx_irq         = INT_1610_McBSP2_RX,
159                 .tx_irq         = INT_1610_McBSP2_TX,
160                 .ops            = &omap1_mcbsp_ops,
161         },
162         {
163                 .phys_base      = OMAP1610_MCBSP3_BASE,
164                 .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
165                 .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
166                 .rx_irq         = INT_McBSP3RX,
167                 .tx_irq         = INT_McBSP3TX,
168                 .ops            = &omap1_mcbsp_ops,
169         },
170 };
171 #define OMAP16XX_MCBSP_PDATA_SZ         ARRAY_SIZE(omap16xx_mcbsp_pdata)
172 #define OMAP16XX_MCBSP_REG_NUM          (OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
173 #else
174 #define omap16xx_mcbsp_pdata            NULL
175 #define OMAP16XX_MCBSP_PDATA_SZ         0
176 #define OMAP16XX_MCBSP_REG_NUM          0
177 #endif
178
179 int __init omap1_mcbsp_init(void)
180 {
181         if (cpu_is_omap7xx()) {
182                 omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ;
183                 omap_mcbsp_cache_size = OMAP7XX_MCBSP_REG_NUM * sizeof(u16);
184         } else if (cpu_is_omap15xx()) {
185                 omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
186                 omap_mcbsp_cache_size = OMAP15XX_MCBSP_REG_NUM * sizeof(u16);
187         } else if (cpu_is_omap16xx()) {
188                 omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
189                 omap_mcbsp_cache_size = OMAP16XX_MCBSP_REG_NUM * sizeof(u16);
190         }
191
192         mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
193                                                                 GFP_KERNEL);
194         if (!mcbsp_ptr)
195                 return -ENOMEM;
196
197         if (cpu_is_omap7xx())
198                 omap_mcbsp_register_board_cfg(omap7xx_mcbsp_pdata,
199                                                 OMAP7XX_MCBSP_PDATA_SZ);
200
201         if (cpu_is_omap15xx())
202                 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
203                                                 OMAP15XX_MCBSP_PDATA_SZ);
204
205         if (cpu_is_omap16xx())
206                 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
207                                                 OMAP16XX_MCBSP_PDATA_SZ);
208
209         return omap_mcbsp_init();
210 }
211
212 arch_initcall(omap1_mcbsp_init);