]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/mcbsp.c
Merge with /home/tmlind/src/kernel/linux-2.6
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / mcbsp.c
1 /*
2  * linux/arch/arm/plat-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 #include <linux/err.h>
22 #include <linux/clk.h>
23
24 #include <asm/delay.h>
25 #include <asm/io.h>
26 #include <asm/irq.h>
27
28 #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>
33
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         /* IRQ based TX/RX */
48         int                          rx_irq;
49         int                          tx_irq;
50
51         /* DMA stuff */
52         u8                           dma_rx_sync;
53         short                        dma_rx_lch;
54         u8                           dma_tx_sync;
55         short                        dma_tx_lch;
56
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;
62
63         spinlock_t                   lock;
64 };
65
66 static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
67 #ifdef CONFIG_ARCH_OMAP1
68 static struct clk *mcbsp_dsp_ck = 0;
69 static struct clk *mcbsp_api_ck = 0;
70 static struct clk *mcbsp_dspxor_ck = 0;
71 #endif
72 #ifdef CONFIG_ARCH_OMAP2
73 static struct clk *mcbsp1_ick = 0;
74 static struct clk *mcbsp1_fck = 0;
75 static struct clk *mcbsp2_ick = 0;
76 static struct clk *mcbsp2_fck = 0;
77 static struct clk *sys_ck = 0;
78 static struct clk *sys_clkout = 0;
79 #endif
80
81 static void omap_mcbsp_dump_reg(u8 id)
82 {
83         DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
84         DBG("DRR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
85         DBG("DRR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
86         DBG("DXR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
87         DBG("DXR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
88         DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
89         DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
90         DBG("RCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
91         DBG("RCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
92         DBG("XCR2:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
93         DBG("XCR1:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
94         DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
95         DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
96         DBG("PCR0:  0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
97         DBG("***********************\n");
98 }
99
100 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
101 {
102         struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
103
104         DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
105
106         complete(&mcbsp_tx->tx_irq_completion);
107         return IRQ_HANDLED;
108 }
109
110 static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
111 {
112         struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
113
114         DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
115
116         complete(&mcbsp_rx->rx_irq_completion);
117         return IRQ_HANDLED;
118 }
119
120 static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
121 {
122         struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
123
124         DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
125
126         /* We can free the channels */
127         omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
128         mcbsp_dma_tx->dma_tx_lch = -1;
129
130         complete(&mcbsp_dma_tx->tx_dma_completion);
131 }
132
133 static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
134 {
135         struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
136
137         DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
138
139         /* We can free the channels */
140         omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
141         mcbsp_dma_rx->dma_rx_lch = -1;
142
143         complete(&mcbsp_dma_rx->rx_dma_completion);
144 }
145
146
147 /*
148  * omap_mcbsp_config simply write a config to the
149  * appropriate McBSP.
150  * You either call this function or set the McBSP registers
151  * by yourself before calling omap_mcbsp_start().
152  */
153
154 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
155 {
156         u32 io_base = mcbsp[id].io_base;
157
158         DBG("OMAP-McBSP: McBSP%d  io_base: 0x%8x\n", id+1, io_base);
159
160         /* We write the given config */
161         OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
162         OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
163         OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
164         OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
165         OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
166         OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
167         OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
168         OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
169         OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
170         OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
171         OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
172 }
173
174
175
176 static int omap_mcbsp_check(unsigned int id)
177 {
178         if (cpu_is_omap730()) {
179                 if (id > OMAP_MAX_MCBSP_COUNT - 1) {
180                        printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
181                        return -1;
182                 }
183                 return 0;
184         }
185
186         if (cpu_is_omap1510() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
187                 if (id > OMAP_MAX_MCBSP_COUNT) {
188                         printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
189                         return -1;
190                 }
191                 return 0;
192         }
193
194         return -1;
195 }
196
197 #ifdef CONFIG_ARCH_OMAP1
198 static void omap_mcbsp_dsp_request(void)
199 {
200         if (cpu_is_omap1510() || cpu_is_omap16xx()) {
201                 omap_dsp_request_mem();
202                 clk_enable(mcbsp_dsp_ck);
203                 clk_enable(mcbsp_api_ck);
204
205                 /* enable 12MHz clock to mcbsp 1 & 3 */
206                 clk_enable(mcbsp_dspxor_ck);
207
208                 /*
209                  * DSP external peripheral reset
210                  * FIXME: This should be moved to dsp code
211                  */
212                 __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
213                              DSP_RSTCT2);
214         }
215 }
216
217 static void omap_mcbsp_dsp_free(void)
218 {
219         if (cpu_is_omap1510() || cpu_is_omap16xx()) {
220                 omap_dsp_release_mem();
221                 clk_disable(mcbsp_dspxor_ck);
222                 clk_disable(mcbsp_dsp_ck);
223                 clk_disable(mcbsp_api_ck);
224         }
225 }
226 #endif
227
228 #ifdef CONFIG_ARCH_OMAP2
229 static void omap2_mcbsp2_mux_setup(void)
230 {
231         omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
232         omap_cfg_reg(R14_24XX_MCBSP2_FSX);
233         omap_cfg_reg(W15_24XX_MCBSP2_DR);
234         omap_cfg_reg(V15_24XX_MCBSP2_DX);
235         omap_cfg_reg(V14_24XX_GPIO117);
236         omap_cfg_reg(W14_24XX_SYS_CLKOUT);
237 }
238 #endif
239
240 int omap_mcbsp_request(unsigned int id)
241 {
242         int err;
243
244         if (omap_mcbsp_check(id) < 0)
245                 return -EINVAL;
246
247 #ifdef CONFIG_ARCH_OMAP1
248         /*
249          * On 1510, 1610 and 1710, McBSP1 and McBSP3
250          * are DSP public peripherals.
251          */
252         if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
253                 omap_mcbsp_dsp_request();
254 #endif
255
256 #ifdef CONFIG_ARCH_OMAP2
257         if (cpu_is_omap24xx()) {
258                 if (id == OMAP_MCBSP1) {
259                         clk_enable(mcbsp1_ick);
260                         clk_enable(mcbsp1_fck);
261                 } else {
262                         clk_enable(mcbsp2_ick);
263                         clk_enable(mcbsp2_fck);
264                 }
265         }
266 #endif
267
268         spin_lock(&mcbsp[id].lock);
269         if (!mcbsp[id].free) {
270                 printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
271                 spin_unlock(&mcbsp[id].lock);
272                 return -1;
273         }
274
275         mcbsp[id].free = 0;
276         spin_unlock(&mcbsp[id].lock);
277
278         /* We need to get IRQs here */
279         err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
280                           "McBSP",
281                           (void *) (&mcbsp[id]));
282         if (err != 0) {
283                 printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
284                        mcbsp[id].tx_irq, mcbsp[id].id);
285                 return err;
286         }
287
288         init_completion(&(mcbsp[id].tx_irq_completion));
289
290
291         err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
292                           "McBSP",
293                           (void *) (&mcbsp[id]));
294         if (err != 0) {
295                 printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
296                        mcbsp[id].rx_irq, mcbsp[id].id);
297                 free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
298                 return err;
299         }
300
301         init_completion(&(mcbsp[id].rx_irq_completion));
302         return 0;
303
304 }
305
306 void omap_mcbsp_free(unsigned int id)
307 {
308         if (omap_mcbsp_check(id) < 0)
309                 return;
310
311 #ifdef CONFIG_ARCH_OMAP1
312         if (cpu_class_is_omap1()) {
313                 if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
314                         omap_mcbsp_dsp_free();
315         }
316 #endif
317
318 #ifdef CONFIG_ARCH_OMAP2
319         if (cpu_is_omap24xx()) {
320                 if (id == OMAP_MCBSP1) {
321                         clk_disable(mcbsp1_ick);
322                         clk_disable(mcbsp1_fck);
323                 } else {
324                         clk_disable(mcbsp2_ick);
325                         clk_disable(mcbsp2_fck);
326                 }
327         }
328 #endif
329
330         spin_lock(&mcbsp[id].lock);
331         if (mcbsp[id].free) {
332                 printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
333                 spin_unlock(&mcbsp[id].lock);
334                 return;
335         }
336
337         mcbsp[id].free = 1;
338         spin_unlock(&mcbsp[id].lock);
339
340         /* Free IRQs */
341         free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
342         free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
343 }
344
345 /*
346  * Here we start the McBSP, by enabling the sample
347  * generator, both transmitter and receivers,
348  * and the frame sync.
349  */
350 void omap_mcbsp_start(unsigned int id)
351 {
352         u32 io_base;
353         u16 w;
354
355         if (omap_mcbsp_check(id) < 0)
356                 return;
357
358         io_base = mcbsp[id].io_base;
359
360         mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
361         mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
362
363         /* Start the sample generator */
364         w = OMAP_MCBSP_READ(io_base, SPCR2);
365         OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
366
367         /* Enable transmitter and receiver */
368         w = OMAP_MCBSP_READ(io_base, SPCR2);
369         OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
370
371         w = OMAP_MCBSP_READ(io_base, SPCR1);
372         OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
373
374         udelay(100);
375
376         /* Start frame sync */
377         w = OMAP_MCBSP_READ(io_base, SPCR2);
378         OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
379
380         /* Dump McBSP Regs */
381         omap_mcbsp_dump_reg(id);
382
383 }
384
385 void omap_mcbsp_stop(unsigned int id)
386 {
387         u32 io_base;
388         u16 w;
389
390         if (omap_mcbsp_check(id) < 0)
391                 return;
392
393         io_base = mcbsp[id].io_base;
394
395         /* Reset transmitter */
396         w = OMAP_MCBSP_READ(io_base, SPCR2);
397         OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
398
399         /* Reset receiver */
400         w = OMAP_MCBSP_READ(io_base, SPCR1);
401         OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
402
403         /* Reset the sample rate generator */
404         w = OMAP_MCBSP_READ(io_base, SPCR2);
405         OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
406 }
407
408
409 /* polled mcbsp i/o operations */
410 int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
411 {
412         u32 base = mcbsp[id].io_base;
413         writew(buf, base + OMAP_MCBSP_REG_DXR1);
414         /* if frame sync error - clear the error */
415         if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) {
416                 /* clear error */
417                 writew(readw(base + OMAP_MCBSP_REG_SPCR2) & (~XSYNC_ERR),
418                        base + OMAP_MCBSP_REG_SPCR2);
419                 /* resend */
420                 return -1;
421         } else {
422                 /* wait for transmit confirmation */
423                 int attemps = 0;
424                 while (!(readw(base + OMAP_MCBSP_REG_SPCR2) & XRDY)) {
425                         if (attemps++ > 1000) {
426                                 writew(readw(base + OMAP_MCBSP_REG_SPCR2) &
427                                        (~XRST),
428                                        base + OMAP_MCBSP_REG_SPCR2);
429                                 udelay(10);
430                                 writew(readw(base + OMAP_MCBSP_REG_SPCR2) |
431                                        (XRST),
432                                        base + OMAP_MCBSP_REG_SPCR2);
433                                 udelay(10);
434                                 printk(KERN_ERR
435                                        " Could not write to McBSP Register\n");
436                                 return -2;
437                         }
438                 }
439         }
440         return 0;
441 }
442
443 int omap_mcbsp_pollread(unsigned int id, u16 * buf)
444 {
445         u32 base = mcbsp[id].io_base;
446         /* if frame sync error - clear the error */
447         if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {
448                 /* clear error */
449                 writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~RSYNC_ERR),
450                        base + OMAP_MCBSP_REG_SPCR1);
451                 /* resend */
452                 return -1;
453         } else {
454                 /* wait for recieve confirmation */
455                 int attemps = 0;
456                 while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & RRDY)) {
457                         if (attemps++ > 1000) {
458                                 writew(readw(base + OMAP_MCBSP_REG_SPCR1) &
459                                        (~RRST),
460                                        base + OMAP_MCBSP_REG_SPCR1);
461                                 udelay(10);
462                                 writew(readw(base + OMAP_MCBSP_REG_SPCR1) |
463                                        (RRST),
464                                        base + OMAP_MCBSP_REG_SPCR1);
465                                 udelay(10);
466                                 printk(KERN_ERR
467                                        " Could not read from McBSP Register\n");
468                                 return -2;
469                         }
470                 }
471         }
472         *buf = readw(base + OMAP_MCBSP_REG_DRR1);
473         return 0;
474 }
475
476 /*
477  * IRQ based word transmission.
478  */
479 void omap_mcbsp_xmit_word(unsigned int id, u32 word)
480 {
481         u32 io_base;
482         omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
483
484         if (omap_mcbsp_check(id) < 0)
485                 return;
486
487         io_base = mcbsp[id].io_base;
488
489         wait_for_completion(&(mcbsp[id].tx_irq_completion));
490
491         if (word_length > OMAP_MCBSP_WORD_16)
492                 OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
493         OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
494 }
495
496 u32 omap_mcbsp_recv_word(unsigned int id)
497 {
498         u32 io_base;
499         u16 word_lsb, word_msb = 0;
500         omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
501
502         if (omap_mcbsp_check(id) < 0)
503                 return -EINVAL;
504
505         io_base = mcbsp[id].io_base;
506
507         wait_for_completion(&(mcbsp[id].rx_irq_completion));
508
509         if (word_length > OMAP_MCBSP_WORD_16)
510                 word_msb = OMAP_MCBSP_READ(io_base, DRR2);
511         word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
512
513         return (word_lsb | (word_msb << 16));
514 }
515
516
517 /*
518  * Simple DMA based buffer rx/tx routines.
519  * Nothing fancy, just a single buffer tx/rx through DMA.
520  * The DMA resources are released once the transfer is done.
521  * For anything fancier, you should use your own customized DMA
522  * routines and callbacks.
523  */
524 int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
525 {
526         int dma_tx_ch;
527         int src_port = 0;
528         int dest_port = 0;
529         int sync_dev = 0;
530
531         if (omap_mcbsp_check(id) < 0)
532                 return -EINVAL;
533
534         if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
535                              &mcbsp[id],
536                              &dma_tx_ch)) {
537                 printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
538                 return -EAGAIN;
539         }
540         mcbsp[id].dma_tx_lch = dma_tx_ch;
541
542         DBG("TX DMA on channel %d\n", dma_tx_ch);
543
544         init_completion(&(mcbsp[id].tx_dma_completion));
545
546         if (cpu_class_is_omap1()) {
547                 src_port = OMAP_DMA_PORT_TIPB;
548                 dest_port = OMAP_DMA_PORT_EMIFF;
549         }
550         if (cpu_is_omap24xx())
551                 sync_dev = mcbsp[id].dma_tx_sync;
552
553         omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
554                                      OMAP_DMA_DATA_TYPE_S16,
555                                      length >> 1, 1,
556                                      OMAP_DMA_SYNC_ELEMENT,
557          sync_dev, 0);
558
559         omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
560                                  src_port,
561                                  OMAP_DMA_AMODE_CONSTANT,
562                                  mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
563                                  0, 0);
564
565         omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
566                                 dest_port,
567                                 OMAP_DMA_AMODE_POST_INC,
568                                 buffer,
569                                 0, 0);
570
571         omap_start_dma(mcbsp[id].dma_tx_lch);
572         wait_for_completion(&(mcbsp[id].tx_dma_completion));
573         return 0;
574 }
575
576
577 int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
578 {
579         int dma_rx_ch;
580         int src_port = 0;
581         int dest_port = 0;
582         int sync_dev = 0;
583
584         if (omap_mcbsp_check(id) < 0)
585                 return -EINVAL;
586
587         if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
588                              &mcbsp[id],
589                              &dma_rx_ch)) {
590                 printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
591                 return -EAGAIN;
592         }
593         mcbsp[id].dma_rx_lch = dma_rx_ch;
594
595         DBG("RX DMA on channel %d\n", dma_rx_ch);
596
597         init_completion(&(mcbsp[id].rx_dma_completion));
598
599         if (cpu_class_is_omap1()) {
600                 src_port = OMAP_DMA_PORT_TIPB;
601                 dest_port = OMAP_DMA_PORT_EMIFF;
602         }
603         if (cpu_is_omap24xx())
604                 sync_dev = mcbsp[id].dma_rx_sync;
605
606         omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
607                                      OMAP_DMA_DATA_TYPE_S16,
608                                      length >> 1, 1,
609                                      OMAP_DMA_SYNC_ELEMENT,
610          sync_dev, 0);
611
612         omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
613                                 src_port,
614                                 OMAP_DMA_AMODE_CONSTANT,
615                                 mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
616                                 0, 0);
617
618         omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
619                                  dest_port,
620                                  OMAP_DMA_AMODE_POST_INC,
621                                  buffer,
622                                  0, 0);
623
624         omap_start_dma(mcbsp[id].dma_rx_lch);
625         wait_for_completion(&(mcbsp[id].rx_dma_completion));
626         return 0;
627 }
628
629
630 /*
631  * SPI wrapper.
632  * Since SPI setup is much simpler than the generic McBSP one,
633  * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
634  * Once this is done, you can call omap_mcbsp_start().
635  */
636 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
637 {
638         struct omap_mcbsp_reg_cfg mcbsp_cfg;
639
640         if (omap_mcbsp_check(id) < 0)
641                 return;
642
643         memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
644
645         /* SPI has only one frame */
646         mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
647         mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
648
649         /* Clock stop mode */
650         if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
651                 mcbsp_cfg.spcr1 |= (1 << 12);
652         else
653                 mcbsp_cfg.spcr1 |= (3 << 11);
654
655         /* Set clock parities */
656         if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
657                 mcbsp_cfg.pcr0 |= CLKRP;
658         else
659                 mcbsp_cfg.pcr0 &= ~CLKRP;
660
661         if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
662                 mcbsp_cfg.pcr0 &= ~CLKXP;
663         else
664                 mcbsp_cfg.pcr0 |= CLKXP;
665
666         /* Set SCLKME to 0 and CLKSM to 1 */
667         mcbsp_cfg.pcr0 &= ~SCLKME;
668         mcbsp_cfg.srgr2 |= CLKSM;
669
670         /* Set FSXP */
671         if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
672                 mcbsp_cfg.pcr0 &= ~FSXP;
673         else
674                 mcbsp_cfg.pcr0 |= FSXP;
675
676         if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
677                 mcbsp_cfg.pcr0 |= CLKXM;
678                 mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
679                 mcbsp_cfg.pcr0 |= FSXM;
680                 mcbsp_cfg.srgr2 &= ~FSGM;
681                 mcbsp_cfg.xcr2 |= XDATDLY(1);
682                 mcbsp_cfg.rcr2 |= RDATDLY(1);
683         }
684         else {
685                 mcbsp_cfg.pcr0 &= ~CLKXM;
686                 mcbsp_cfg.srgr1 |= CLKGDV(1);
687                 mcbsp_cfg.pcr0 &= ~FSXM;
688                 mcbsp_cfg.xcr2 &= ~XDATDLY(3);
689                 mcbsp_cfg.rcr2 &= ~RDATDLY(3);
690         }
691
692         mcbsp_cfg.xcr2 &= ~XPHASE;
693         mcbsp_cfg.rcr2 &= ~RPHASE;
694
695         omap_mcbsp_config(id, &mcbsp_cfg);
696 }
697
698
699 /*
700  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
701  * 730 has only 2 McBSP, and both of them are MPU peripherals.
702  */
703 struct omap_mcbsp_info {
704         u32 virt_base;
705         u8 dma_rx_sync, dma_tx_sync;
706         u16 rx_irq, tx_irq;
707 };
708
709 #ifdef CONFIG_ARCH_OMAP730
710 static const struct omap_mcbsp_info mcbsp_730[] = {
711         [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
712                 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
713                 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
714                 .rx_irq = INT_730_McBSP1RX,
715                 .tx_irq = INT_730_McBSP1TX },
716         [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
717                 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
718                 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
719                 .rx_irq = INT_730_McBSP2RX,
720                 .tx_irq = INT_730_McBSP2TX },
721 };
722 #endif
723
724 #ifdef CONFIG_ARCH_OMAP15XX
725 static const struct omap_mcbsp_info mcbsp_1510[] = {
726         [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
727                 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
728                 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
729                 .rx_irq = INT_McBSP1RX,
730                 .tx_irq = INT_McBSP1TX },
731         [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
732                 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
733                 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
734                 .rx_irq = INT_1510_SPI_RX,
735                 .tx_irq = INT_1510_SPI_TX },
736         [2] = { .virt_base = OMAP1510_MCBSP3_BASE,
737                 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
738                 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
739                 .rx_irq = INT_McBSP3RX,
740                 .tx_irq = INT_McBSP3TX },
741 };
742 #endif
743
744 #if defined(CONFIG_ARCH_OMAP16XX)
745 static const struct omap_mcbsp_info mcbsp_1610[] = {
746         [0] = { .virt_base = OMAP1610_MCBSP1_BASE,
747                 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
748                 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
749                 .rx_irq = INT_McBSP1RX,
750                 .tx_irq = INT_McBSP1TX },
751         [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
752                 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
753                 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
754                 .rx_irq = INT_1610_McBSP2_RX,
755                 .tx_irq = INT_1610_McBSP2_TX },
756         [2] = { .virt_base = OMAP1610_MCBSP3_BASE,
757                 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
758                 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
759                 .rx_irq = INT_McBSP3RX,
760                 .tx_irq = INT_McBSP3TX },
761 };
762 #endif
763
764 #if defined(CONFIG_ARCH_OMAP24XX)
765 static const struct omap_mcbsp_info mcbsp_24xx[] = {
766         [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
767                 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
768                 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
769                 .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
770                 .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
771                 },
772         [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
773                 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
774                 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
775                 .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
776                 .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
777                 },
778 };
779 #endif
780
781 static int __init omap_mcbsp_init(void)
782 {
783         int mcbsp_count = 0, i;
784         static const struct omap_mcbsp_info *mcbsp_info;
785
786         printk("Initializing OMAP McBSP system\n");
787
788 #ifdef CONFIG_ARCH_OMAP1
789         mcbsp_dsp_ck = clk_get(0, "dsp_ck");
790         if (IS_ERR(mcbsp_dsp_ck)) {
791                 printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
792                 return PTR_ERR(mcbsp_dsp_ck);
793         }
794         mcbsp_api_ck = clk_get(0, "api_ck");
795         if (IS_ERR(mcbsp_api_ck)) {
796                 printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
797                 return PTR_ERR(mcbsp_api_ck);
798         }
799         mcbsp_dspxor_ck = clk_get(0, "dspxor_ck");
800         if (IS_ERR(mcbsp_dspxor_ck)) {
801                 printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
802                 return PTR_ERR(mcbsp_dspxor_ck);
803         }
804 #endif
805 #ifdef CONFIG_ARCH_OMAP2
806         mcbsp1_ick = clk_get(0, "mcbsp1_ick");
807         if (IS_ERR(mcbsp1_ick)) {
808                 printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
809                 return PTR_ERR(mcbsp1_ick);
810         }
811         mcbsp1_fck = clk_get(0, "mcbsp1_fck");
812         if (IS_ERR(mcbsp1_fck)) {
813                 printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
814                 return PTR_ERR(mcbsp1_fck);
815         }
816         mcbsp2_ick = clk_get(0, "mcbsp2_ick");
817         if (IS_ERR(mcbsp2_ick)) {
818                 printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
819                 return PTR_ERR(mcbsp2_ick);
820         }
821         mcbsp2_fck = clk_get(0, "mcbsp2_fck");
822         if (IS_ERR(mcbsp2_fck)) {
823                 printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
824                 return PTR_ERR(mcbsp2_fck);
825         }
826 #endif
827
828 #ifdef CONFIG_ARCH_OMAP730
829         if (cpu_is_omap730()) {
830                 mcbsp_info = mcbsp_730;
831                 mcbsp_count = ARRAY_SIZE(mcbsp_730);
832         }
833 #endif
834 #ifdef CONFIG_ARCH_OMAP15XX
835         if (cpu_is_omap1510()) {
836                 mcbsp_info = mcbsp_1510;
837                 mcbsp_count = ARRAY_SIZE(mcbsp_1510);
838         }
839 #endif
840 #if defined(CONFIG_ARCH_OMAP16XX)
841         if (cpu_is_omap16xx()) {
842                 mcbsp_info = mcbsp_1610;
843                 mcbsp_count = ARRAY_SIZE(mcbsp_1610);
844         }
845 #endif
846 #if defined(CONFIG_ARCH_OMAP24XX)
847         if (cpu_is_omap24xx()) {
848                 mcbsp_info = mcbsp_24xx;
849                 mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
850
851                 /* REVISIT: where's the right place? */
852                 omap2_mcbsp2_mux_setup();
853                 sys_ck = clk_get(0, "sys_ck");
854                 sys_clkout = clk_get(0, "sys_clkout");
855                 clk_set_parent(sys_clkout, sys_ck);
856                 clk_enable(sys_clkout);
857         }
858 #endif
859         for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
860                 if (i >= mcbsp_count) {
861                         mcbsp[i].io_base = 0;
862                         mcbsp[i].free = 0;
863                         continue;
864                 }
865                 mcbsp[i].id = i + 1;
866                 mcbsp[i].free = 1;
867                 mcbsp[i].dma_tx_lch = -1;
868                 mcbsp[i].dma_rx_lch = -1;
869
870                 mcbsp[i].io_base = mcbsp_info[i].virt_base;
871                 mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
872                 mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
873                 mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
874                 mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
875                 spin_lock_init(&mcbsp[i].lock);
876         }
877
878         return 0;
879 }
880
881 arch_initcall(omap_mcbsp_init);
882
883 EXPORT_SYMBOL(omap_mcbsp_config);
884 EXPORT_SYMBOL(omap_mcbsp_request);
885 EXPORT_SYMBOL(omap_mcbsp_free);
886 EXPORT_SYMBOL(omap_mcbsp_start);
887 EXPORT_SYMBOL(omap_mcbsp_stop);
888 EXPORT_SYMBOL(omap_mcbsp_xmit_word);
889 EXPORT_SYMBOL(omap_mcbsp_recv_word);
890 EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
891 EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
892 EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);