tree-wide: fix assorted typos all over the place
[safe/jmp/linux-2.6] / arch / arm / plat-omap / dma.c
index b1d3c79..0e30891 100644 (file)
@@ -10,6 +10,9 @@
  * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
  * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
  *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
  * Support functions for the OMAP internal DMA channels.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -310,41 +313,62 @@ EXPORT_SYMBOL(omap_set_dma_transfer_params);
 
 void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 {
-       u16 w;
-
        BUG_ON(omap_dma_in_1510_mode());
 
-       if (cpu_class_is_omap2()) {
-               REVISIT_24XX();
-               return;
-       }
+       if (cpu_class_is_omap1()) {
+               u16 w;
 
-       w = dma_read(CCR2(lch));
-       w &= ~0x03;
+               w = dma_read(CCR2(lch));
+               w &= ~0x03;
 
-       switch (mode) {
-       case OMAP_DMA_CONSTANT_FILL:
-               w |= 0x01;
-               break;
-       case OMAP_DMA_TRANSPARENT_COPY:
-               w |= 0x02;
-               break;
-       case OMAP_DMA_COLOR_DIS:
-               break;
-       default:
-               BUG();
+               switch (mode) {
+               case OMAP_DMA_CONSTANT_FILL:
+                       w |= 0x01;
+                       break;
+               case OMAP_DMA_TRANSPARENT_COPY:
+                       w |= 0x02;
+                       break;
+               case OMAP_DMA_COLOR_DIS:
+                       break;
+               default:
+                       BUG();
+               }
+               dma_write(w, CCR2(lch));
+
+               w = dma_read(LCH_CTRL(lch));
+               w &= ~0x0f;
+               /* Default is channel type 2D */
+               if (mode) {
+                       dma_write((u16)color, COLOR_L(lch));
+                       dma_write((u16)(color >> 16), COLOR_U(lch));
+                       w |= 1;         /* Channel type G */
+               }
+               dma_write(w, LCH_CTRL(lch));
        }
-       dma_write(w, CCR2(lch));
 
-       w = dma_read(LCH_CTRL(lch));
-       w &= ~0x0f;
-       /* Default is channel type 2D */
-       if (mode) {
-               dma_write((u16)color, COLOR_L(lch));
-               dma_write((u16)(color >> 16), COLOR_U(lch));
-               w |= 1;         /* Channel type G */
+       if (cpu_class_is_omap2()) {
+               u32 val;
+
+               val = dma_read(CCR(lch));
+               val &= ~((1 << 17) | (1 << 16));
+
+               switch (mode) {
+               case OMAP_DMA_CONSTANT_FILL:
+                       val |= 1 << 16;
+                       break;
+               case OMAP_DMA_TRANSPARENT_COPY:
+                       val |= 1 << 17;
+                       break;
+               case OMAP_DMA_COLOR_DIS:
+                       break;
+               default:
+                       BUG();
+               }
+               dma_write(val, CCR(lch));
+
+               color &= 0xffffff;
+               dma_write(color, COLOR(lch));
        }
-       dma_write(w, LCH_CTRL(lch));
 }
 EXPORT_SYMBOL(omap_set_dma_color_mode);
 
@@ -760,19 +784,12 @@ void omap_free_dma(int lch)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&dma_chan_lock, flags);
        if (dma_chan[lch].dev_id == -1) {
                pr_err("omap_dma: trying to free unallocated DMA channel %d\n",
                       lch);
-               spin_unlock_irqrestore(&dma_chan_lock, flags);
                return;
        }
 
-       dma_chan[lch].dev_id = -1;
-       dma_chan[lch].next_lch = -1;
-       dma_chan[lch].callback = NULL;
-       spin_unlock_irqrestore(&dma_chan_lock, flags);
-
        if (cpu_class_is_omap1()) {
                /* Disable all DMA interrupts for the channel. */
                dma_write(0, CICR(lch));
@@ -798,6 +815,12 @@ void omap_free_dma(int lch)
                dma_write(0, CCR(lch));
                omap_clear_dma(lch);
        }
+
+       spin_lock_irqsave(&dma_chan_lock, flags);
+       dma_chan[lch].dev_id = -1;
+       dma_chan[lch].next_lch = -1;
+       dma_chan[lch].callback = NULL;
+       spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 EXPORT_SYMBOL(omap_free_dma);
 
@@ -806,10 +829,10 @@ EXPORT_SYMBOL(omap_free_dma);
  *
  * @param arb_rate
  * @param max_fifo_depth
- * @param tparams - Number of thereads to reserve : DMA_THREAD_RESERVE_NORM
- *                                                 DMA_THREAD_RESERVE_ONET
- *                                                 DMA_THREAD_RESERVE_TWOT
- *                                                 DMA_THREAD_RESERVE_THREET
+ * @param tparams - Number of threads to reserve : DMA_THREAD_RESERVE_NORM
+ *                                                DMA_THREAD_RESERVE_ONET
+ *                                                DMA_THREAD_RESERVE_TWOT
+ *                                                DMA_THREAD_RESERVE_THREET
  */
 void
 omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
@@ -821,11 +844,14 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
                return;
        }
 
+       if (max_fifo_depth == 0)
+               max_fifo_depth = 1;
        if (arb_rate == 0)
                arb_rate = 1;
 
-       reg = (arb_rate & 0xff) << 16;
-       reg |= (0xff & max_fifo_depth);
+       reg = 0xff & max_fifo_depth;
+       reg |= (0x3 & tparams) << 12;
+       reg |= (arb_rate & 0xff) << 16;
 
        dma_write(reg, GCR);
 }
@@ -852,7 +878,7 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio,
        }
        l = dma_read(CCR(lch));
        l &= ~((1 << 6) | (1 << 26));
-       if (cpu_is_omap2430() || cpu_is_omap34xx())
+       if (cpu_is_omap2430() || cpu_is_omap34xx() ||  cpu_is_omap44xx())
                l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
        else
                l |= ((read_prio & 0x1) << 6);
@@ -923,7 +949,9 @@ void omap_start_dma(int lch)
 
                        cur_lch = next_lch;
                } while (next_lch != -1);
-       } else if (cpu_class_is_omap2()) {
+       } else if (cpu_is_omap242x() ||
+               (cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
+
                /* Errata: Need to write lch even if not using chaining */
                dma_write(lch, CLNK_CTRL(lch));
        }
@@ -950,6 +978,14 @@ void omap_stop_dma(int lch)
 {
        u32 l;
 
+       /* Disable all interrupts on the channel */
+       if (cpu_class_is_omap1())
+               dma_write(0, CICR(lch));
+
+       l = dma_read(CCR(lch));
+       l &= ~OMAP_DMA_CCR_EN;
+       dma_write(l, CCR(lch));
+
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch = lch;
                char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT];
@@ -967,18 +1003,8 @@ void omap_stop_dma(int lch)
                        next_lch = dma_chan[cur_lch].next_lch;
                        cur_lch = next_lch;
                } while (next_lch != -1);
-
-               return;
        }
 
-       /* Disable all interrupts on the channel */
-       if (cpu_class_is_omap1())
-               dma_write(0, CICR(lch));
-
-       l = dma_read(CCR(lch));
-       l &= ~OMAP_DMA_CCR_EN;
-       dma_write(l, CCR(lch));
-
        dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 EXPORT_SYMBOL(omap_stop_dma);
