diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
commit | ff877ea80efa2015b6263766f78ee42c2a1b32f9 (patch) | |
tree | 85205005c611ab774702148558321c6fb92f1ccd /arch/arm/plat-omap/mcbsp.c | |
parent | 30821fee4f0cb3e6d241d9f7ddc37742212e3eb7 (diff) | |
parent | d37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 (diff) |
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 767 |
1 files changed, 309 insertions, 458 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 9cf83c4da9fa..c7f74064696c 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -15,95 +15,66 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/platform_device.h> | ||
18 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
19 | #include <linux/completion.h> | 20 | #include <linux/completion.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/err.h> | 22 | #include <linux/err.h> |
22 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
24 | 25 | #include <linux/io.h> | |
25 | #include <asm/io.h> | ||
26 | #include <asm/irq.h> | ||
27 | 26 | ||
28 | #include <asm/arch/dma.h> | 27 | #include <asm/arch/dma.h> |
29 | #include <asm/arch/mux.h> | ||
30 | #include <asm/arch/irqs.h> | ||
31 | #include <asm/arch/dsp_common.h> | ||
32 | #include <asm/arch/mcbsp.h> | 28 | #include <asm/arch/mcbsp.h> |
33 | 29 | ||
34 | #ifdef CONFIG_MCBSP_DEBUG | ||
35 | #define DBG(x...) printk(x) | ||
36 | #else | ||
37 | #define DBG(x...) do { } while (0) | ||
38 | #endif | ||
39 | |||
40 | struct omap_mcbsp { | ||
41 | u32 io_base; | ||
42 | u8 id; | ||
43 | u8 free; | ||
44 | omap_mcbsp_word_length rx_word_length; | ||
45 | omap_mcbsp_word_length tx_word_length; | ||
46 | |||
47 | omap_mcbsp_io_type_t io_type; /* IRQ or poll */ | ||
48 | /* IRQ based TX/RX */ | ||
49 | int rx_irq; | ||
50 | int tx_irq; | ||
51 | |||
52 | /* DMA stuff */ | ||
53 | u8 dma_rx_sync; | ||
54 | short dma_rx_lch; | ||
55 | u8 dma_tx_sync; | ||
56 | short dma_tx_lch; | ||
57 | |||
58 | /* Completion queues */ | ||
59 | struct completion tx_irq_completion; | ||
60 | struct completion rx_irq_completion; | ||
61 | struct completion tx_dma_completion; | ||
62 | struct completion rx_dma_completion; | ||
63 | |||
64 | spinlock_t lock; | ||
65 | }; | ||
66 | |||
67 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; | 30 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; |
68 | #ifdef CONFIG_ARCH_OMAP1 | 31 | |
69 | static struct clk *mcbsp_dsp_ck = 0; | 32 | #define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \ |
70 | static struct clk *mcbsp_api_ck = 0; | 33 | mcbsp[id].pdata->ops && \ |
71 | static struct clk *mcbsp_dspxor_ck = 0; | 34 | mcbsp[id].pdata->ops->check && \ |
72 | #endif | 35 | (mcbsp[id].pdata->ops->check(id) == 0)) |
73 | #ifdef CONFIG_ARCH_OMAP2 | ||
74 | static struct clk *mcbsp1_ick = 0; | ||
75 | static struct clk *mcbsp1_fck = 0; | ||
76 | static struct clk *mcbsp2_ick = 0; | ||
77 | static struct clk *mcbsp2_fck = 0; | ||
78 | #endif | ||
79 | 36 | ||
80 | static void omap_mcbsp_dump_reg(u8 id) | 37 | static void omap_mcbsp_dump_reg(u8 id) |
81 | { | 38 | { |
82 | DBG("**** MCBSP%d regs ****\n", mcbsp[id].id); | 39 | dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id); |
83 | DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); | 40 | dev_dbg(mcbsp[id].dev, "DRR2: 0x%04x\n", |
84 | DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); | 41 | OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); |
85 | DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); | 42 | dev_dbg(mcbsp[id].dev, "DRR1: 0x%04x\n", |
86 | DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); | 43 | OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); |
87 | DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); | 44 | dev_dbg(mcbsp[id].dev, "DXR2: 0x%04x\n", |
88 | DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); | 45 | OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); |
89 | DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); | 46 | dev_dbg(mcbsp[id].dev, "DXR1: 0x%04x\n", |
90 | DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); | 47 | OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); |
91 | DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); | 48 | dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n", |
92 | DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); | 49 | OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); |
93 | DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); | 50 | dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n", |
94 | DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); | 51 | OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); |
95 | DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); | 52 | dev_dbg(mcbsp[id].dev, "RCR2: 0x%04x\n", |
96 | DBG("***********************\n"); | 53 | OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); |
54 | dev_dbg(mcbsp[id].dev, "RCR1: 0x%04x\n", | ||
55 | OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); | ||
56 | dev_dbg(mcbsp[id].dev, "XCR2: 0x%04x\n", | ||
57 | OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); | ||
58 | dev_dbg(mcbsp[id].dev, "XCR1: 0x%04x\n", | ||
59 | OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); | ||
60 | dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n", | ||
61 | OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); | ||
62 | dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n", | ||
63 | OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); | ||
64 | dev_dbg(mcbsp[id].dev, "PCR0: 0x%04x\n", | ||
65 | OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); | ||
66 | dev_dbg(mcbsp[id].dev, "***********************\n"); | ||
97 | } | 67 | } |
98 | 68 | ||
99 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) | 69 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) |
100 | { | 70 | { |
101 | struct omap_mcbsp *mcbsp_tx = dev_id; | 71 | struct omap_mcbsp *mcbsp_tx = dev_id; |
102 | 72 | ||
103 | DBG("TX IRQ callback : 0x%x\n", | 73 | dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", |
104 | OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); | 74 | OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); |
105 | 75 | ||
106 | complete(&mcbsp_tx->tx_irq_completion); | 76 | complete(&mcbsp_tx->tx_irq_completion); |
77 | |||
107 | return IRQ_HANDLED; | 78 | return IRQ_HANDLED; |
108 | } | 79 | } |
109 | 80 | ||
@@ -111,10 +82,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) | |||
111 | { | 82 | { |
112 | struct omap_mcbsp *mcbsp_rx = dev_id; | 83 | struct omap_mcbsp *mcbsp_rx = dev_id; |
113 | 84 | ||
114 | DBG("RX IRQ callback : 0x%x\n", | 85 | dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", |
115 | OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); | 86 | OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); |
116 | 87 | ||
117 | complete(&mcbsp_rx->rx_irq_completion); | 88 | complete(&mcbsp_rx->rx_irq_completion); |
89 | |||
118 | return IRQ_HANDLED; | 90 | return IRQ_HANDLED; |
119 | } | 91 | } |
120 | 92 | ||
@@ -122,8 +94,8 @@ static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) | |||
122 | { | 94 | { |
123 | struct omap_mcbsp *mcbsp_dma_tx = data; | 95 | struct omap_mcbsp *mcbsp_dma_tx = data; |
124 | 96 | ||
125 | DBG("TX DMA callback : 0x%x\n", | 97 | dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", |
126 | OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); | 98 | OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); |
127 | 99 | ||
128 | /* We can free the channels */ | 100 | /* We can free the channels */ |
129 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); | 101 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); |
@@ -136,8 +108,8 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
136 | { | 108 | { |
137 | struct omap_mcbsp *mcbsp_dma_rx = data; | 109 | struct omap_mcbsp *mcbsp_dma_rx = data; |
138 | 110 | ||
139 | DBG("RX DMA callback : 0x%x\n", | 111 | dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", |
140 | OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); | 112 | OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); |
141 | 113 | ||
142 | /* We can free the channels */ | 114 | /* We can free the channels */ |
143 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); | 115 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); |
@@ -146,19 +118,24 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
146 | complete(&mcbsp_dma_rx->rx_dma_completion); | 118 | complete(&mcbsp_dma_rx->rx_dma_completion); |
147 | } | 119 | } |
148 | 120 | ||
149 | |||
150 | /* | 121 | /* |
151 | * omap_mcbsp_config simply write a config to the | 122 | * omap_mcbsp_config simply write a config to the |
152 | * appropriate McBSP. | 123 | * appropriate McBSP. |
153 | * You either call this function or set the McBSP registers | 124 | * You either call this function or set the McBSP registers |
154 | * by yourself before calling omap_mcbsp_start(). | 125 | * by yourself before calling omap_mcbsp_start(). |
155 | */ | 126 | */ |
156 | 127 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | |
157 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config) | ||
158 | { | 128 | { |
159 | u32 io_base = mcbsp[id].io_base; | 129 | u32 io_base; |
130 | |||
131 | if (!omap_mcbsp_check_valid_id(id)) { | ||
132 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
133 | return; | ||
134 | } | ||
160 | 135 | ||
161 | DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id+1, io_base); | 136 | io_base = mcbsp[id].io_base; |
137 | dev_dbg(mcbsp[id].dev, "Configuring McBSP%d io_base: 0x%8x\n", | ||
138 | mcbsp[id].id, io_base); | ||
162 | 139 | ||
163 | /* We write the given config */ | 140 | /* We write the given config */ |
164 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); | 141 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); |
@@ -173,83 +150,7 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config | |||
173 | OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); | 150 | OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); |
174 | OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); | 151 | OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); |
175 | } | 152 | } |
176 | 153 | EXPORT_SYMBOL(omap_mcbsp_config); | |
177 | |||
178 | |||
179 | static int omap_mcbsp_check(unsigned int id) | ||
180 | { | ||
181 | if (cpu_is_omap730()) { | ||
182 | if (id > OMAP_MAX_MCBSP_COUNT - 1) { | ||
183 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); | ||
184 | return -1; | ||
185 | } | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) { | ||
190 | if (id > OMAP_MAX_MCBSP_COUNT) { | ||
191 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1); | ||
192 | return -1; | ||
193 | } | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | return -1; | ||
198 | } | ||
199 | |||
200 | #ifdef CONFIG_ARCH_OMAP1 | ||
201 | static void omap_mcbsp_dsp_request(void) | ||
202 | { | ||
203 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { | ||
204 | int ret; | ||
205 | |||
206 | ret = omap_dsp_request_mem(); | ||
207 | if (ret < 0) { | ||
208 | printk(KERN_ERR "Could not get dsp memory: %i\n", ret); | ||
209 | return; | ||
210 | } | ||
211 | |||
212 | clk_enable(mcbsp_dsp_ck); | ||
213 | clk_enable(mcbsp_api_ck); | ||
214 | |||
215 | /* enable 12MHz clock to mcbsp 1 & 3 */ | ||
216 | clk_enable(mcbsp_dspxor_ck); | ||
217 | |||
218 | /* | ||
219 | * DSP external peripheral reset | ||
220 | * FIXME: This should be moved to dsp code | ||
221 | */ | ||
222 | __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1, | ||
223 | DSP_RSTCT2); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | static void omap_mcbsp_dsp_free(void) | ||
228 | { | ||
229 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { | ||
230 | omap_dsp_release_mem(); | ||
231 | clk_disable(mcbsp_dspxor_ck); | ||
232 | clk_disable(mcbsp_dsp_ck); | ||
233 | clk_disable(mcbsp_api_ck); | ||
234 | } | ||
235 | } | ||
236 | #endif | ||
237 | |||
238 | #ifdef CONFIG_ARCH_OMAP2 | ||
239 | static void omap2_mcbsp2_mux_setup(void) | ||
240 | { | ||
241 | if (cpu_is_omap2420()) { | ||
242 | omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); | ||
243 | omap_cfg_reg(R14_24XX_MCBSP2_FSX); | ||
244 | omap_cfg_reg(W15_24XX_MCBSP2_DR); | ||
245 | omap_cfg_reg(V15_24XX_MCBSP2_DX); | ||
246 | omap_cfg_reg(V14_24XX_GPIO117); | ||
247 | } | ||
248 | /* | ||
249 | * Need to add MUX settings for OMAP 2430 SDP | ||
250 | */ | ||
251 | } | ||
252 | #endif | ||
253 | 154 | ||
254 | /* | 155 | /* |
255 | * We can choose between IRQ based or polled IO. | 156 | * We can choose between IRQ based or polled IO. |
@@ -257,13 +158,16 @@ static void omap2_mcbsp2_mux_setup(void) | |||
257 | */ | 158 | */ |
258 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | 159 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) |
259 | { | 160 | { |
260 | if (omap_mcbsp_check(id) < 0) | 161 | if (!omap_mcbsp_check_valid_id(id)) { |
261 | return -EINVAL; | 162 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
163 | return -ENODEV; | ||
164 | } | ||
262 | 165 | ||
263 | spin_lock(&mcbsp[id].lock); | 166 | spin_lock(&mcbsp[id].lock); |
264 | 167 | ||
265 | if (!mcbsp[id].free) { | 168 | if (!mcbsp[id].free) { |
266 | printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); | 169 | dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", |
170 | mcbsp[id].id); | ||
267 | spin_unlock(&mcbsp[id].lock); | 171 | spin_unlock(&mcbsp[id].lock); |
268 | return -EINVAL; | 172 | return -EINVAL; |
269 | } | 173 | } |
@@ -274,38 +178,26 @@ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | |||
274 | 178 | ||
275 | return 0; | 179 | return 0; |
276 | } | 180 | } |
181 | EXPORT_SYMBOL(omap_mcbsp_set_io_type); | ||
277 | 182 | ||
278 | int omap_mcbsp_request(unsigned int id) | 183 | int omap_mcbsp_request(unsigned int id) |
279 | { | 184 | { |
280 | int err; | 185 | int err; |
281 | 186 | ||
282 | if (omap_mcbsp_check(id) < 0) | 187 | if (!omap_mcbsp_check_valid_id(id)) { |
283 | return -EINVAL; | 188 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
284 | 189 | return -ENODEV; | |
285 | #ifdef CONFIG_ARCH_OMAP1 | ||
286 | /* | ||
287 | * On 1510, 1610 and 1710, McBSP1 and McBSP3 | ||
288 | * are DSP public peripherals. | ||
289 | */ | ||
290 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | ||
291 | omap_mcbsp_dsp_request(); | ||
292 | #endif | ||
293 | |||
294 | #ifdef CONFIG_ARCH_OMAP2 | ||
295 | if (cpu_is_omap24xx()) { | ||
296 | if (id == OMAP_MCBSP1) { | ||
297 | clk_enable(mcbsp1_ick); | ||
298 | clk_enable(mcbsp1_fck); | ||
299 | } else { | ||
300 | clk_enable(mcbsp2_ick); | ||
301 | clk_enable(mcbsp2_fck); | ||
302 | } | ||
303 | } | 190 | } |
304 | #endif | 191 | |
192 | if (mcbsp[id].pdata->ops->request) | ||
193 | mcbsp[id].pdata->ops->request(id); | ||
194 | |||
195 | clk_enable(mcbsp[id].clk); | ||
305 | 196 | ||
306 | spin_lock(&mcbsp[id].lock); | 197 | spin_lock(&mcbsp[id].lock); |
307 | if (!mcbsp[id].free) { | 198 | if (!mcbsp[id].free) { |
308 | printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1); | 199 | dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", |
200 | mcbsp[id].id); | ||
309 | spin_unlock(&mcbsp[id].lock); | 201 | spin_unlock(&mcbsp[id].lock); |
310 | return -1; | 202 | return -1; |
311 | } | 203 | } |
@@ -315,24 +207,23 @@ int omap_mcbsp_request(unsigned int id) | |||
315 | 207 | ||
316 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { | 208 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { |
317 | /* We need to get IRQs here */ | 209 | /* We need to get IRQs here */ |
318 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0, | 210 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, |
319 | "McBSP", | 211 | 0, "McBSP", (void *) (&mcbsp[id])); |
320 | (void *) (&mcbsp[id])); | ||
321 | if (err != 0) { | 212 | if (err != 0) { |
322 | printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n", | 213 | dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d " |
323 | mcbsp[id].tx_irq, mcbsp[id].id); | 214 | "for McBSP%d\n", mcbsp[id].tx_irq, |
215 | mcbsp[id].id); | ||
324 | return err; | 216 | return err; |
325 | } | 217 | } |
326 | 218 | ||
327 | init_completion(&(mcbsp[id].tx_irq_completion)); | 219 | init_completion(&(mcbsp[id].tx_irq_completion)); |
328 | 220 | ||
329 | 221 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, | |
330 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0, | 222 | 0, "McBSP", (void *) (&mcbsp[id])); |
331 | "McBSP", | ||
332 | (void *) (&mcbsp[id])); | ||
333 | if (err != 0) { | 223 | if (err != 0) { |
334 | printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n", | 224 | dev_err(mcbsp[id].dev, "Unable to request RX IRQ %d " |
335 | mcbsp[id].rx_irq, mcbsp[id].id); | 225 | "for McBSP%d\n", mcbsp[id].rx_irq, |
226 | mcbsp[id].id); | ||
336 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 227 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); |
337 | return err; | 228 | return err; |
338 | } | 229 | } |
@@ -341,36 +232,25 @@ int omap_mcbsp_request(unsigned int id) | |||
341 | } | 232 | } |
342 | 233 | ||
343 | return 0; | 234 | return 0; |
344 | |||
345 | } | 235 | } |
236 | EXPORT_SYMBOL(omap_mcbsp_request); | ||
346 | 237 | ||
347 | void omap_mcbsp_free(unsigned int id) | 238 | void omap_mcbsp_free(unsigned int id) |
348 | { | 239 | { |
349 | if (omap_mcbsp_check(id) < 0) | 240 | if (!omap_mcbsp_check_valid_id(id)) { |
241 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
350 | return; | 242 | return; |
351 | |||
352 | #ifdef CONFIG_ARCH_OMAP1 | ||
353 | if (cpu_class_is_omap1()) { | ||
354 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | ||
355 | omap_mcbsp_dsp_free(); | ||
356 | } | 243 | } |
357 | #endif | 244 | |
358 | 245 | if (mcbsp[id].pdata->ops->free) | |
359 | #ifdef CONFIG_ARCH_OMAP2 | 246 | mcbsp[id].pdata->ops->free(id); |
360 | if (cpu_is_omap24xx()) { | 247 | |
361 | if (id == OMAP_MCBSP1) { | 248 | clk_disable(mcbsp[id].clk); |
362 | clk_disable(mcbsp1_ick); | ||
363 | clk_disable(mcbsp1_fck); | ||
364 | } else { | ||
365 | clk_disable(mcbsp2_ick); | ||
366 | clk_disable(mcbsp2_fck); | ||
367 | } | ||
368 | } | ||
369 | #endif | ||
370 | 249 | ||
371 | spin_lock(&mcbsp[id].lock); | 250 | spin_lock(&mcbsp[id].lock); |
372 | if (mcbsp[id].free) { | 251 | if (mcbsp[id].free) { |
373 | printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1); | 252 | dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n", |
253 | mcbsp[id].id); | ||
374 | spin_unlock(&mcbsp[id].lock); | 254 | spin_unlock(&mcbsp[id].lock); |
375 | return; | 255 | return; |
376 | } | 256 | } |
@@ -384,6 +264,7 @@ void omap_mcbsp_free(unsigned int id) | |||
384 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 264 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); |
385 | } | 265 | } |
386 | } | 266 | } |
267 | EXPORT_SYMBOL(omap_mcbsp_free); | ||
387 | 268 | ||
388 | /* | 269 | /* |
389 | * Here we start the McBSP, by enabling the sample | 270 | * Here we start the McBSP, by enabling the sample |
@@ -395,13 +276,15 @@ void omap_mcbsp_start(unsigned int id) | |||
395 | u32 io_base; | 276 | u32 io_base; |
396 | u16 w; | 277 | u16 w; |
397 | 278 | ||
398 | if (omap_mcbsp_check(id) < 0) | 279 | if (!omap_mcbsp_check_valid_id(id)) { |
280 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
399 | return; | 281 | return; |
282 | } | ||
400 | 283 | ||
401 | io_base = mcbsp[id].io_base; | 284 | io_base = mcbsp[id].io_base; |
402 | 285 | ||
403 | mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7); | 286 | mcbsp[id].rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; |
404 | mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7); | 287 | mcbsp[id].tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; |
405 | 288 | ||
406 | /* Start the sample generator */ | 289 | /* Start the sample generator */ |
407 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 290 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
@@ -422,20 +305,22 @@ void omap_mcbsp_start(unsigned int id) | |||
422 | 305 | ||
423 | /* Dump McBSP Regs */ | 306 | /* Dump McBSP Regs */ |
424 | omap_mcbsp_dump_reg(id); | 307 | omap_mcbsp_dump_reg(id); |
425 | |||
426 | } | 308 | } |
309 | EXPORT_SYMBOL(omap_mcbsp_start); | ||
427 | 310 | ||
428 | void omap_mcbsp_stop(unsigned int id) | 311 | void omap_mcbsp_stop(unsigned int id) |
429 | { | 312 | { |
430 | u32 io_base; | 313 | u32 io_base; |
431 | u16 w; | 314 | u16 w; |
432 | 315 | ||
433 | if (omap_mcbsp_check(id) < 0) | 316 | if (!omap_mcbsp_check_valid_id(id)) { |
317 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
434 | return; | 318 | return; |
319 | } | ||
435 | 320 | ||
436 | io_base = mcbsp[id].io_base; | 321 | io_base = mcbsp[id].io_base; |
437 | 322 | ||
438 | /* Reset transmitter */ | 323 | /* Reset transmitter */ |
439 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 324 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
440 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); | 325 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); |
441 | 326 | ||
@@ -447,12 +332,19 @@ void omap_mcbsp_stop(unsigned int id) | |||
447 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 332 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
448 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); | 333 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); |
449 | } | 334 | } |
450 | 335 | EXPORT_SYMBOL(omap_mcbsp_stop); | |
451 | 336 | ||
452 | /* polled mcbsp i/o operations */ | 337 | /* polled mcbsp i/o operations */ |
453 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | 338 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) |
454 | { | 339 | { |
455 | u32 base = mcbsp[id].io_base; | 340 | u32 base; |
341 | |||
342 | if (!omap_mcbsp_check_valid_id(id)) { | ||
343 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
344 | return -ENODEV; | ||
345 | } | ||
346 | |||
347 | base = mcbsp[id].io_base; | ||
456 | writew(buf, base + OMAP_MCBSP_REG_DXR1); | 348 | writew(buf, base + OMAP_MCBSP_REG_DXR1); |
457 | /* if frame sync error - clear the error */ | 349 | /* if frame sync error - clear the error */ |
458 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { | 350 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { |
@@ -474,18 +366,27 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | |||
474 | (XRST), | 366 | (XRST), |
475 | base + OMAP_MCBSP_REG_SPCR2); | 367 | base + OMAP_MCBSP_REG_SPCR2); |
476 | udelay(10); | 368 | udelay(10); |
477 | printk(KERN_ERR | 369 | dev_err(mcbsp[id].dev, "Could not write to" |
478 | " Could not write to McBSP Register\n"); | 370 | " McBSP%d Register\n", mcbsp[id].id); |
479 | return -2; | 371 | return -2; |
480 | } | 372 | } |
481 | } | 373 | } |
482 | } | 374 | } |
375 | |||
483 | return 0; | 376 | return 0; |
484 | } | 377 | } |
378 | EXPORT_SYMBOL(omap_mcbsp_pollwrite); | ||
485 | 379 | ||
486 | int omap_mcbsp_pollread(unsigned int id, u16 * buf) | 380 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) |
487 | { | 381 | { |
488 | u32 base = mcbsp[id].io_base; | 382 | u32 base; |
383 | |||
384 | if (!omap_mcbsp_check_valid_id(id)) { | ||
385 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
386 | return -ENODEV; | ||
387 | } | ||
388 | |||
389 | base = mcbsp[id].io_base; | ||
489 | /* if frame sync error - clear the error */ | 390 | /* if frame sync error - clear the error */ |
490 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { | 391 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { |
491 | /* clear error */ | 392 | /* clear error */ |
@@ -506,15 +407,17 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf) | |||
506 | (RRST), | 407 | (RRST), |
507 | base + OMAP_MCBSP_REG_SPCR1); | 408 | base + OMAP_MCBSP_REG_SPCR1); |
508 | udelay(10); | 409 | udelay(10); |
509 | printk(KERN_ERR | 410 | dev_err(mcbsp[id].dev, "Could not read from" |
510 | " Could not read from McBSP Register\n"); | 411 | " McBSP%d Register\n", mcbsp[id].id); |
511 | return -2; | 412 | return -2; |
512 | } | 413 | } |
513 | } | 414 | } |
514 | } | 415 | } |
515 | *buf = readw(base + OMAP_MCBSP_REG_DRR1); | 416 | *buf = readw(base + OMAP_MCBSP_REG_DRR1); |
417 | |||
516 | return 0; | 418 | return 0; |
517 | } | 419 | } |
420 | EXPORT_SYMBOL(omap_mcbsp_pollread); | ||
518 | 421 | ||
519 | /* | 422 | /* |
520 | * IRQ based word transmission. | 423 | * IRQ based word transmission. |
@@ -522,12 +425,15 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf) | |||
522 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) | 425 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) |
523 | { | 426 | { |
524 | u32 io_base; | 427 | u32 io_base; |
525 | omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length; | 428 | omap_mcbsp_word_length word_length; |
526 | 429 | ||
527 | if (omap_mcbsp_check(id) < 0) | 430 | if (!omap_mcbsp_check_valid_id(id)) { |
431 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
528 | return; | 432 | return; |
433 | } | ||
529 | 434 | ||
530 | io_base = mcbsp[id].io_base; | 435 | io_base = mcbsp[id].io_base; |
436 | word_length = mcbsp[id].tx_word_length; | ||
531 | 437 | ||
532 | wait_for_completion(&(mcbsp[id].tx_irq_completion)); | 438 | wait_for_completion(&(mcbsp[id].tx_irq_completion)); |
533 | 439 | ||
@@ -535,16 +441,20 @@ void omap_mcbsp_xmit_word(unsigned int id, u32 word) | |||
535 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); | 441 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); |
536 | OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); | 442 | OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); |
537 | } | 443 | } |
444 | EXPORT_SYMBOL(omap_mcbsp_xmit_word); | ||
538 | 445 | ||
539 | u32 omap_mcbsp_recv_word(unsigned int id) | 446 | u32 omap_mcbsp_recv_word(unsigned int id) |
540 | { | 447 | { |
541 | u32 io_base; | 448 | u32 io_base; |
542 | u16 word_lsb, word_msb = 0; | 449 | u16 word_lsb, word_msb = 0; |
543 | omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length; | 450 | omap_mcbsp_word_length word_length; |
544 | 451 | ||
545 | if (omap_mcbsp_check(id) < 0) | 452 | if (!omap_mcbsp_check_valid_id(id)) { |
546 | return -EINVAL; | 453 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
454 | return -ENODEV; | ||
455 | } | ||
547 | 456 | ||
457 | word_length = mcbsp[id].rx_word_length; | ||
548 | io_base = mcbsp[id].io_base; | 458 | io_base = mcbsp[id].io_base; |
549 | 459 | ||
550 | wait_for_completion(&(mcbsp[id].rx_irq_completion)); | 460 | wait_for_completion(&(mcbsp[id].rx_irq_completion)); |
@@ -555,15 +465,24 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
555 | 465 | ||
556 | return (word_lsb | (word_msb << 16)); | 466 | return (word_lsb | (word_msb << 16)); |
557 | } | 467 | } |
558 | 468 | EXPORT_SYMBOL(omap_mcbsp_recv_word); | |
559 | 469 | ||
560 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | 470 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) |
561 | { | 471 | { |
562 | u32 io_base = mcbsp[id].io_base; | 472 | u32 io_base; |
563 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | 473 | omap_mcbsp_word_length tx_word_length; |
564 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | 474 | omap_mcbsp_word_length rx_word_length; |
565 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 475 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
566 | 476 | ||
477 | if (!omap_mcbsp_check_valid_id(id)) { | ||
478 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
479 | return -ENODEV; | ||
480 | } | ||
481 | |||
482 | io_base = mcbsp[id].io_base; | ||
483 | tx_word_length = mcbsp[id].tx_word_length; | ||
484 | rx_word_length = mcbsp[id].rx_word_length; | ||
485 | |||
567 | if (tx_word_length != rx_word_length) | 486 | if (tx_word_length != rx_word_length) |
568 | return -EINVAL; | 487 | return -EINVAL; |
569 | 488 | ||
@@ -577,7 +496,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
577 | udelay(10); | 496 | udelay(10); |
578 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 497 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); |
579 | udelay(10); | 498 | udelay(10); |
580 | printk("McBSP transmitter not ready\n"); | 499 | dev_err(mcbsp[id].dev, "McBSP%d transmitter not " |
500 | "ready\n", mcbsp[id].id); | ||
581 | return -EAGAIN; | 501 | return -EAGAIN; |
582 | } | 502 | } |
583 | } | 503 | } |
@@ -597,7 +517,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
597 | udelay(10); | 517 | udelay(10); |
598 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 518 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); |
599 | udelay(10); | 519 | udelay(10); |
600 | printk("McBSP receiver not ready\n"); | 520 | dev_err(mcbsp[id].dev, "McBSP%d receiver not " |
521 | "ready\n", mcbsp[id].id); | ||
601 | return -EAGAIN; | 522 | return -EAGAIN; |
602 | } | 523 | } |
603 | } | 524 | } |
@@ -609,14 +530,24 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
609 | 530 | ||
610 | return 0; | 531 | return 0; |
611 | } | 532 | } |
533 | EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | ||
612 | 534 | ||
613 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | 535 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) |
614 | { | 536 | { |
615 | u32 io_base = mcbsp[id].io_base, clock_word = 0; | 537 | u32 io_base, clock_word = 0; |
616 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | 538 | omap_mcbsp_word_length tx_word_length; |
617 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | 539 | omap_mcbsp_word_length rx_word_length; |
618 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 540 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
619 | 541 | ||
542 | if (!omap_mcbsp_check_valid_id(id)) { | ||
543 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
544 | return -ENODEV; | ||
545 | } | ||
546 | |||
547 | io_base = mcbsp[id].io_base; | ||
548 | tx_word_length = mcbsp[id].tx_word_length; | ||
549 | rx_word_length = mcbsp[id].rx_word_length; | ||
550 | |||
620 | if (tx_word_length != rx_word_length) | 551 | if (tx_word_length != rx_word_length) |
621 | return -EINVAL; | 552 | return -EINVAL; |
622 | 553 | ||
@@ -630,7 +561,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | |||
630 | udelay(10); | 561 | udelay(10); |
631 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 562 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); |
632 | udelay(10); | 563 | udelay(10); |
633 | printk("McBSP transmitter not ready\n"); | 564 | dev_err(mcbsp[id].dev, "McBSP%d transmitter not " |
565 | "ready\n", mcbsp[id].id); | ||
634 | return -EAGAIN; | 566 | return -EAGAIN; |
635 | } | 567 | } |
636 | } | 568 | } |
@@ -650,7 +582,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | |||
650 | udelay(10); | 582 | udelay(10); |
651 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 583 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); |
652 | udelay(10); | 584 | udelay(10); |
653 | printk("McBSP receiver not ready\n"); | 585 | dev_err(mcbsp[id].dev, "McBSP%d receiver not " |
586 | "ready\n", mcbsp[id].id); | ||
654 | return -EAGAIN; | 587 | return -EAGAIN; |
655 | } | 588 | } |
656 | } | 589 | } |
@@ -664,7 +597,7 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | |||
664 | 597 | ||
665 | return 0; | 598 | return 0; |
666 | } | 599 | } |
667 | 600 | EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); | |
668 | 601 | ||
669 | /* | 602 | /* |
670 | * Simple DMA based buffer rx/tx routines. | 603 | * Simple DMA based buffer rx/tx routines. |
@@ -673,25 +606,32 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word) | |||
673 | * For anything fancier, you should use your own customized DMA | 606 | * For anything fancier, you should use your own customized DMA |
674 | * routines and callbacks. | 607 | * routines and callbacks. |
675 | */ | 608 | */ |
676 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) | 609 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, |
610 | unsigned int length) | ||
677 | { | 611 | { |
678 | int dma_tx_ch; | 612 | int dma_tx_ch; |
679 | int src_port = 0; | 613 | int src_port = 0; |
680 | int dest_port = 0; | 614 | int dest_port = 0; |
681 | int sync_dev = 0; | 615 | int sync_dev = 0; |
682 | 616 | ||
683 | if (omap_mcbsp_check(id) < 0) | 617 | if (!omap_mcbsp_check_valid_id(id)) { |
684 | return -EINVAL; | 618 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
619 | return -ENODEV; | ||
620 | } | ||
685 | 621 | ||
686 | if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback, | 622 | if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", |
687 | &mcbsp[id], | 623 | omap_mcbsp_tx_dma_callback, |
688 | &dma_tx_ch)) { | 624 | &mcbsp[id], |
689 | printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1); | 625 | &dma_tx_ch)) { |
626 | dev_err(mcbsp[id].dev, " Unable to request DMA channel for " | ||
627 | "McBSP%d TX. Trying IRQ based TX\n", | ||
628 | mcbsp[id].id); | ||
690 | return -EAGAIN; | 629 | return -EAGAIN; |
691 | } | 630 | } |
692 | mcbsp[id].dma_tx_lch = dma_tx_ch; | 631 | mcbsp[id].dma_tx_lch = dma_tx_ch; |
693 | 632 | ||
694 | DBG("TX DMA on channel %d\n", dma_tx_ch); | 633 | dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id, |
634 | dma_tx_ch); | ||
695 | 635 | ||
696 | init_completion(&(mcbsp[id].tx_dma_completion)); | 636 | init_completion(&(mcbsp[id].tx_dma_completion)); |
697 | 637 | ||
@@ -699,7 +639,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
699 | src_port = OMAP_DMA_PORT_TIPB; | 639 | src_port = OMAP_DMA_PORT_TIPB; |
700 | dest_port = OMAP_DMA_PORT_EMIFF; | 640 | dest_port = OMAP_DMA_PORT_EMIFF; |
701 | } | 641 | } |
702 | if (cpu_is_omap24xx()) | 642 | if (cpu_class_is_omap2()) |
703 | sync_dev = mcbsp[id].dma_tx_sync; | 643 | sync_dev = mcbsp[id].dma_tx_sync; |
704 | 644 | ||
705 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, | 645 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, |
@@ -722,29 +662,37 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
722 | 662 | ||
723 | omap_start_dma(mcbsp[id].dma_tx_lch); | 663 | omap_start_dma(mcbsp[id].dma_tx_lch); |
724 | wait_for_completion(&(mcbsp[id].tx_dma_completion)); | 664 | wait_for_completion(&(mcbsp[id].tx_dma_completion)); |
665 | |||
725 | return 0; | 666 | return 0; |
726 | } | 667 | } |
668 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); | ||
727 | 669 | ||
728 | 670 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, | |
729 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) | 671 | unsigned int length) |
730 | { | 672 | { |
731 | int dma_rx_ch; | 673 | int dma_rx_ch; |
732 | int src_port = 0; | 674 | int src_port = 0; |
733 | int dest_port = 0; | 675 | int dest_port = 0; |
734 | int sync_dev = 0; | 676 | int sync_dev = 0; |
735 | 677 | ||
736 | if (omap_mcbsp_check(id) < 0) | 678 | if (!omap_mcbsp_check_valid_id(id)) { |
737 | return -EINVAL; | 679 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
680 | return -ENODEV; | ||
681 | } | ||
738 | 682 | ||
739 | if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback, | 683 | if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", |
740 | &mcbsp[id], | 684 | omap_mcbsp_rx_dma_callback, |
741 | &dma_rx_ch)) { | 685 | &mcbsp[id], |
742 | printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1); | 686 | &dma_rx_ch)) { |
687 | dev_err(mcbsp[id].dev, "Unable to request DMA channel for " | ||
688 | "McBSP%d RX. Trying IRQ based RX\n", | ||
689 | mcbsp[id].id); | ||
743 | return -EAGAIN; | 690 | return -EAGAIN; |
744 | } | 691 | } |
745 | mcbsp[id].dma_rx_lch = dma_rx_ch; | 692 | mcbsp[id].dma_rx_lch = dma_rx_ch; |
746 | 693 | ||
747 | DBG("RX DMA on channel %d\n", dma_rx_ch); | 694 | dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id, |
695 | dma_rx_ch); | ||
748 | 696 | ||
749 | init_completion(&(mcbsp[id].rx_dma_completion)); | 697 | init_completion(&(mcbsp[id].rx_dma_completion)); |
750 | 698 | ||
@@ -752,14 +700,14 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
752 | src_port = OMAP_DMA_PORT_TIPB; | 700 | src_port = OMAP_DMA_PORT_TIPB; |
753 | dest_port = OMAP_DMA_PORT_EMIFF; | 701 | dest_port = OMAP_DMA_PORT_EMIFF; |
754 | } | 702 | } |
755 | if (cpu_is_omap24xx()) | 703 | if (cpu_class_is_omap2()) |
756 | sync_dev = mcbsp[id].dma_rx_sync; | 704 | sync_dev = mcbsp[id].dma_rx_sync; |
757 | 705 | ||
758 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, | 706 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, |
759 | OMAP_DMA_DATA_TYPE_S16, | 707 | OMAP_DMA_DATA_TYPE_S16, |
760 | length >> 1, 1, | 708 | length >> 1, 1, |
761 | OMAP_DMA_SYNC_ELEMENT, | 709 | OMAP_DMA_SYNC_ELEMENT, |
762 | sync_dev, 0); | 710 | sync_dev, 0); |
763 | 711 | ||
764 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, | 712 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, |
765 | src_port, | 713 | src_port, |
@@ -768,16 +716,17 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
768 | 0, 0); | 716 | 0, 0); |
769 | 717 | ||
770 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, | 718 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, |
771 | dest_port, | 719 | dest_port, |
772 | OMAP_DMA_AMODE_POST_INC, | 720 | OMAP_DMA_AMODE_POST_INC, |
773 | buffer, | 721 | buffer, |
774 | 0, 0); | 722 | 0, 0); |
775 | 723 | ||
776 | omap_start_dma(mcbsp[id].dma_rx_lch); | 724 | omap_start_dma(mcbsp[id].dma_rx_lch); |
777 | wait_for_completion(&(mcbsp[id].rx_dma_completion)); | 725 | wait_for_completion(&(mcbsp[id].rx_dma_completion)); |
726 | |||
778 | return 0; | 727 | return 0; |
779 | } | 728 | } |
780 | 729 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); | |
781 | 730 | ||
782 | /* | 731 | /* |
783 | * SPI wrapper. | 732 | * SPI wrapper. |
@@ -785,12 +734,15 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng | |||
785 | * this wrapper just need an omap_mcbsp_spi_cfg structure as an input. | 734 | * this wrapper just need an omap_mcbsp_spi_cfg structure as an input. |
786 | * Once this is done, you can call omap_mcbsp_start(). | 735 | * Once this is done, you can call omap_mcbsp_start(). |
787 | */ | 736 | */ |
788 | void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg) | 737 | void omap_mcbsp_set_spi_mode(unsigned int id, |
738 | const struct omap_mcbsp_spi_cfg *spi_cfg) | ||
789 | { | 739 | { |
790 | struct omap_mcbsp_reg_cfg mcbsp_cfg; | 740 | struct omap_mcbsp_reg_cfg mcbsp_cfg; |
791 | 741 | ||
792 | if (omap_mcbsp_check(id) < 0) | 742 | if (!omap_mcbsp_check_valid_id(id)) { |
743 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
793 | return; | 744 | return; |
745 | } | ||
794 | 746 | ||
795 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); | 747 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); |
796 | 748 | ||
@@ -798,7 +750,7 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * | |||
798 | mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0)); | 750 | mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0)); |
799 | mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0)); | 751 | mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0)); |
800 | 752 | ||
801 | /* Clock stop mode */ | 753 | /* Clock stop mode */ |
802 | if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY) | 754 | if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY) |
803 | mcbsp_cfg.spcr1 |= (1 << 12); | 755 | mcbsp_cfg.spcr1 |= (1 << 12); |
804 | else | 756 | else |
@@ -827,13 +779,12 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * | |||
827 | 779 | ||
828 | if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) { | 780 | if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) { |
829 | mcbsp_cfg.pcr0 |= CLKXM; | 781 | mcbsp_cfg.pcr0 |= CLKXM; |
830 | mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1); | 782 | mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div - 1); |
831 | mcbsp_cfg.pcr0 |= FSXM; | 783 | mcbsp_cfg.pcr0 |= FSXM; |
832 | mcbsp_cfg.srgr2 &= ~FSGM; | 784 | mcbsp_cfg.srgr2 &= ~FSGM; |
833 | mcbsp_cfg.xcr2 |= XDATDLY(1); | 785 | mcbsp_cfg.xcr2 |= XDATDLY(1); |
834 | mcbsp_cfg.rcr2 |= RDATDLY(1); | 786 | mcbsp_cfg.rcr2 |= RDATDLY(1); |
835 | } | 787 | } else { |
836 | else { | ||
837 | mcbsp_cfg.pcr0 &= ~CLKXM; | 788 | mcbsp_cfg.pcr0 &= ~CLKXM; |
838 | mcbsp_cfg.srgr1 |= CLKGDV(1); | 789 | mcbsp_cfg.srgr1 |= CLKGDV(1); |
839 | mcbsp_cfg.pcr0 &= ~FSXM; | 790 | mcbsp_cfg.pcr0 &= ~FSXM; |
@@ -846,199 +797,99 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * | |||
846 | 797 | ||
847 | omap_mcbsp_config(id, &mcbsp_cfg); | 798 | omap_mcbsp_config(id, &mcbsp_cfg); |
848 | } | 799 | } |
849 | 800 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | |
850 | 801 | ||
851 | /* | 802 | /* |
852 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. | 803 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. |
853 | * 730 has only 2 McBSP, and both of them are MPU peripherals. | 804 | * 730 has only 2 McBSP, and both of them are MPU peripherals. |
854 | */ | 805 | */ |
855 | struct omap_mcbsp_info { | 806 | static int __init omap_mcbsp_probe(struct platform_device *pdev) |
856 | u32 virt_base; | 807 | { |
857 | u8 dma_rx_sync, dma_tx_sync; | 808 | struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; |
858 | u16 rx_irq, tx_irq; | 809 | int id = pdev->id - 1; |
859 | }; | 810 | int ret = 0; |
860 | 811 | ||
861 | #ifdef CONFIG_ARCH_OMAP730 | 812 | if (!pdata) { |
862 | static const struct omap_mcbsp_info mcbsp_730[] = { | 813 | dev_err(&pdev->dev, "McBSP device initialized without" |
863 | [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE), | 814 | "platform data\n"); |
864 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 815 | ret = -EINVAL; |
865 | .dma_tx_sync = OMAP_DMA_MCBSP1_TX, | 816 | goto exit; |
866 | .rx_irq = INT_730_McBSP1RX, | 817 | } |
867 | .tx_irq = INT_730_McBSP1TX }, | 818 | |
868 | [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE), | 819 | dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); |
869 | .dma_rx_sync = OMAP_DMA_MCBSP3_RX, | 820 | |
870 | .dma_tx_sync = OMAP_DMA_MCBSP3_TX, | 821 | if (id >= OMAP_MAX_MCBSP_COUNT) { |
871 | .rx_irq = INT_730_McBSP2RX, | 822 | dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); |
872 | .tx_irq = INT_730_McBSP2TX }, | 823 | ret = -EINVAL; |
873 | }; | 824 | goto exit; |
874 | #endif | 825 | } |
875 | 826 | ||
876 | #ifdef CONFIG_ARCH_OMAP15XX | 827 | spin_lock_init(&mcbsp[id].lock); |
877 | static const struct omap_mcbsp_info mcbsp_1510[] = { | 828 | mcbsp[id].id = id + 1; |
878 | [0] = { .virt_base = OMAP1510_MCBSP1_BASE, | 829 | mcbsp[id].free = 1; |
879 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 830 | mcbsp[id].dma_tx_lch = -1; |
880 | .dma_tx_sync = OMAP_DMA_MCBSP1_TX, | 831 | mcbsp[id].dma_rx_lch = -1; |
881 | .rx_irq = INT_McBSP1RX, | 832 | |
882 | .tx_irq = INT_McBSP1TX }, | 833 | mcbsp[id].io_base = pdata->virt_base; |
883 | [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE), | 834 | /* Default I/O is IRQ based */ |
884 | .dma_rx_sync = OMAP_DMA_MCBSP2_RX, | 835 | mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO; |
885 | .dma_tx_sync = OMAP_DMA_MCBSP2_TX, | 836 | mcbsp[id].tx_irq = pdata->tx_irq; |
886 | .rx_irq = INT_1510_SPI_RX, | 837 | mcbsp[id].rx_irq = pdata->rx_irq; |
887 | .tx_irq = INT_1510_SPI_TX }, | 838 | mcbsp[id].dma_rx_sync = pdata->dma_rx_sync; |
888 | [2] = { .virt_base = OMAP1510_MCBSP3_BASE, | 839 | mcbsp[id].dma_tx_sync = pdata->dma_tx_sync; |
889 | .dma_rx_sync = OMAP_DMA_MCBSP3_RX, | 840 | |
890 | .dma_tx_sync = OMAP_DMA_MCBSP3_TX, | 841 | if (pdata->clk_name) |
891 | .rx_irq = INT_McBSP3RX, | 842 | mcbsp[id].clk = clk_get(&pdev->dev, pdata->clk_name); |
892 | .tx_irq = INT_McBSP3TX }, | 843 | if (IS_ERR(mcbsp[id].clk)) { |
893 | }; | 844 | mcbsp[id].free = 0; |
894 | #endif | 845 | dev_err(&pdev->dev, |
895 | 846 | "Invalid clock configuration for McBSP%d.\n", | |
896 | #if defined(CONFIG_ARCH_OMAP16XX) | 847 | mcbsp[id].id); |
897 | static const struct omap_mcbsp_info mcbsp_1610[] = { | 848 | ret = -EINVAL; |
898 | [0] = { .virt_base = OMAP1610_MCBSP1_BASE, | 849 | goto exit; |
899 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 850 | } |
900 | .dma_tx_sync = OMAP_DMA_MCBSP1_TX, | 851 | |
901 | .rx_irq = INT_McBSP1RX, | 852 | mcbsp[id].pdata = pdata; |
902 | .tx_irq = INT_McBSP1TX }, | 853 | mcbsp[id].dev = &pdev->dev; |
903 | [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE), | 854 | platform_set_drvdata(pdev, &mcbsp[id]); |
904 | .dma_rx_sync = OMAP_DMA_MCBSP2_RX, | 855 | |
905 | .dma_tx_sync = OMAP_DMA_MCBSP2_TX, | 856 | exit: |
906 | .rx_irq = INT_1610_McBSP2_RX, | 857 | return ret; |
907 | .tx_irq = INT_1610_McBSP2_TX }, | 858 | } |
908 | [2] = { .virt_base = OMAP1610_MCBSP3_BASE, | ||
909 | .dma_rx_sync = OMAP_DMA_MCBSP3_RX, | ||
910 | .dma_tx_sync = OMAP_DMA_MCBSP3_TX, | ||
911 | .rx_irq = INT_McBSP3RX, | ||
912 | .tx_irq = INT_McBSP3TX }, | ||
913 | }; | ||
914 | #endif | ||
915 | |||
916 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
917 | static const struct omap_mcbsp_info mcbsp_24xx[] = { | ||
918 | [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE), | ||
919 | .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, | ||
920 | .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, | ||
921 | .rx_irq = INT_24XX_MCBSP1_IRQ_RX, | ||
922 | .tx_irq = INT_24XX_MCBSP1_IRQ_TX, | ||
923 | }, | ||
924 | [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE), | ||
925 | .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, | ||
926 | .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, | ||
927 | .rx_irq = INT_24XX_MCBSP2_IRQ_RX, | ||
928 | .tx_irq = INT_24XX_MCBSP2_IRQ_TX, | ||
929 | }, | ||
930 | }; | ||
931 | #endif | ||
932 | 859 | ||
933 | static int __init omap_mcbsp_init(void) | 860 | static int omap_mcbsp_remove(struct platform_device *pdev) |
934 | { | 861 | { |
935 | int mcbsp_count = 0, i; | 862 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); |
936 | static const struct omap_mcbsp_info *mcbsp_info; | ||
937 | 863 | ||
938 | printk("Initializing OMAP McBSP system\n"); | 864 | platform_set_drvdata(pdev, NULL); |
865 | if (mcbsp) { | ||
939 | 866 | ||
940 | #ifdef CONFIG_ARCH_OMAP1 | 867 | if (mcbsp->pdata && mcbsp->pdata->ops && |
941 | mcbsp_dsp_ck = clk_get(0, "dsp_ck"); | 868 | mcbsp->pdata->ops->free) |
942 | if (IS_ERR(mcbsp_dsp_ck)) { | 869 | mcbsp->pdata->ops->free(mcbsp->id); |
943 | printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); | ||
944 | return PTR_ERR(mcbsp_dsp_ck); | ||
945 | } | ||
946 | mcbsp_api_ck = clk_get(0, "api_ck"); | ||
947 | if (IS_ERR(mcbsp_api_ck)) { | ||
948 | printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n"); | ||
949 | return PTR_ERR(mcbsp_api_ck); | ||
950 | } | ||
951 | mcbsp_dspxor_ck = clk_get(0, "dspxor_ck"); | ||
952 | if (IS_ERR(mcbsp_dspxor_ck)) { | ||
953 | printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); | ||
954 | return PTR_ERR(mcbsp_dspxor_ck); | ||
955 | } | ||
956 | #endif | ||
957 | #ifdef CONFIG_ARCH_OMAP2 | ||
958 | mcbsp1_ick = clk_get(0, "mcbsp1_ick"); | ||
959 | if (IS_ERR(mcbsp1_ick)) { | ||
960 | printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n"); | ||
961 | return PTR_ERR(mcbsp1_ick); | ||
962 | } | ||
963 | mcbsp1_fck = clk_get(0, "mcbsp1_fck"); | ||
964 | if (IS_ERR(mcbsp1_fck)) { | ||
965 | printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n"); | ||
966 | return PTR_ERR(mcbsp1_fck); | ||
967 | } | ||
968 | mcbsp2_ick = clk_get(0, "mcbsp2_ick"); | ||
969 | if (IS_ERR(mcbsp2_ick)) { | ||
970 | printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n"); | ||
971 | return PTR_ERR(mcbsp2_ick); | ||
972 | } | ||
973 | mcbsp2_fck = clk_get(0, "mcbsp2_fck"); | ||
974 | if (IS_ERR(mcbsp2_fck)) { | ||
975 | printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n"); | ||
976 | return PTR_ERR(mcbsp2_fck); | ||
977 | } | ||
978 | #endif | ||
979 | 870 | ||
980 | #ifdef CONFIG_ARCH_OMAP730 | 871 | clk_disable(mcbsp->clk); |
981 | if (cpu_is_omap730()) { | 872 | clk_put(mcbsp->clk); |
982 | mcbsp_info = mcbsp_730; | 873 | |
983 | mcbsp_count = ARRAY_SIZE(mcbsp_730); | 874 | mcbsp->clk = NULL; |
984 | } | 875 | mcbsp->free = 0; |
985 | #endif | 876 | mcbsp->dev = NULL; |
986 | #ifdef CONFIG_ARCH_OMAP15XX | ||
987 | if (cpu_is_omap15xx()) { | ||
988 | mcbsp_info = mcbsp_1510; | ||
989 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); | ||
990 | } | ||
991 | #endif | ||
992 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
993 | if (cpu_is_omap16xx()) { | ||
994 | mcbsp_info = mcbsp_1610; | ||
995 | mcbsp_count = ARRAY_SIZE(mcbsp_1610); | ||
996 | } | ||
997 | #endif | ||
998 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
999 | if (cpu_is_omap24xx()) { | ||
1000 | mcbsp_info = mcbsp_24xx; | ||
1001 | mcbsp_count = ARRAY_SIZE(mcbsp_24xx); | ||
1002 | omap2_mcbsp2_mux_setup(); | ||
1003 | } | ||
1004 | #endif | ||
1005 | for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { | ||
1006 | if (i >= mcbsp_count) { | ||
1007 | mcbsp[i].io_base = 0; | ||
1008 | mcbsp[i].free = 0; | ||
1009 | continue; | ||
1010 | } | ||
1011 | mcbsp[i].id = i + 1; | ||
1012 | mcbsp[i].free = 1; | ||
1013 | mcbsp[i].dma_tx_lch = -1; | ||
1014 | mcbsp[i].dma_rx_lch = -1; | ||
1015 | |||
1016 | mcbsp[i].io_base = mcbsp_info[i].virt_base; | ||
1017 | mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */ | ||
1018 | mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; | ||
1019 | mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; | ||
1020 | mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; | ||
1021 | mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync; | ||
1022 | spin_lock_init(&mcbsp[i].lock); | ||
1023 | } | 877 | } |
1024 | 878 | ||
1025 | return 0; | 879 | return 0; |
1026 | } | 880 | } |
1027 | 881 | ||
1028 | arch_initcall(omap_mcbsp_init); | 882 | static struct platform_driver omap_mcbsp_driver = { |
883 | .probe = omap_mcbsp_probe, | ||
884 | .remove = omap_mcbsp_remove, | ||
885 | .driver = { | ||
886 | .name = "omap-mcbsp", | ||
887 | }, | ||
888 | }; | ||
889 | |||
890 | int __init omap_mcbsp_init(void) | ||
891 | { | ||
892 | /* Register the McBSP driver */ | ||
893 | return platform_driver_register(&omap_mcbsp_driver); | ||
894 | } | ||
1029 | 895 | ||
1030 | EXPORT_SYMBOL(omap_mcbsp_config); | ||
1031 | EXPORT_SYMBOL(omap_mcbsp_request); | ||
1032 | EXPORT_SYMBOL(omap_mcbsp_set_io_type); | ||
1033 | EXPORT_SYMBOL(omap_mcbsp_free); | ||
1034 | EXPORT_SYMBOL(omap_mcbsp_start); | ||
1035 | EXPORT_SYMBOL(omap_mcbsp_stop); | ||
1036 | EXPORT_SYMBOL(omap_mcbsp_pollread); | ||
1037 | EXPORT_SYMBOL(omap_mcbsp_pollwrite); | ||
1038 | EXPORT_SYMBOL(omap_mcbsp_xmit_word); | ||
1039 | EXPORT_SYMBOL(omap_mcbsp_recv_word); | ||
1040 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); | ||
1041 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); | ||
1042 | EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | ||
1043 | EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); | ||
1044 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | ||