2 * linux/arch/arm/omap/mcbsp.c
4 * Copyright (C) 2004 Nokia Corporation
5 * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
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.
12 * Multichannel mode not supported.
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 #include <linux/err.h>
23 #include <asm/delay.h>
27 #include <asm/arch/dma.h>
28 #include <asm/arch/mux.h>
29 #include <asm/arch/irqs.h>
30 #include <asm/arch/mcbsp.h>
32 #include <asm/hardware/clock.h>
34 #ifdef CONFIG_MCBSP_DEBUG
35 #define DBG(x...) printk(x)
37 #define DBG(x...) do { } while (0)
44 omap_mcbsp_word_length rx_word_length
;
45 omap_mcbsp_word_length tx_word_length
;
57 /* Completion queues */
58 struct completion tx_irq_completion
;
59 struct completion rx_irq_completion
;
60 struct completion tx_dma_completion
;
61 struct completion rx_dma_completion
;
66 static struct omap_mcbsp mcbsp
[OMAP_MAX_MCBSP_COUNT
];
67 static struct clk
*mcbsp_dsp_ck
= 0;
68 static struct clk
*mcbsp_api_ck
= 0;
71 static void omap_mcbsp_dump_reg(u8 id
)
73 DBG("**** MCBSP%d regs ****\n", mcbsp
[id
].id
);
74 DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, DRR2
));
75 DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, DRR1
));
76 DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, DXR2
));
77 DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, DXR1
));
78 DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, SPCR2
));
79 DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, SPCR1
));
80 DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, RCR2
));
81 DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, RCR1
));
82 DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, XCR2
));
83 DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, XCR1
));
84 DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, SRGR2
));
85 DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, SRGR1
));
86 DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp
[id
].io_base
, PCR0
));
87 DBG("***********************\n");
91 static irqreturn_t
omap_mcbsp_tx_irq_handler(int irq
, void *dev_id
, struct pt_regs
*regs
)
93 struct omap_mcbsp
* mcbsp_tx
= (struct omap_mcbsp
*)(dev_id
);
95 DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx
->io_base
, SPCR2
));
97 complete(&mcbsp_tx
->tx_irq_completion
);
101 static irqreturn_t
omap_mcbsp_rx_irq_handler(int irq
, void *dev_id
, struct pt_regs
*regs
)
103 struct omap_mcbsp
* mcbsp_rx
= (struct omap_mcbsp
*)(dev_id
);
105 DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx
->io_base
, SPCR2
));
107 complete(&mcbsp_rx
->rx_irq_completion
);
112 static void omap_mcbsp_tx_dma_callback(int lch
, u16 ch_status
, void *data
)
114 struct omap_mcbsp
* mcbsp_dma_tx
= (struct omap_mcbsp
*)(data
);
116 DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx
->io_base
, SPCR2
));
118 /* We can free the channels */
119 omap_free_dma(mcbsp_dma_tx
->dma_tx_lch
);
120 mcbsp_dma_tx
->dma_tx_lch
= -1;
122 complete(&mcbsp_dma_tx
->tx_dma_completion
);
125 static void omap_mcbsp_rx_dma_callback(int lch
, u16 ch_status
, void *data
)
127 struct omap_mcbsp
* mcbsp_dma_rx
= (struct omap_mcbsp
*)(data
);
129 DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx
->io_base
, SPCR2
));
131 /* We can free the channels */
132 omap_free_dma(mcbsp_dma_rx
->dma_rx_lch
);
133 mcbsp_dma_rx
->dma_rx_lch
= -1;
135 complete(&mcbsp_dma_rx
->rx_dma_completion
);
140 * omap_mcbsp_config simply write a config to the
142 * You either call this function or set the McBSP registers
143 * by yourself before calling omap_mcbsp_start().
146 void omap_mcbsp_config(unsigned int id
, const struct omap_mcbsp_reg_cfg
* config
)
148 u32 io_base
= mcbsp
[id
].io_base
;
150 DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id
+1, io_base
);
152 /* We write the given config */
153 OMAP_MCBSP_WRITE(io_base
, SPCR2
, config
->spcr2
);
154 OMAP_MCBSP_WRITE(io_base
, SPCR1
, config
->spcr1
);
155 OMAP_MCBSP_WRITE(io_base
, RCR2
, config
->rcr2
);
156 OMAP_MCBSP_WRITE(io_base
, RCR1
, config
->rcr1
);
157 OMAP_MCBSP_WRITE(io_base
, XCR2
, config
->xcr2
);
158 OMAP_MCBSP_WRITE(io_base
, XCR1
, config
->xcr1
);
159 OMAP_MCBSP_WRITE(io_base
, SRGR2
, config
->srgr2
);
160 OMAP_MCBSP_WRITE(io_base
, SRGR1
, config
->srgr1
);
161 OMAP_MCBSP_WRITE(io_base
, MCR2
, config
->mcr2
);
162 OMAP_MCBSP_WRITE(io_base
, MCR1
, config
->mcr1
);
163 OMAP_MCBSP_WRITE(io_base
, PCR0
, config
->pcr0
);
168 static int omap_mcbsp_check(unsigned int id
)
170 if (cpu_is_omap730()) {
171 if (id
> OMAP_MAX_MCBSP_COUNT
- 1) {
172 printk(KERN_ERR
"OMAP-McBSP: McBSP%d doesn't exist\n", id
+ 1);
178 if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
179 if (id
> OMAP_MAX_MCBSP_COUNT
) {
180 printk(KERN_ERR
"OMAP-McBSP: McBSP%d doesn't exist\n", id
+ 1);
190 #define DSP_RSTCT2 0xe1008014
192 static void omap_mcbsp_dsp_request(void)
194 if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
195 omap_writew((omap_readw(ARM_RSTCT1
) | (1 << 1) | (1 << 2)),
197 clk_enable(mcbsp_dsp_ck
);
198 clk_enable(mcbsp_api_ck
);
200 /* enable 12MHz clock to mcbsp 1 & 3 */
201 __raw_writew(__raw_readw(DSP_IDLECT2
) | (1 << EN_XORPCK
),
203 __raw_writew(__raw_readw(DSP_RSTCT2
) | 1 | 1 << 1,
208 static void omap_mcbsp_dsp_free(void)
210 /* Useless for now */
214 int omap_mcbsp_request(unsigned int id
)
218 if (omap_mcbsp_check(id
) < 0)
222 * On 1510, 1610 and 1710, McBSP1 and McBSP3
223 * are DSP public peripherals.
225 if (id
== OMAP_MCBSP1
|| id
== OMAP_MCBSP3
)
226 omap_mcbsp_dsp_request();
228 spin_lock(&mcbsp
[id
].lock
);
229 if (!mcbsp
[id
].free
) {
230 printk (KERN_ERR
"OMAP-McBSP: McBSP%d is currently in use\n", id
+ 1);
231 spin_unlock(&mcbsp
[id
].lock
);
236 spin_unlock(&mcbsp
[id
].lock
);
238 /* We need to get IRQs here */
239 err
= request_irq(mcbsp
[id
].tx_irq
, omap_mcbsp_tx_irq_handler
, 0,
241 (void *) (&mcbsp
[id
]));
243 printk(KERN_ERR
"OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
244 mcbsp
[id
].tx_irq
, mcbsp
[id
].id
);
248 init_completion(&(mcbsp
[id
].tx_irq_completion
));
251 err
= request_irq(mcbsp
[id
].rx_irq
, omap_mcbsp_rx_irq_handler
, 0,
253 (void *) (&mcbsp
[id
]));
255 printk(KERN_ERR
"OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
256 mcbsp
[id
].rx_irq
, mcbsp
[id
].id
);
257 free_irq(mcbsp
[id
].tx_irq
, (void *) (&mcbsp
[id
]));
261 init_completion(&(mcbsp
[id
].rx_irq_completion
));
266 void omap_mcbsp_free(unsigned int id
)
268 if (omap_mcbsp_check(id
) < 0)
271 if (id
== OMAP_MCBSP1
|| id
== OMAP_MCBSP3
)
272 omap_mcbsp_dsp_free();
274 spin_lock(&mcbsp
[id
].lock
);
275 if (mcbsp
[id
].free
) {
276 printk (KERN_ERR
"OMAP-McBSP: McBSP%d was not reserved\n", id
+ 1);
277 spin_unlock(&mcbsp
[id
].lock
);
282 spin_unlock(&mcbsp
[id
].lock
);
285 free_irq(mcbsp
[id
].rx_irq
, (void *) (&mcbsp
[id
]));
286 free_irq(mcbsp
[id
].tx_irq
, (void *) (&mcbsp
[id
]));
290 * Here we start the McBSP, by enabling the sample
291 * generator, both transmitter and receivers,
292 * and the frame sync.
294 void omap_mcbsp_start(unsigned int id
)
299 if (omap_mcbsp_check(id
) < 0)
302 io_base
= mcbsp
[id
].io_base
;
304 mcbsp
[id
].rx_word_length
= ((OMAP_MCBSP_READ(io_base
, RCR1
) >> 5) & 0x7);
305 mcbsp
[id
].tx_word_length
= ((OMAP_MCBSP_READ(io_base
, XCR1
) >> 5) & 0x7);
307 /* Start the sample generator */
308 w
= OMAP_MCBSP_READ(io_base
, SPCR2
);
309 OMAP_MCBSP_WRITE(io_base
, SPCR2
, w
| (1 << 6));
311 /* Enable transmitter and receiver */
312 w
= OMAP_MCBSP_READ(io_base
, SPCR2
);
313 OMAP_MCBSP_WRITE(io_base
, SPCR2
, w
| 1);
315 w
= OMAP_MCBSP_READ(io_base
, SPCR1
);
316 OMAP_MCBSP_WRITE(io_base
, SPCR1
, w
| 1);
320 /* Start frame sync */
321 w
= OMAP_MCBSP_READ(io_base
, SPCR2
);
322 OMAP_MCBSP_WRITE(io_base
, SPCR2
, w
| (1 << 7));
324 /* Dump McBSP Regs */
325 omap_mcbsp_dump_reg(id
);
329 void omap_mcbsp_stop(unsigned int id
)
334 if (omap_mcbsp_check(id
) < 0)
337 io_base
= mcbsp
[id
].io_base
;
339 /* Reset transmitter */
340 w
= OMAP_MCBSP_READ(io_base
, SPCR2
);
341 OMAP_MCBSP_WRITE(io_base
, SPCR2
, w
& ~(1));
344 w
= OMAP_MCBSP_READ(io_base
, SPCR1
);
345 OMAP_MCBSP_WRITE(io_base
, SPCR1
, w
& ~(1));
347 /* Reset the sample rate generator */
348 w
= OMAP_MCBSP_READ(io_base
, SPCR2
);
349 OMAP_MCBSP_WRITE(io_base
, SPCR2
, w
& ~(1 << 6));
354 * IRQ based word transmission.
356 void omap_mcbsp_xmit_word(unsigned int id
, u32 word
)
359 omap_mcbsp_word_length word_length
= mcbsp
[id
].tx_word_length
;
361 if (omap_mcbsp_check(id
) < 0)
364 io_base
= mcbsp
[id
].io_base
;
366 wait_for_completion(&(mcbsp
[id
].tx_irq_completion
));
368 if (word_length
> OMAP_MCBSP_WORD_16
)
369 OMAP_MCBSP_WRITE(io_base
, DXR2
, word
>> 16);
370 OMAP_MCBSP_WRITE(io_base
, DXR1
, word
& 0xffff);
373 u32
omap_mcbsp_recv_word(unsigned int id
)
376 u16 word_lsb
, word_msb
= 0;
377 omap_mcbsp_word_length word_length
= mcbsp
[id
].rx_word_length
;
379 if (omap_mcbsp_check(id
) < 0)
382 io_base
= mcbsp
[id
].io_base
;
384 wait_for_completion(&(mcbsp
[id
].rx_irq_completion
));
386 if (word_length
> OMAP_MCBSP_WORD_16
)
387 word_msb
= OMAP_MCBSP_READ(io_base
, DRR2
);
388 word_lsb
= OMAP_MCBSP_READ(io_base
, DRR1
);
390 return (word_lsb
| (word_msb
<< 16));
395 * Simple DMA based buffer rx/tx routines.
396 * Nothing fancy, just a single buffer tx/rx through DMA.
397 * The DMA resources are released once the transfer is done.
398 * For anything fancier, you should use your own customized DMA
399 * routines and callbacks.
401 int omap_mcbsp_xmit_buffer(unsigned int id
, dma_addr_t buffer
, unsigned int length
)
405 if (omap_mcbsp_check(id
) < 0)
408 if (omap_request_dma(mcbsp
[id
].dma_tx_sync
, "McBSP TX", omap_mcbsp_tx_dma_callback
,
411 printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id
+1);
414 mcbsp
[id
].dma_tx_lch
= dma_tx_ch
;
416 DBG("TX DMA on channel %d\n", dma_tx_ch
);
418 init_completion(&(mcbsp
[id
].tx_dma_completion
));
420 omap_set_dma_transfer_params(mcbsp
[id
].dma_tx_lch
,
421 OMAP_DMA_DATA_TYPE_S16
,
423 OMAP_DMA_SYNC_ELEMENT
);
425 omap_set_dma_dest_params(mcbsp
[id
].dma_tx_lch
,
427 OMAP_DMA_AMODE_CONSTANT
,
428 mcbsp
[id
].io_base
+ OMAP_MCBSP_REG_DXR1
);
430 omap_set_dma_src_params(mcbsp
[id
].dma_tx_lch
,
432 OMAP_DMA_AMODE_POST_INC
,
435 omap_start_dma(mcbsp
[id
].dma_tx_lch
);
436 wait_for_completion(&(mcbsp
[id
].tx_dma_completion
));
441 int omap_mcbsp_recv_buffer(unsigned int id
, dma_addr_t buffer
, unsigned int length
)
445 if (omap_mcbsp_check(id
) < 0)
448 if (omap_request_dma(mcbsp
[id
].dma_rx_sync
, "McBSP RX", omap_mcbsp_rx_dma_callback
,
451 printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id
+1);
454 mcbsp
[id
].dma_rx_lch
= dma_rx_ch
;
456 DBG("RX DMA on channel %d\n", dma_rx_ch
);
458 init_completion(&(mcbsp
[id
].rx_dma_completion
));
460 omap_set_dma_transfer_params(mcbsp
[id
].dma_rx_lch
,
461 OMAP_DMA_DATA_TYPE_S16
,
463 OMAP_DMA_SYNC_ELEMENT
);
465 omap_set_dma_src_params(mcbsp
[id
].dma_rx_lch
,
467 OMAP_DMA_AMODE_CONSTANT
,
468 mcbsp
[id
].io_base
+ OMAP_MCBSP_REG_DRR1
);
470 omap_set_dma_dest_params(mcbsp
[id
].dma_rx_lch
,
472 OMAP_DMA_AMODE_POST_INC
,
475 omap_start_dma(mcbsp
[id
].dma_rx_lch
);
476 wait_for_completion(&(mcbsp
[id
].rx_dma_completion
));
483 * Since SPI setup is much simpler than the generic McBSP one,
484 * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
485 * Once this is done, you can call omap_mcbsp_start().
487 void omap_mcbsp_set_spi_mode(unsigned int id
, const struct omap_mcbsp_spi_cfg
* spi_cfg
)
489 struct omap_mcbsp_reg_cfg mcbsp_cfg
;
491 if (omap_mcbsp_check(id
) < 0)
494 memset(&mcbsp_cfg
, 0, sizeof(struct omap_mcbsp_reg_cfg
));
496 /* SPI has only one frame */
497 mcbsp_cfg
.rcr1
|= (RWDLEN1(spi_cfg
->word_length
) | RFRLEN1(0));
498 mcbsp_cfg
.xcr1
|= (XWDLEN1(spi_cfg
->word_length
) | XFRLEN1(0));
500 /* Clock stop mode */
501 if (spi_cfg
->clk_stp_mode
== OMAP_MCBSP_CLK_STP_MODE_NO_DELAY
)
502 mcbsp_cfg
.spcr1
|= (1 << 12);
504 mcbsp_cfg
.spcr1
|= (3 << 11);
506 /* Set clock parities */
507 if (spi_cfg
->rx_clock_polarity
== OMAP_MCBSP_CLK_RISING
)
508 mcbsp_cfg
.pcr0
|= CLKRP
;
510 mcbsp_cfg
.pcr0
&= ~CLKRP
;
512 if (spi_cfg
->tx_clock_polarity
== OMAP_MCBSP_CLK_RISING
)
513 mcbsp_cfg
.pcr0
&= ~CLKXP
;
515 mcbsp_cfg
.pcr0
|= CLKXP
;
517 /* Set SCLKME to 0 and CLKSM to 1 */
518 mcbsp_cfg
.pcr0
&= ~SCLKME
;
519 mcbsp_cfg
.srgr2
|= CLKSM
;
522 if (spi_cfg
->fsx_polarity
== OMAP_MCBSP_FS_ACTIVE_HIGH
)
523 mcbsp_cfg
.pcr0
&= ~FSXP
;
525 mcbsp_cfg
.pcr0
|= FSXP
;
527 if (spi_cfg
->spi_mode
== OMAP_MCBSP_SPI_MASTER
) {
528 mcbsp_cfg
.pcr0
|= CLKXM
;
529 mcbsp_cfg
.srgr1
|= CLKGDV(spi_cfg
->clk_div
-1);
530 mcbsp_cfg
.pcr0
|= FSXM
;
531 mcbsp_cfg
.srgr2
&= ~FSGM
;
532 mcbsp_cfg
.xcr2
|= XDATDLY(1);
533 mcbsp_cfg
.rcr2
|= RDATDLY(1);
536 mcbsp_cfg
.pcr0
&= ~CLKXM
;
537 mcbsp_cfg
.srgr1
|= CLKGDV(1);
538 mcbsp_cfg
.pcr0
&= ~FSXM
;
539 mcbsp_cfg
.xcr2
&= ~XDATDLY(3);
540 mcbsp_cfg
.rcr2
&= ~RDATDLY(3);
543 mcbsp_cfg
.xcr2
&= ~XPHASE
;
544 mcbsp_cfg
.rcr2
&= ~RPHASE
;
546 omap_mcbsp_config(id
, &mcbsp_cfg
);
551 * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
552 * 730 has only 2 McBSP, and both of them are MPU peripherals.
554 struct omap_mcbsp_info
{
556 u8 dma_rx_sync
, dma_tx_sync
;
560 #ifdef CONFIG_ARCH_OMAP730
561 static const struct omap_mcbsp_info mcbsp_730
[] = {
562 [0] = { .virt_base
= io_p2v(OMAP730_MCBSP1_BASE
),
563 .dma_rx_sync
= OMAP_DMA_MCBSP1_RX
,
564 .dma_tx_sync
= OMAP_DMA_MCBSP1_TX
,
565 .rx_irq
= INT_730_McBSP1RX
,
566 .tx_irq
= INT_730_McBSP1TX
},
567 [1] = { .virt_base
= io_p2v(OMAP730_MCBSP2_BASE
),
568 .dma_rx_sync
= OMAP_DMA_MCBSP3_RX
,
569 .dma_tx_sync
= OMAP_DMA_MCBSP3_TX
,
570 .rx_irq
= INT_730_McBSP2RX
,
571 .tx_irq
= INT_730_McBSP2TX
},
575 #ifdef CONFIG_ARCH_OMAP1510
576 static const struct omap_mcbsp_info mcbsp_1510
[] = {
577 [0] = { .virt_base
= OMAP1510_MCBSP1_BASE
,
578 .dma_rx_sync
= OMAP_DMA_MCBSP1_RX
,
579 .dma_tx_sync
= OMAP_DMA_MCBSP1_TX
,
580 .rx_irq
= INT_McBSP1RX
,
581 .tx_irq
= INT_McBSP1TX
},
582 [1] = { .virt_base
= io_p2v(OMAP1510_MCBSP2_BASE
),
583 .dma_rx_sync
= OMAP_DMA_MCBSP2_RX
,
584 .dma_tx_sync
= OMAP_DMA_MCBSP2_TX
,
585 .rx_irq
= INT_1510_SPI_RX
,
586 .tx_irq
= INT_1510_SPI_TX
},
587 [2] = { .virt_base
= OMAP1510_MCBSP3_BASE
,
588 .dma_rx_sync
= OMAP_DMA_MCBSP3_RX
,
589 .dma_tx_sync
= OMAP_DMA_MCBSP3_TX
,
590 .rx_irq
= INT_McBSP3RX
,
591 .tx_irq
= INT_McBSP3TX
},
595 #if defined(CONFIG_ARCH_OMAP16XX)
596 static const struct omap_mcbsp_info mcbsp_1610
[] = {
597 [0] = { .virt_base
= OMAP1610_MCBSP1_BASE
,
598 .dma_rx_sync
= OMAP_DMA_MCBSP1_RX
,
599 .dma_tx_sync
= OMAP_DMA_MCBSP1_TX
,
600 .rx_irq
= INT_McBSP1RX
,
601 .tx_irq
= INT_McBSP1TX
},
602 [1] = { .virt_base
= io_p2v(OMAP1610_MCBSP2_BASE
),
603 .dma_rx_sync
= OMAP_DMA_MCBSP2_RX
,
604 .dma_tx_sync
= OMAP_DMA_MCBSP2_TX
,
605 .rx_irq
= INT_1610_McBSP2_RX
,
606 .tx_irq
= INT_1610_McBSP2_TX
},
607 [2] = { .virt_base
= OMAP1610_MCBSP3_BASE
,
608 .dma_rx_sync
= OMAP_DMA_MCBSP3_RX
,
609 .dma_tx_sync
= OMAP_DMA_MCBSP3_TX
,
610 .rx_irq
= INT_McBSP3RX
,
611 .tx_irq
= INT_McBSP3TX
},
615 static int __init
omap_mcbsp_init(void)
617 int mcbsp_count
= 0, i
;
618 static const struct omap_mcbsp_info
*mcbsp_info
;
620 printk("Initializing OMAP McBSP system\n");
622 mcbsp_dsp_ck
= clk_get(0, "dsp_ck");
623 if (IS_ERR(mcbsp_dsp_ck
)) {
624 printk(KERN_ERR
"mcbsp: could not acquire dsp_ck handle.\n");
625 return PTR_ERR(mcbsp_dsp_ck
);
627 mcbsp_api_ck
= clk_get(0, "api_ck");
628 if (IS_ERR(mcbsp_dsp_ck
)) {
629 printk(KERN_ERR
"mcbsp: could not acquire api_ck handle.\n");
630 return PTR_ERR(mcbsp_api_ck
);
633 #ifdef CONFIG_ARCH_OMAP730
634 if (cpu_is_omap730()) {
635 mcbsp_info
= mcbsp_730
;
636 mcbsp_count
= ARRAY_SIZE(mcbsp_730
);
639 #ifdef CONFIG_ARCH_OMAP1510
640 if (cpu_is_omap1510()) {
641 mcbsp_info
= mcbsp_1510
;
642 mcbsp_count
= ARRAY_SIZE(mcbsp_1510
);
645 #if defined(CONFIG_ARCH_OMAP16XX)
646 if (cpu_is_omap1610() || cpu_is_omap1710()) {
647 mcbsp_info
= mcbsp_1610
;
648 mcbsp_count
= ARRAY_SIZE(mcbsp_1610
);
651 for (i
= 0; i
< OMAP_MAX_MCBSP_COUNT
; i
++) {
652 if (i
>= mcbsp_count
) {
653 mcbsp
[i
].io_base
= 0;
659 mcbsp
[i
].dma_tx_lch
= -1;
660 mcbsp
[i
].dma_rx_lch
= -1;
662 mcbsp
[i
].io_base
= mcbsp_info
[i
].virt_base
;
663 mcbsp
[i
].tx_irq
= mcbsp_info
[i
].tx_irq
;
664 mcbsp
[i
].rx_irq
= mcbsp_info
[i
].rx_irq
;
665 mcbsp
[i
].dma_rx_sync
= mcbsp_info
[i
].dma_rx_sync
;
666 mcbsp
[i
].dma_tx_sync
= mcbsp_info
[i
].dma_tx_sync
;
667 spin_lock_init(&mcbsp
[i
].lock
);
674 arch_initcall(omap_mcbsp_init
);
676 EXPORT_SYMBOL(omap_mcbsp_config
);
677 EXPORT_SYMBOL(omap_mcbsp_request
);
678 EXPORT_SYMBOL(omap_mcbsp_free
);
679 EXPORT_SYMBOL(omap_mcbsp_start
);
680 EXPORT_SYMBOL(omap_mcbsp_stop
);
681 EXPORT_SYMBOL(omap_mcbsp_xmit_word
);
682 EXPORT_SYMBOL(omap_mcbsp_recv_word
);
683 EXPORT_SYMBOL(omap_mcbsp_xmit_buffer
);
684 EXPORT_SYMBOL(omap_mcbsp_recv_buffer
);
685 EXPORT_SYMBOL(omap_mcbsp_set_spi_mode
);