@@ -1102,6 +1128,11 @@ int omap_dma_running(void)
 void omap_dma_link_lch(int lch_head, int lch_queue)
 {
        if (omap_dma_in_1510_mode()) {
+               if (lch_head == lch_queue) {
+                       dma_write(dma_read(CCR(lch_head)) | (3 << 8),
+                                                               CCR(lch_head));
+                       return;
+               }
                printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
                BUG();
                return;
@@ -1124,6 +1155,11 @@ EXPORT_SYMBOL(omap_dma_link_lch);
 void omap_dma_unlink_lch(int lch_head, int lch_queue)
 {
        if (omap_dma_in_1510_mode()) {
+               if (lch_head == lch_queue) {
+                       dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
+                                                               CCR(lch_head));
+                       return;
+               }
                printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
                BUG();
                return;
@@ -1196,11 +1232,11 @@ static void create_dma_lch_chain(int lch_head, int lch_queue)
  *                                           OMAP_DMA_DYNAMIC_CHAIN
  * @params - Channel parameters
  *
- * @return - Succes : 0
+ * @return - Success : 0
  *          Failure: -EINVAL/-ENOMEM
  */
 int omap_request_dma_chain(int dev_id, const char *dev_name,
-                          void (*callback) (int chain_id, u16 ch_status,
+                          void (*callback) (int lch, u16 ch_status,
                                             void *data),
                           int *chain_id, int no_of_chans, int chain_mode,
                           struct omap_dma_channel_params params)
@@ -1824,7 +1860,8 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
 #define omap1_dma_irq_handler  NULL
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+                       defined(CONFIG_ARCH_OMAP4)
 
 static int omap2_dma_handle_ch(int ch)
 {
@@ -1901,7 +1938,7 @@ static int omap2_dma_handle_ch(int ch)
 /* STATUS register count is from 1-32 while our is 0-31 */
 static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
 {
-       u32 val;
+       u32 val, enable_reg;
        int i;
 
        val = dma_read(IRQSTATUS_L0);
@@ -1910,6 +1947,8 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id)
                        printk(KERN_WARNING "Spurious DMA IRQ\n");
                return IRQ_HANDLED;
        }
+       enable_reg = dma_read(IRQENABLE_L0);
+       val &= enable_reg; /* Dispatch only relevant interrupts */
        for (i = 0; i < dma_lch_count && val != 0; i++) {
                if (val & 1)
                        omap2_dma_handle_ch(i);
@@ -2309,13 +2348,16 @@ static int __init omap_init_dma(void)
        int ch, r;
 
        if (cpu_class_is_omap1()) {
-               omap_dma_base = IO_ADDRESS(OMAP1_DMA_BASE);
+               omap_dma_base = OMAP1_IO_ADDRESS(OMAP1_DMA_BASE);
                dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
        } else if (cpu_is_omap24xx()) {
-               omap_dma_base = IO_ADDRESS(OMAP24XX_DMA4_BASE);
+               omap_dma_base = OMAP2_IO_ADDRESS(OMAP24XX_DMA4_BASE);
                dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
        } else if (cpu_is_omap34xx()) {
-               omap_dma_base = IO_ADDRESS(OMAP34XX_DMA4_BASE);
+               omap_dma_base = OMAP2_IO_ADDRESS(OMAP34XX_DMA4_BASE);
+               dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
+       } else if (cpu_is_omap44xx()) {
+               omap_dma_base = OMAP2_IO_ADDRESS(OMAP44XX_DMA4_BASE);
                dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
        } else {
                pr_err("DMA init failed for unsupported omap\n");
@@ -2415,12 +2457,31 @@ static int __init omap_init_dma(void)
                }
        }
 
-       if (cpu_is_omap2430() || cpu_is_omap34xx())
+       if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx())
                omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
                                DMA_DEFAULT_FIFO_DEPTH, 0);
 
-       if (cpu_class_is_omap2())
-               setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq);
+       if (cpu_class_is_omap2()) {
+               int irq;
+               if (cpu_is_omap44xx())
+                       irq = INT_44XX_SDMA_IRQ0;
+               else
+                       irq = INT_24XX_SDMA_IRQ0;
+               setup_irq(irq, &omap24xx_dma_irq);
+       }
+
+       /* Enable smartidle idlemodes and autoidle */
+       if (cpu_is_omap34xx()) {
+               u32 v = dma_read(OCP_SYSCONFIG);
+               v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
+                               DMA_SYSCONFIG_SIDLEMODE_MASK |
+                               DMA_SYSCONFIG_AUTOIDLE);
+               v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
+                       DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
+                       DMA_SYSCONFIG_AUTOIDLE);
+               dma_write(v , OCP_SYSCONFIG);
+       }
+
 
        /* FIXME: Update LCD DMA to work on 24xx */
        if (cpu_class_is_omap1()) {