This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / arm / mach-omap / mcbsp.c
1 /*
2  * linux/arch/arm/omap/mcbsp.c
3  *
4  * Copyright (C) 2004 Nokia Corporation
5  * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
6  *
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * Multichannel mode not supported.
13  */
14
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/device.h>
18 #include <linux/wait.h>
19 #include <linux/completion.h>
20 #include <linux/interrupt.h>
21
22 #include <asm/delay.h>
23 #include <asm/io.h>
24 #include <asm/irq.h>
25
26 #include <asm/arch/dma.h>
27 #include <asm/arch/mux.h>
28 #include <asm/arch/irqs.h>
29 #include <asm/arch/mcbsp.h>
30
31 #ifdef CONFIG_MCBSP_DEBUG
32 #define DBG(x...)       printk(x)
33 #else
34 #define DBG(x...)       do { } while (0)
35 #endif
36
37 struct omap_mcbsp {
38         u32                          io_base;
39         u8                           id;
40         u8                           free;
41         omap_mcbsp_word_length       rx_word_length;
42         omap_mcbsp_word_length       tx_word_length;
43
44         /* IRQ based TX/RX */
45         int                          rx_irq;
46         int                          tx_irq;
47
48         /* DMA stuff */
49         u8                           dma_rx_sync;
50         short                        dma_rx_lch;
51         u8                           dma_tx_sync;
52         short                        dma_tx_lch;
53
54         /* Completion queues */
55         struct completion            tx_irq_completion;
56         struct completion            rx_irq_completion;
57         struct completion            tx_dma_completion;
58         struct completion            rx_dma_completion;
59
60         spinlock_t                   lock;
61 };
62
63 static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
64
65
66 static void omap_mcbsp_dump_reg(u8 id)
67 {
68         DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
69         DBG("DRR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
70         DBG("DRR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
71         DBG("DXR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
72         DBG("DXR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
73         DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
74         DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
75         DBG("RCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
76         DBG("RCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
77         DBG("XCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
78         DBG("XCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
79         DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
80         DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
81         DBG("PCR0:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
82         DBG("***********************\n");
83 }
84
85
86 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
87 {
88         struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
89
90         DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
91
92         complete(&mcbsp_tx->tx_irq_completion);
93         return IRQ_HANDLED;
94 }
95
96 static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
97 {
98         struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
99
100         DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
101
102         complete(&mcbsp_rx->rx_irq_completion);
103         return IRQ_HANDLED;
104 }
105
106
107 static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
108 {
109         struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
110
111         DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
112
113         /* We can free the channels */
114         omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
115         mcbsp_dma_tx->dma_tx_lch = -1;
116
117         complete(&mcbsp_dma_tx->tx_dma_completion);
118 }
119
120 static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
121 {
122         struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
123
124         DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
125
126         /* We can free the channels */
127         omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
128         mcbsp_dma_rx->dma_rx_lch = -1;
129
130         complete(&mcbsp_dma_rx->rx_dma_completion);
131 }
132
133
134 /*
135  * omap_mcbsp_config simply write a config to the
136  * appropriate McBSP.
137  * You either call this function or set the McBSP registers
138  * by yourself before calling omap_mcbsp_start().
139  */
140
141 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
142 {
143         u32 io_base = mcbsp[id].io_base;
144
145         DBG("OMAP-McBSP: McBSP%d  io_base: 0x%8x\n", id+1, io_base);
146
147         /* We write the given config */
148         OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
149         OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
150         OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
151         OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
152         OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
153         OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
154         OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
155         OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
156         OMAP_MCBSP_WRITE(io_base, SRGR2, config->mcr2);
157         OMAP_MCBSP_WRITE(io_base, SRGR1, config->mcr1);
158         OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
159 }
160
161
162
163 static int omap_mcbsp_check(unsigned int id)
164 {
165         if (cpu_is_omap730()) {
166                 if (id > OMAP_MAX_MCBSP_COUNT - 1) {
167                        printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
168                        return -1;
169                 }
170                 return 0;
171         }
172
173         if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
174                 if (id > OMAP_MAX_MCBSP_COUNT) {
175                         printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
176                         return -1;
177                 }
178                 return 0;
179         }
180
181         return -1;
182 }
183
184 #define DSP_RSTCT2              0xe1008014
185
186 static void omap_mcbsp_dsp_request(void)
187 {
188         if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
189                 omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
190                             ARM_RSTCT1);
191                 omap_writew((omap_readw(ARM_CKCTL) | 1 << EN_DSPCK),
192                             ARM_CKCTL);
193                 omap_writew((omap_readw(ARM_IDLECT2) | (1 << EN_APICK)),
194                             ARM_IDLECT2);
195
196                 /* enable 12MHz clock to mcbsp 1 & 3 */
197                 __raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
198                              DSP_IDLECT2);
199                 __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
200                              DSP_RSTCT2);
201         }
202 }
203
204 static void omap_mcbsp_dsp_free(void)
205 {
206         /* Useless for now */
207 }
208
209
210 int omap_mcbsp_request(unsigned int id)
211 {
212         int err;
213
214         if (omap_mcbsp_check(id) < 0)
215                 return -EINVAL;
216
217         /*
218          * On 1510, 1610 and 1710, McBSP1 and McBSP3
219          * are DSP public peripherals.
220          */
221         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
222                 omap_mcbsp_dsp_request();
223
224         spin_lock(&mcbsp[id].lock);
225         if (!mcbsp[id].free) {
226                 printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
227                 spin_unlock(&mcbsp[id].lock);
228                 return -1;
229         }
230
231         mcbsp[id].free = 0;
232         spin_unlock(&mcbsp[id].lock);
233
234         /* We need to get IRQs here */
235         err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
236                           "McBSP",
237                           (void *) (&mcbsp[id]));
238         if (err != 0) {
239                 printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
240                        mcbsp[id].tx_irq, mcbsp[id].id);
241                 return err;
242         }
243
244         init_completion(&(mcbsp[id].tx_irq_completion));
245
246
247         err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
248                           "McBSP",
249                           (void *) (&mcbsp[id]));
250         if (err != 0) {
251                 printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
252                        mcbsp[id].rx_irq, mcbsp[id].id);
253                 free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
254                 return err;
255         }
256
257         init_completion(&(mcbsp[id].rx_irq_completion));
258         return 0;
259
260 }
261
262 void omap_mcbsp_free(unsigned int id)
263 {
264         if (omap_mcbsp_check(id) < 0)
265                 return;
266
267         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
268                 omap_mcbsp_dsp_free();
269
270         spin_lock(&mcbsp[id].lock);
271         if (mcbsp[id].free) {
272                 printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
273                 spin_unlock(&mcbsp[id].lock);
274                 return;
275         }
276
277         mcbsp[id].free = 1;
278         spin_unlock(&mcbsp[id].lock);
279
280         /* Free IRQs */
281         free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
282         free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
283 }
284
285 /*
286  * Here we start the McBSP, by enabling the sample
287  * generator, both transmitter and receivers,
288  * and the frame sync.
289  */
290 void omap_mcbsp_start(unsigned int id)
291 {
292         u32 io_base;
293         u16 w;
294
295         if (omap_mcbsp_check(id) < 0)
296                 return;
297
298         io_base = mcbsp[id].io_base;
299
300         mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
301         mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
302
303         /* Start the sample generator */
304         w = OMAP_MCBSP_READ(io_base, SPCR2);
305         OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
306
307         /* Enable transmitter and receiver */
308         w = OMAP_MCBSP_READ(io_base, SPCR2);
309         OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
310
311         w = OMAP_MCBSP_READ(io_base, SPCR1);
312         OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
313
314         udelay(100);
315
316         /* Start frame sync */
317         w = OMAP_MCBSP_READ(io_base, SPCR2);
318         OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
319
320         /* Dump McBSP Regs */
321         omap_mcbsp_dump_reg(id);
322
323 }
324
325 void omap_mcbsp_stop(unsigned int id)
326 {
327         u32 io_base;
328         u16 w;
329
330         if (omap_mcbsp_check(id) < 0)
331                 return;
332
333         io_base = mcbsp[id].io_base;
334
335         /* Reset transmitter */
336         w = OMAP_MCBSP_READ(io_base, SPCR2);
337         OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
338
339         /* Reset receiver */
340         w = OMAP_MCBSP_READ(io_base, SPCR1);
341         OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
342
343         /* Reset the sample rate generator */
344         w = OMAP_MCBSP_READ(io_base, SPCR2);
345         OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
346 }
347
348
349 /*
350  * IRQ based word transmission.
351  */
352 void omap_mcbsp_xmit_word(unsigned int id, u32 word)
353 {
354         u32 io_base;
355         omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
356
357         if (omap_mcbsp_check(id) < 0)
358                 return;
359
360         io_base = mcbsp[id].io_base;
361
362         wait_for_completion(&(mcbsp[id].tx_irq_completion));
363
364         if (word_length > OMAP_MCBSP_WORD_16)
365                 OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
366         OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
367 }
368
369 u32 omap_mcbsp_recv_word(unsigned int id)
370 {
371         u32 io_base;
372         u16 word_lsb, word_msb = 0;
373         omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
374
375         if (omap_mcbsp_check(id) < 0)
376                 return -EINVAL;
377
378         io_base = mcbsp[id].io_base;
379
380         wait_for_completion(&(mcbsp[id].rx_irq_completion));
381
382         if (word_length > OMAP_MCBSP_WORD_16)
383                 word_msb = OMAP_MCBSP_READ(io_base, DRR2);
384         word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
385
386         return (word_lsb | (word_msb << 16));
387 }
388
389
390 /*
391  * Simple DMA based buffer rx/tx routines.
392  * Nothing fancy, just a single buffer tx/rx through DMA.
393  * The DMA resources are released once the transfer is done.
394  * For anything fancier, you should use your own customized DMA
395  * routines and callbacks.
396  */
397 int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
398 {
399         int dma_tx_ch;
400
401         if (omap_mcbsp_check(id) < 0)
402                 return -EINVAL;
403
404         if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
405                              &mcbsp[id],
406                              &dma_tx_ch)) {
407                 printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
408                 return -EAGAIN;
409         }
410         mcbsp[id].dma_tx_lch = dma_tx_ch;
411
412         DBG("TX DMA on channel %d\n", dma_tx_ch);
413
414         init_completion(&(mcbsp[id].tx_dma_completion));
415
416         omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
417                                      OMAP_DMA_DATA_TYPE_S16,
418                                      length >> 1, 1,
419                                      OMAP_DMA_SYNC_ELEMENT);
420
421         omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
422                                  OMAP_DMA_PORT_TIPB,
423                                  OMAP_DMA_AMODE_CONSTANT,
424                                  mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1);
425
426         omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
427                                 OMAP_DMA_PORT_EMIFF,
428                                 OMAP_DMA_AMODE_POST_INC,
429                                 buffer);
430
431         omap_start_dma(mcbsp[id].dma_tx_lch);
432         wait_for_completion(&(mcbsp[id].tx_dma_completion));
433         return 0;
434 }
435
436
437 int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
438 {
439         int dma_rx_ch;
440
441         if (omap_mcbsp_check(id) < 0)
442                 return -EINVAL;
443
444         if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
445                              &mcbsp[id],
446                              &dma_rx_ch)) {
447                 printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
448                 return -EAGAIN;
449         }
450         mcbsp[id].dma_rx_lch = dma_rx_ch;
451
452         DBG("RX DMA on channel %d\n", dma_rx_ch);
453
454         init_completion(&(mcbsp[id].rx_dma_completion));
455
456         omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
457                                      OMAP_DMA_DATA_TYPE_S16,
458                                      length >> 1, 1,
459                                      OMAP_DMA_SYNC_ELEMENT);
460
461         omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
462                                 OMAP_DMA_PORT_TIPB,
463                                 OMAP_DMA_AMODE_CONSTANT,
464                                 mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1);
465
466         omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
467                                  OMAP_DMA_PORT_EMIFF,
468                                  OMAP_DMA_AMODE_POST_INC,
469                                  buffer);
470
471         omap_start_dma(mcbsp[id].dma_rx_lch);
472         wait_for_completion(&(mcbsp[id].rx_dma_completion));
473         return 0;
474 }
475
476
477 /*
478  * SPI wrapper.
479  * Since SPI setup is much simpler than the generic McBSP one,
480  * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
481  * Once this is done, you can call omap_mcbsp_start().
482  */
483 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
484 {
485         struct omap_mcbsp_reg_cfg mcbsp_cfg;
486
487         if (omap_mcbsp_check(id) < 0)
488                 return;
489
490         memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
491
492         /* SPI has only one frame */
493         mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
494         mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
495
496         /* Clock stop mode */
497         if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
498                 mcbsp_cfg.spcr1 |= (1 << 12);
499         else
500                 mcbsp_cfg.spcr1 |= (3 << 11);
501
502         /* Set clock parities */
503         if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
504                 mcbsp_cfg.pcr0 |= CLKRP;
505         else
506                 mcbsp_cfg.pcr0 &= ~CLKRP;
507
508         if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
509                 mcbsp_cfg.pcr0 &= ~CLKXP;
510         else
511                 mcbsp_cfg.pcr0 |= CLKXP;
512
513         /* Set SCLKME to 0 and CLKSM to 1 */
514         mcbsp_cfg.pcr0 &= ~SCLKME;
515         mcbsp_cfg.srgr2 |= CLKSM;
516
517         /* Set FSXP */
518         if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
519                 mcbsp_cfg.pcr0 &= ~FSXP;
520         else
521                 mcbsp_cfg.pcr0 |= FSXP;
522
523         if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
524                 mcbsp_cfg.pcr0 |= CLKXM;
525                 mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
526                 mcbsp_cfg.pcr0 |= FSXM;
527                 mcbsp_cfg.srgr2 &= ~FSGM;
528                 mcbsp_cfg.xcr2 |= XDATDLY(1);
529                 mcbsp_cfg.rcr2 |= RDATDLY(1);
530         }
531         else {
532                 mcbsp_cfg.pcr0 &= ~CLKXM;
533                 mcbsp_cfg.srgr1 |= CLKGDV(1);
534                 mcbsp_cfg.pcr0 &= ~FSXM;
535                 mcbsp_cfg.xcr2 &= ~XDATDLY(3);
536                 mcbsp_cfg.rcr2 &= ~RDATDLY(3);
537         }
538
539         mcbsp_cfg.xcr2 &= ~XPHASE;
540         mcbsp_cfg.rcr2 &= ~RPHASE;
541
542         omap_mcbsp_config(id, &mcbsp_cfg);
543 }
544
545
546 /*
547  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
548  * 730 has only 2 McBSP, and both of them are MPU peripherals.
549  */
550 struct omap_mcbsp_info {
551         u32 virt_base;
552         u8 dma_rx_sync, dma_tx_sync;
553         u16 rx_irq, tx_irq;
554 };
555
556 #ifdef CONFIG_ARCH_OMAP730
557 static const struct omap_mcbsp_info mcbsp_730[] = {
558         [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
559                 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
560                 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
561                 .rx_irq = INT_730_McBSP1RX,
562                 .tx_irq = INT_730_McBSP1TX },
563         [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
564                 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
565                 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
566                 .rx_irq = INT_730_McBSP2RX,
567                 .tx_irq = INT_730_McBSP2TX },
568 };
569 #endif
570
571 #ifdef CONFIG_ARCH_OMAP1510
572 static const struct omap_mcbsp_info mcbsp_1510[] = {
573         [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
574                 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
575                 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
576                 .rx_irq = INT_McBSP1RX,
577                 .tx_irq = INT_McBSP1TX },
578         [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
579                 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
580                 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
581                 .rx_irq = INT_1510_SPI_RX,
582                 .tx_irq = INT_1510_SPI_TX },
583         [2] = { .virt_base = OMAP1510_MCBSP3_BASE,
584                 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
585                 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
586                 .rx_irq = INT_McBSP3RX,
587                 .tx_irq = INT_McBSP3TX },
588 };
589 #endif
590
591 #if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
592 static const struct omap_mcbsp_info mcbsp_1610[] = {
593         [0] = { .virt_base = OMAP1610_MCBSP1_BASE,
594                 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
595                 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
596                 .rx_irq = INT_McBSP1RX,
597                 .tx_irq = INT_McBSP1TX },
598         [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
599                 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
600                 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
601                 .rx_irq = INT_1610_McBSP2_RX,
602                 .tx_irq = INT_1610_McBSP2_TX },
603         [2] = { .virt_base = OMAP1610_MCBSP3_BASE,
604                 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
605                 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
606                 .rx_irq = INT_McBSP3RX,
607                 .tx_irq = INT_McBSP3TX },
608 };
609 #endif
610
611 static int __init omap_mcbsp_init(void)
612 {
613         int mcbsp_count = 0, i;
614         static const struct omap_mcbsp_info *mcbsp_info;
615
616         printk("Initializing OMAP McBSP system\n");
617 #ifdef CONFIG_ARCH_OMAP730
618         if (cpu_is_omap730()) {
619                 mcbsp_info = mcbsp_730;
620                 mcbsp_count = ARRAY_SIZE(mcbsp_730);
621         }
622 #endif
623 #ifdef CONFIG_ARCH_OMAP1510
624         if (cpu_is_omap1510()) {
625                 mcbsp_info = mcbsp_1510;
626                 mcbsp_count = ARRAY_SIZE(mcbsp_1510);
627         }
628 #endif
629 #if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
630         if (cpu_is_omap1610() || cpu_is_omap1710()) {
631                 mcbsp_info = mcbsp_1610;
632                 mcbsp_count = ARRAY_SIZE(mcbsp_1610);
633         }
634 #endif
635         for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
636                 if (i >= mcbsp_count) {
637                         mcbsp[i].io_base = 0;
638                         mcbsp[i].free = 0;
639                         continue;
640                 }
641                 mcbsp[i].id = i + 1;
642                 mcbsp[i].free = 1;
643                 mcbsp[i].dma_tx_lch = -1;
644                 mcbsp[i].dma_rx_lch = -1;
645
646                 mcbsp[i].io_base = mcbsp_info[i].virt_base;
647                 mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
648                 mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
649                 mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
650                 mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
651                 spin_lock_init(&mcbsp[i].lock);
652         }
653
654         return 0;
655 }
656
657
658 arch_initcall(omap_mcbsp_init);
659
660 EXPORT_SYMBOL(omap_mcbsp_config);
661 EXPORT_SYMBOL(omap_mcbsp_request);
662 EXPORT_SYMBOL(omap_mcbsp_free);
663 EXPORT_SYMBOL(omap_mcbsp_start);
664 EXPORT_SYMBOL(omap_mcbsp_stop);
665 EXPORT_SYMBOL(omap_mcbsp_xmit_word);
666 EXPORT_SYMBOL(omap_mcbsp_recv_word);
667 EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
668 EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
669 EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);