Merge master.kernel.org:/home/rmk/linux-2.6-serial
[powerpc.git] / arch / arm / plat-omap / mcbsp.c
index 10c3f22..9c9b7df 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/arch/dma.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/irqs.h>
+#include <asm/arch/dsp_common.h>
 #include <asm/arch/mcbsp.h>
 
 #include <asm/hardware/clock.h>
@@ -66,6 +67,7 @@ struct omap_mcbsp {
 static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
 static struct clk *mcbsp_dsp_ck = 0;
 static struct clk *mcbsp_api_ck = 0;
+static struct clk *mcbsp_dspxor_ck = 0;
 
 
 static void omap_mcbsp_dump_reg(u8 id)
@@ -175,7 +177,7 @@ static int omap_mcbsp_check(unsigned int id)
                return 0;
        }
 
-       if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
+       if (cpu_is_omap1510() || cpu_is_omap16xx()) {
                if (id > OMAP_MAX_MCBSP_COUNT) {
                        printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
                        return -1;
@@ -186,20 +188,19 @@ static int omap_mcbsp_check(unsigned int id)
        return -1;
 }
 
-#define EN_XORPCK              1
-#define DSP_RSTCT2              0xe1008014
-
 static void omap_mcbsp_dsp_request(void)
 {
-       if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
-               omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
-                           ARM_RSTCT1);
-               clk_enable(mcbsp_dsp_ck);
-               clk_enable(mcbsp_api_ck);
+       if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+               clk_use(mcbsp_dsp_ck);
+               clk_use(mcbsp_api_ck);
 
                /* enable 12MHz clock to mcbsp 1 & 3 */
-               __raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
-                            DSP_IDLECT2);
+               clk_use(mcbsp_dspxor_ck);
+
+               /*
+                * DSP external peripheral reset
+                * FIXME: This should be moved to dsp code
+                */
                __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
                             DSP_RSTCT2);
        }
@@ -207,10 +208,13 @@ static void omap_mcbsp_dsp_request(void)
 
 static void omap_mcbsp_dsp_free(void)
 {
-       /* Useless for now */
+       if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+               clk_unuse(mcbsp_dspxor_ck);
+               clk_unuse(mcbsp_dsp_ck);
+               clk_unuse(mcbsp_api_ck);
+       }
 }
 
-
 int omap_mcbsp_request(unsigned int id)
 {
        int err;
@@ -350,6 +354,73 @@ void omap_mcbsp_stop(unsigned int id)
 }
 
 
+/* polled mcbsp i/o operations */
+int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
+{
+       u32 base = mcbsp[id].io_base;
+       writew(buf, base + OMAP_MCBSP_REG_DXR1);
+       /* if frame sync error - clear the error */
+       if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) {
+               /* clear error */
+               writew(readw(base + OMAP_MCBSP_REG_SPCR2) & (~XSYNC_ERR),
+                      base + OMAP_MCBSP_REG_SPCR2);
+               /* resend */
+               return -1;
+       } else {
+               /* wait for transmit confirmation */
+               int attemps = 0;
+               while (!(readw(base + OMAP_MCBSP_REG_SPCR2) & XRDY)) {
+                       if (attemps++ > 1000) {
+                               writew(readw(base + OMAP_MCBSP_REG_SPCR2) &
+                                      (~XRST),
+                                      base + OMAP_MCBSP_REG_SPCR2);
+                               udelay(10);
+                               writew(readw(base + OMAP_MCBSP_REG_SPCR2) |
+                                      (XRST),
+                                      base + OMAP_MCBSP_REG_SPCR2);
+                               udelay(10);
+                               printk(KERN_ERR
+                                      " Could not write to McBSP Register\n");
+                               return -2;
+                       }
+               }
+       }
+       return 0;
+}
+
+int omap_mcbsp_pollread(unsigned int id, u16 * buf)
+{
+       u32 base = mcbsp[id].io_base;
+       /* if frame sync error - clear the error */
+       if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {
+               /* clear error */
+               writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~RSYNC_ERR),
+                      base + OMAP_MCBSP_REG_SPCR1);
+               /* resend */
+               return -1;
+       } else {
+               /* wait for recieve confirmation */
+               int attemps = 0;
+               while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & RRDY)) {
+                       if (attemps++ > 1000) {
+                               writew(readw(base + OMAP_MCBSP_REG_SPCR1) &
+                                      (~RRST),
+                                      base + OMAP_MCBSP_REG_SPCR1);
+                               udelay(10);
+                               writew(readw(base + OMAP_MCBSP_REG_SPCR1) |
+                                      (RRST),
+                                      base + OMAP_MCBSP_REG_SPCR1);
+                               udelay(10);
+                               printk(KERN_ERR
+                                      " Could not read from McBSP Register\n");
+                               return -2;
+                       }
+               }
+       }
+       *buf = readw(base + OMAP_MCBSP_REG_DRR1);
+       return 0;
+}
+
 /*
  * IRQ based word transmission.
  */
@@ -625,10 +696,15 @@ static int __init omap_mcbsp_init(void)
                return PTR_ERR(mcbsp_dsp_ck);
        }
        mcbsp_api_ck = clk_get(0, "api_ck");
-       if (IS_ERR(mcbsp_dsp_ck)) {
+       if (IS_ERR(mcbsp_api_ck)) {
                printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
                return PTR_ERR(mcbsp_api_ck);
        }
+       mcbsp_dspxor_ck = clk_get(0, "dspxor_ck");
+       if (IS_ERR(mcbsp_dspxor_ck)) {
+               printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
+               return PTR_ERR(mcbsp_dspxor_ck);
+       }
 
 #ifdef CONFIG_ARCH_OMAP730
        if (cpu_is_omap730()) {
@@ -643,7 +719,7 @@ static int __init omap_mcbsp_init(void)
        }
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
-       if (cpu_is_omap1610() || cpu_is_omap1710()) {
+       if (cpu_is_omap16xx()) {
                mcbsp_info = mcbsp_1610;
                mcbsp_count = ARRAY_SIZE(mcbsp_1610);
        }