From: David Brownell <[email protected]>

Move EDMA platform device creation into SoC-specific init code,
and provide it with platform_data to parameterize some of the
key differences.

Handle some key dm646x differences.  Ones that can change the
behavior including supporting all the DMA slots (512 vs just 128)
and a different set of no-events channels.

This doesn't yet ioremap(), or support using more than the first
two TCs on platforms like dm646x or dm365.

Signed-off-by: David Brownell <[email protected]>
---
Sanity tested on dm6446 and dm355 EVM boards.

 arch/arm/mach-davinci/dm355.c             |   69 +++++
 arch/arm/mach-davinci/dm644x.c            |   72 +++++
 arch/arm/mach-davinci/dm646x.c            |   84 ++++++
 arch/arm/mach-davinci/dma.c               |  342 ++++++++++++----------------
 arch/arm/mach-davinci/include/mach/edma.h |   24 +
 5 files changed, 396 insertions(+), 195 deletions(-)

--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -18,6 +18,8 @@
 
 #include <mach/dm355.h>
 #include <mach/clock.h>
+#include <mach/cpu.h>
+#include <mach/edma.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
 #include <mach/irqs.h>
@@ -463,8 +465,75 @@ EVT_CFG(DM355,  EVT9_ASP1_RX,            1,  
 EVT_CFG(DM355,  EVT26_MMC0_RX,       2,    1,    0,     false)
 };
 
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm355_no_event[] = {
+       12, 13, 24, 56, 57,
+       58, 59, 60, 61, 62,
+       63,
+       -1
+};
+
+static struct edma_soc_info dm355_edma_info = {
+       .n_channel      = 64,
+       .n_region       = 4,
+       .n_slot         = 128,
+       .n_tc           = 2,
+       .noevent        = dma_chan_dm355_no_event,
+};
+
+static struct resource edma_resources[] = {
+       {
+               .start  = 0x01c00000,
+               .end    = 0x01c00000 + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc0",
+               .start  = 0x01c10000,
+               .end    = 0x01c10000 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc1",
+               .start  = 0x01c10400,
+               .end    = 0x01c10400 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_CCINT0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_CCERRINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+       /* not using (or muxing) TC*_ERR */
+};
+
+static struct platform_device dm355_edma_device = {
+       .name                   = "edma",
+       .id                     = -1,
+       .dev.platform_data      = &dm355_edma_info,
+       .num_resources          = ARRAY_SIZE(edma_resources),
+       .resource               = edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+
 void __init dm355_init(void)
 {
        davinci_clk_init(dm355_clks);
        davinci_mux_register(dm355_pins, ARRAY_SIZE(dm355_pins));;
 }
+
+static int __init dm355_init_devices(void)
+{
+       if (!cpu_is_davinci_dm355())
+               return 0;
+
+       davinci_cfg_reg(DM355_INT_EDMA_CC);
+       platform_device_register(&dm355_edma_device);
+       return 0;
+}
+postcore_initcall(dm355_init_devices);
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -11,9 +11,13 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
 
 #include <mach/dm644x.h>
 #include <mach/clock.h>
+#include <mach/cpu.h>
+#include <mach/edma.h>
+#include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
 
@@ -358,8 +362,76 @@ MUX_CFG(DM644X, LFLDEN,            0,   25,    1,  
 };
 
 
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm644x_no_event[] = {
+        0,  1, 12, 13, 14,
+       15, 25, 30, 31, 45,
+       46, 47, 55, 56, 57,
+       58, 59, 60, 61, 62,
+       63,
+       -1
+};
+
+static struct edma_soc_info dm644x_edma_info = {
+       .n_channel      = 64,
+       .n_region       = 4,
+       .n_slot         = 128,
+       .n_tc           = 2,
+       .noevent        = dma_chan_dm644x_no_event,
+};
+
+static struct resource edma_resources[] = {
+       {
+               .start  = 0x01c00000,
+               .end    = 0x01c00000 + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc0",
+               .start  = 0x01c10000,
+               .end    = 0x01c10000 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc1",
+               .start  = 0x01c10400,
+               .end    = 0x01c10400 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_CCINT0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_CCERRINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+       /* not using TC*_ERR */
+};
+
+static struct platform_device dm644x_edma_device = {
+       .name                   = "edma",
+       .id                     = -1,
+       .dev.platform_data      = &dm644x_edma_info,
+       .num_resources          = ARRAY_SIZE(edma_resources),
+       .resource               = edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+
 void __init dm644x_init(void)
 {
        davinci_clk_init(dm644x_clks);
        davinci_mux_register(dm644x_pins, ARRAY_SIZE(dm644x_pins));
 }
+
+static int __init dm644x_init_devices(void)
+{
+       if (!cpu_is_davinci_dm644x())
+               return 0;
+
+       platform_device_register(&dm644x_edma_device);
+       return 0;
+}
+postcore_initcall(dm644x_init_devices);
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -11,9 +11,13 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
 
 #include <mach/dm646x.h>
 #include <mach/clock.h>
+#include <mach/cpu.h>
+#include <mach/edma.h>
+#include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
 
@@ -273,8 +277,88 @@ MUX_CFG(DM646X, AUDCK1,            0,   29,    1,  
 MUX_CFG(DM646X, AUDCK0,                0,   28,    1,    0,     false)
 };
 
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm646x_no_event[] = {
+        0,  1,  2,  3, 13,
+       14, 15, 24, 25, 26,
+       27, 30, 31, 54, 55,
+       56,
+       -1
+};
+
+static struct edma_soc_info dm646x_edma_info = {
+       .n_channel      = 64,
+       .n_region       = 6,    /* 0-1, 4-7 */
+       .n_slot         = 512,
+       .n_tc           = 4,
+       .noevent        = dma_chan_dm646x_no_event,
+};
+
+static struct resource edma_resources[] = {
+       {
+               .start  = 0x01c00000,
+               .end    = 0x01c00000 + SZ_64K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc0",
+               .start  = 0x01c10000,
+               .end    = 0x01c10000 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc1",
+               .start  = 0x01c10400,
+               .end    = 0x01c10400 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc2",
+               .start  = 0x01c10800,
+               .end    = 0x01c10800 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .name   = "edma_tc3",
+               .start  = 0x01c10c00,
+               .end    = 0x01c10c00 + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_CCINT0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_CCERRINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+       /* not using TC*_ERR */
+};
+
+static struct platform_device dm646x_edma_device = {
+       .name                   = "edma",
+       .id                     = -1,
+       .dev.platform_data      = &dm646x_edma_info,
+       .num_resources          = ARRAY_SIZE(edma_resources),
+       .resource               = edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+
+
 void __init dm646x_init(void)
 {
        davinci_clk_init(dm646x_clks);
        davinci_mux_register(dm646x_pins, ARRAY_SIZE(dm646x_pins));
 }
+
+static int __init dm646x_init_devices(void)
+{
+       if (!cpu_is_davinci_dm646x())
+               return 0;
+
+       platform_device_register(&dm646x_edma_device);
+       return 0;
+}
+postcore_initcall(dm646x_init_devices);
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -104,6 +104,12 @@
 
 #define edmacc_regs_base       IO_ADDRESS(DAVINCI_DMA_3PCC_BASE)
 
+
+#define EDMA_MAX_DMACH           64
+#define EDMA_MAX_PARAMENTRY     512
+#define EDMA_MAX_EVQUE            2    /* FIXME too small */
+
+
 /*****************************************************************************/
 
 static inline unsigned int edma_read(int offset)
@@ -199,55 +205,25 @@ static inline void edma_parm_or(int offs
 
 /*****************************************************************************/
 
-static struct platform_driver edma_driver = {
-       .driver.name    = "edma",
-};
-
-static struct resource edma_resources[] = {
-       {
-               .start  = DAVINCI_DMA_3PCC_BASE,
-               .end    = DAVINCI_DMA_3PCC_BASE + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .name   = "edma_tc0",
-               .start  = 0x01c10000,
-               .end    = 0x01c10000 + SZ_1K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .name   = "edma_tc1",
-               .start  = 0x01c10400,
-               .end    = 0x01c10400 + SZ_1K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device edma_dev = {
-       .name           = "edma",
-       .id             = -1,
-       .dev.driver     = &edma_driver.driver,
-       .num_resources  = ARRAY_SIZE(edma_resources),
-       .resource       = edma_resources,
-};
-
-/*****************************************************************************/
+/* actual number of DMA channels and slots on this silicon */
+static unsigned num_channels;
+static unsigned num_slots;
 
 static struct dma_interrupt_data {
        void (*callback)(unsigned channel, unsigned short ch_status, void 
*data);
        void *data;
-} intr_data[DAVINCI_EDMA_NUM_DMACH];
+} intr_data[EDMA_MAX_DMACH];
 
 /* The edma_inuse bit for each PaRAM slot is clear unless the
  * channel is in use ... by ARM or DSP, for QDMA, or whatever.
  */
-static DECLARE_BITMAP(edma_inuse, DAVINCI_EDMA_NUM_PARAMENTRY);
+static DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
 
 /* The edma_noevent bit for each channel is clear unless
  * it doesn't trigger DMA events on this platform.  It uses a
  * bit of SOC-specific initialization code.
  */
-static DECLARE_BITMAP(edma_noevent, DAVINCI_EDMA_NUM_DMACH);
+static DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
 
 /* dummy param set used to (re)initialize parameter RAM slots */
 static const struct edmacc_param dummy_paramset = {
@@ -255,16 +231,8 @@ static const struct edmacc_param dummy_p
        .ccnt = 1,
 };
 
-static const s8 __initconst dma_chan_dm644x_no_event[] = {
-       0, 1, 12, 13, 14, 15, 25, 30, 31, 45, 46, 47, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, -1
-};
-static const s8 __initconst dma_chan_dm355_no_event[] = {
-       12, 13, 24, 56, 57, 58, 59, 60, 61, 62, 63, -1
-};
-
 static const int __initconst
-queue_tc_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = {
+queue_tc_mapping[EDMA_MAX_EVQUE + 1][2] = {
 /* {event queue no, TC no} */
        {0, 0},
        {1, 1},
@@ -272,7 +240,7 @@ queue_tc_mapping[DAVINCI_EDMA_NUM_EVQUE 
 };
 
 static const int __initconst
-queue_priority_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = {
+queue_priority_mapping[EDMA_MAX_EVQUE + 1][2] = {
        /* {event queue no, Priority} */
        {0, 3},
        {1, 7},
@@ -337,7 +305,7 @@ static irqreturn_t dma_irq_handler(int i
        int i;
        unsigned int cnt = 0;
 
-       dev_dbg(&edma_dev.dev, "dma_irq_handler\n");
+       dev_dbg(data, "dma_irq_handler\n");
 
        if ((edma_shadow0_read_array(SH_IPR, 0) == 0)
            && (edma_shadow0_read_array(SH_IPR, 1) == 0))
@@ -351,7 +319,7 @@ static irqreturn_t dma_irq_handler(int i
                        j = 1;
                else
                        break;
-               dev_dbg(&edma_dev.dev, "IPR%d %08x\n", j,
+               dev_dbg(data, "IPR%d %08x\n", j,
                                edma_shadow0_read_array(SH_IPR, j));
                for (i = 0; i < 32; i++) {
                        int k = (j << 5) + i;
@@ -382,7 +350,7 @@ static irqreturn_t dma_ccerr_handler(int
        int i;
        unsigned int cnt = 0;
 
-       dev_dbg(&edma_dev.dev, "dma_ccerr_handler\n");
+       dev_dbg(data, "dma_ccerr_handler\n");
 
        if ((edma_read_array(EDMA_EMR, 0) == 0) &&
            (edma_read_array(EDMA_EMR, 1) == 0) &&
@@ -396,7 +364,7 @@ static irqreturn_t dma_ccerr_handler(int
                else if (edma_read_array(EDMA_EMR, 1))
                        j = 1;
                if (j >= 0) {
-                       dev_dbg(&edma_dev.dev, "EMR%d %08x\n", j,
+                       dev_dbg(data, "EMR%d %08x\n", j,
                                        edma_read_array(EDMA_EMR, j));
                        for (i = 0; i < 32; i++) {
                                int k = (j << 5) + i;
@@ -415,7 +383,7 @@ static irqreturn_t dma_ccerr_handler(int
                                }
                        }
                } else if (edma_read(EDMA_QEMR)) {
-                       dev_dbg(&edma_dev.dev, "QEMR %02x\n",
+                       dev_dbg(data, "QEMR %02x\n",
                                edma_read(EDMA_QEMR));
                        for (i = 0; i < 8; i++) {
                                if (edma_read(EDMA_QEMR) & (1 << i)) {
@@ -427,7 +395,7 @@ static irqreturn_t dma_ccerr_handler(int
                                }
                        }
                } else if (edma_read(EDMA_CCERR)) {
-                       dev_dbg(&edma_dev.dev, "CCERR %08x\n",
+                       dev_dbg(data, "CCERR %08x\n",
                                edma_read(EDMA_CCERR));
                        /* FIXME:  CCERR.BIT(16) ignored!  much better
                         * to just write CCERRCLR with CCERR value...
@@ -465,116 +433,16 @@ static irqreturn_t dma_ccerr_handler(int
 
 static irqreturn_t dma_tc0err_handler(int irq, void *data)
 {
-       dev_dbg(&edma_dev.dev, "dma_tc0err_handler\n");
+       dev_dbg(data, "dma_tc0err_handler\n");
        return IRQ_HANDLED;
 }
 
 static irqreturn_t dma_tc1err_handler(int irq, void *data)
 {
-       dev_dbg(&edma_dev.dev, "dma_tc1err_handler\n");
+       dev_dbg(data, "dma_tc1err_handler\n");
        return IRQ_HANDLED;
 }
 
-/******************************************************************************
- *
- * DMA initialisation on davinci
- *
- *****************************************************************************/
-static int __init davinci_dma_init(void)
-{
-       int i;
-       int status;
-       const s8 *noevent;
-
-       platform_driver_register(&edma_driver);
-       platform_device_register(&edma_dev);
-
-       dev_dbg(&edma_dev.dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base);
-
-       for (i = 0; i < DAVINCI_EDMA_NUM_PARAMENTRY; i++)
-               memcpy_toio(edmacc_regs_base + PARM_OFFSET(i),
-                               &dummy_paramset, PARM_SIZE);
-
-       if (cpu_is_davinci_dm355()) {
-               /* NOTE conflicts with SPI1_INT{0,1} and SPI2_INT0 */
-               davinci_cfg_reg(DM355_INT_EDMA_CC);
-               if (tc_errs_handled) {
-                       davinci_cfg_reg(DM355_INT_EDMA_TC0_ERR);
-                       davinci_cfg_reg(DM355_INT_EDMA_TC1_ERR);
-               }
-               noevent = dma_chan_dm355_no_event;
-       } else if (cpu_is_davinci_dm644x()) {
-               noevent = dma_chan_dm644x_no_event;
-       } else {
-               /* alloc_channel(EDMA_CHANNEL_ANY) fails */
-               noevent = NULL;
-       }
-
-       if (noevent) {
-               while (*noevent != -1)
-                       set_bit(*noevent++, edma_noevent);
-       }
-
-       status = request_irq(IRQ_CCINT0, dma_irq_handler, 0, "edma", NULL);
-       if (status < 0) {
-               dev_dbg(&edma_dev.dev, "request_irq %d failed --> %d\n",
-                       IRQ_CCINT0, status);
-               return status;
-       }
-       status = request_irq(IRQ_CCERRINT, dma_ccerr_handler, 0,
-                               "edma_error", NULL);
-       if (status < 0) {
-               dev_dbg(&edma_dev.dev, "request_irq %d failed --> %d\n",
-                       IRQ_CCERRINT, status);
-               return status;
-       }
-
-       if (tc_errs_handled) {
-               status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
-                                       "edma_tc0", NULL);
-               if (status < 0) {
-                       dev_dbg(&edma_dev.dev, "request_irq %d failed --> %d\n",
-                               IRQ_TCERRINT0, status);
-                       return status;
-               }
-               status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
-                                       "edma_tc1", NULL);
-               if (status < 0) {
-                       dev_dbg(&edma_dev.dev, "request_irq %d --> %d\n",
-                               IRQ_TCERRINT, status);
-                       return status;
-               }
-       }
-
-       /* Everything lives on transfer controller 1 until otherwise specified.
-        * This way, long transfers on the low priority queue
-        * started by the codec engine will not cause audio defects.
-        */
-       for (i = 0; i < DAVINCI_EDMA_NUM_DMACH; i++)
-               map_dmach_queue(i, EVENTQ_1);
-
-       i = 0;
-       /* Event queue to TC mapping */
-       while (queue_tc_mapping[i][0] != -1) {
-               map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);
-               i++;
-       }
-       i = 0;
-       /* Event queue priority mapping */
-       while (queue_priority_mapping[i][0] != -1) {
-               assign_priority_to_queue(queue_priority_mapping[i][0],
-                                        queue_priority_mapping[i][1]);
-               i++;
-       }
-       for (i = 0; i < DAVINCI_EDMA_NUM_REGIONS; i++) {
-               edma_write_array2(EDMA_DRAE, i, 0, 0x0);
-               edma_write_array2(EDMA_DRAE, i, 1, 0x0);
-               edma_write_array(EDMA_QRAE, i, 0x0);
-       }
-       return 0;
-}
-arch_initcall(davinci_dma_init);
-
 /*-----------------------------------------------------------------------*/
 
 /* Resource alloc/free:  dma channels, parameter RAM slots */
@@ -618,13 +486,13 @@ int edma_alloc_channel(int channel,
                channel = 0;
                for (;;) {
                        channel = find_next_zero_bit(edma_inuse,
-                                       DAVINCI_EDMA_NUM_DMACH, channel);
-                       if (channel == DAVINCI_EDMA_NUM_DMACH)
+                                       num_channels, channel);
+                       if (channel == num_channels)
                                return -ENOMEM;
                        if (!test_and_set_bit(channel, edma_inuse))
                                break;
                }
-       } else if (channel >= DAVINCI_EDMA_NUM_DMACH) {
+       } else if (channel >= num_channels) {
                return -EINVAL;
        } else if (test_and_set_bit(channel, edma_inuse)) {
                return -EBUSY;
@@ -661,7 +529,7 @@ EXPORT_SYMBOL(edma_alloc_channel);
  */
 void edma_free_channel(unsigned channel)
 {
-       if (channel >= DAVINCI_EDMA_NUM_DMACH)
+       if (channel >= num_channels)
                return;
 
        setup_dma_interrupt(channel, NULL, NULL);
@@ -690,17 +558,16 @@ EXPORT_SYMBOL(edma_free_channel);
 int edma_alloc_slot(int slot)
 {
        if (slot < 0) {
-               slot = DAVINCI_EDMA_NUM_DMACH;
+               slot = num_channels;
                for (;;) {
                        slot = find_next_zero_bit(edma_inuse,
-                                       DAVINCI_EDMA_NUM_PARAMENTRY, slot);
-                       if (slot == DAVINCI_EDMA_NUM_PARAMENTRY)
+                                       num_slots, slot);
+                       if (slot == num_slots)
                                return -ENOMEM;
                        if (!test_and_set_bit(slot, edma_inuse))
                                break;
                }
-       } else if (slot < DAVINCI_EDMA_NUM_DMACH
-                       || slot >= DAVINCI_EDMA_NUM_PARAMENTRY) {
+       } else if (slot < num_channels || slot >= num_slots) {
                return -EINVAL;
        } else if (test_and_set_bit(slot, edma_inuse)) {
                return -EBUSY;
@@ -723,8 +590,7 @@ EXPORT_SYMBOL(edma_alloc_slot);
  */
 void edma_free_slot(unsigned slot)
 {
-       if (slot < DAVINCI_EDMA_NUM_DMACH
-                       || slot >= DAVINCI_EDMA_NUM_PARAMENTRY)
+       if (slot < num_channels || slot >= num_slots)
                return;
 
        memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot),
@@ -751,7 +617,7 @@ EXPORT_SYMBOL(edma_free_slot);
 void edma_set_src(unsigned slot, dma_addr_t src_port,
                                enum address_mode mode, enum fifo_width width)
 {
-       if (slot < DAVINCI_EDMA_NUM_PARAMENTRY) {
+       if (slot < num_slots) {
                unsigned int i = edma_parm_read(PARM_OPT, slot);
 
                if (mode) {
@@ -784,7 +650,7 @@ EXPORT_SYMBOL(edma_set_src);
 void edma_set_dest(unsigned slot, dma_addr_t dest_port,
                                 enum address_mode mode, enum fifo_width width)
 {
-       if (slot < DAVINCI_EDMA_NUM_PARAMENTRY) {
+       if (slot < num_slots) {
                unsigned int i = edma_parm_read(PARM_OPT, slot);
 
                if (mode) {
@@ -835,7 +701,7 @@ EXPORT_SYMBOL(edma_get_position);
  */
 void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
 {
-       if (slot < DAVINCI_EDMA_NUM_PARAMENTRY) {
+       if (slot < num_slots) {
                edma_parm_modify(PARM_SRC_DST_BIDX, slot,
                                0xffff0000, src_bidx);
                edma_parm_modify(PARM_SRC_DST_CIDX, slot,
@@ -856,7 +722,7 @@ EXPORT_SYMBOL(edma_set_src_index);
  */
 void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
 {
-       if (slot < DAVINCI_EDMA_NUM_PARAMENTRY) {
+       if (slot < num_slots) {
                edma_parm_modify(PARM_SRC_DST_BIDX, slot,
                                0x0000ffff, dest_bidx << 16);
                edma_parm_modify(PARM_SRC_DST_CIDX, slot,
@@ -898,7 +764,7 @@ void edma_set_transfer_params(unsigned s
                u16 acnt, u16 bcnt, u16 ccnt,
                u16 bcnt_rld, enum sync_dimension sync_mode)
 {
-       if (slot < DAVINCI_EDMA_NUM_PARAMENTRY) {
+       if (slot < num_slots) {
                edma_parm_modify(PARM_LINK_BCNTRLD, slot,
                                0x0000ffff, bcnt_rld << 16);
                if (sync_mode == ASYNC)
@@ -921,9 +787,9 @@ EXPORT_SYMBOL(edma_set_transfer_params);
  */
 void edma_link(unsigned from, unsigned to)
 {
-       if (from >= DAVINCI_EDMA_NUM_PARAMENTRY)
+       if (from >= num_slots)
                return;
-       if (to >= DAVINCI_EDMA_NUM_PARAMENTRY)
+       if (to >= num_slots)
                return;
        edma_parm_modify(PARM_LINK_BCNTRLD, from, 0xffff0000, PARM_OFFSET(to));
 }
@@ -938,7 +804,7 @@ EXPORT_SYMBOL(edma_link);
  */
 void edma_unlink(unsigned from)
 {
-       if (from >= DAVINCI_EDMA_NUM_PARAMENTRY)
+       if (from >= num_slots)
                return;
        edma_parm_or(PARM_LINK_BCNTRLD, from, 0xffff);
 }
@@ -960,7 +826,7 @@ EXPORT_SYMBOL(edma_unlink);
  */
 void edma_write_slot(unsigned slot, const struct edmacc_param *param)
 {
-       if (slot >= DAVINCI_EDMA_NUM_PARAMENTRY)
+       if (slot >= num_slots)
                return;
        memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot), param, PARM_SIZE);
 }
@@ -976,7 +842,7 @@ EXPORT_SYMBOL(edma_write_slot);
  */
 void edma_read_slot(unsigned slot, struct edmacc_param *param)
 {
-       if (slot >= DAVINCI_EDMA_NUM_PARAMENTRY)
+       if (slot >= num_slots)
                return;
        memcpy_fromio(param, edmacc_regs_base + PARM_OFFSET(slot), PARM_SIZE);
 }
@@ -995,7 +861,7 @@ EXPORT_SYMBOL(edma_read_slot);
  */
 void edma_pause(unsigned channel)
 {
-       if (channel < DAVINCI_EDMA_NUM_DMACH) {
+       if (channel < num_channels) {
                unsigned int mask = (1 << (channel & 0x1f));
 
                edma_shadow0_write_array(SH_EECR, channel >> 5, mask);
@@ -1011,7 +877,7 @@ EXPORT_SYMBOL(edma_pause);
  */
 void edma_resume(unsigned channel)
 {
-       if (channel < DAVINCI_EDMA_NUM_DMACH) {
+       if (channel < num_channels) {
                unsigned int mask = (1 << (channel & 0x1f));
 
                edma_shadow0_write_array(SH_EESR, channel >> 5, mask);
@@ -1032,27 +898,27 @@ EXPORT_SYMBOL(edma_resume);
  */
 int edma_start(unsigned channel)
 {
-       if (channel < DAVINCI_EDMA_NUM_DMACH) {
+       if (channel < num_channels) {
                int j = channel >> 5;
                unsigned int mask = (1 << (channel & 0x1f));
 
                /* EDMA channels without event association */
                if (test_bit(channel, edma_noevent)) {
-                       dev_dbg(&edma_dev.dev, "ESR%d %08x\n", j,
+                       pr_debug("EDMA: ESR%d %08x\n", j,
                                edma_shadow0_read_array(SH_ESR, j));
                        edma_shadow0_write_array(SH_ESR, j, mask);
                        return 0;
                }
 
                /* EDMA channel with event association */
-               dev_dbg(&edma_dev.dev, "ER%d %08x\n", j,
+               pr_debug("EDMA: ER%d %08x\n", j,
                        edma_shadow0_read_array(SH_ER, j));
                /* Clear any pending error */
                edma_write_array(EDMA_EMCR, j, mask);
                /* Clear any SER */
                edma_shadow0_write_array(SH_SECR, j, mask);
                edma_shadow0_write_array(SH_EESR, j, mask);
-               dev_dbg(&edma_dev.dev, "EER%d %08x\n", j,
+               pr_debug("EDMA: EER%d %08x\n", j,
                        edma_shadow0_read_array(SH_EER, j));
                return 0;
        }
@@ -1072,7 +938,7 @@ EXPORT_SYMBOL(edma_start);
  */
 void edma_stop(unsigned channel)
 {
-       if (channel < DAVINCI_EDMA_NUM_DMACH) {
+       if (channel < num_channels) {
                int j = channel >> 5;
                unsigned int mask = (1 << (channel & 0x1f));
 
@@ -1081,7 +947,7 @@ void edma_stop(unsigned channel)
                edma_shadow0_write_array(SH_SECR, j, mask);
                edma_write_array(EDMA_EMCR, j, mask);
 
-               dev_dbg(&edma_dev.dev, "EER%d %08x\n", j,
+               pr_debug("EDMA: EER%d %08x\n", j,
                                edma_shadow0_read_array(SH_EER, j));
 
                /* REVISIT:  consider guarding against inappropriate event
@@ -1106,11 +972,11 @@ EXPORT_SYMBOL(edma_stop);
 
 void edma_clean_channel(unsigned channel)
 {
-       if (channel < DAVINCI_EDMA_NUM_DMACH) {
+       if (channel < num_channels) {
                int j = (channel >> 5);
                unsigned int mask = 1 << (channel & 0x1f);
 
-               dev_dbg(&edma_dev.dev, "EMR%d %08x\n", j,
+               pr_debug("EDMA: EMR%d %08x\n", j,
                                edma_read_array(EDMA_EMR, j));
                edma_shadow0_write_array(SH_ECR, j, mask);
                /* Clear the corresponding EMR bits */
@@ -1121,3 +987,109 @@ void edma_clean_channel(unsigned channel
        }
 }
 EXPORT_SYMBOL(edma_clean_channel);
+
+/*-----------------------------------------------------------------------*/
+
+static int __init edma_probe(struct platform_device *pdev)
+{
+       struct edma_soc_info    *info = pdev->dev.platform_data;
+       int                     i;
+       int                     status;
+       const s8                *noevent;
+       int                     irq = 0, err_irq = 0;
+
+       if (!info)
+               return -ENODEV;
+
+       num_channels = min_t(unsigned, info->n_channel, EDMA_MAX_DMACH);
+       num_slots = min_t(unsigned, info->n_slot, EDMA_MAX_PARAMENTRY);
+
+       dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base);
+
+       for (i = 0; i < num_slots; i++)
+               memcpy_toio(edmacc_regs_base + PARM_OFFSET(i),
+                               &dummy_paramset, PARM_SIZE);
+
+       noevent = info->noevent;
+       if (noevent) {
+               while (*noevent != -1)
+                       set_bit(*noevent++, edma_noevent);
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       status = request_irq(irq, dma_irq_handler, 0, "edma", &pdev->dev);
+       if (status < 0) {
+               dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+                       irq, status);
+               goto fail;
+       }
+
+       err_irq = platform_get_irq(pdev, 1);
+       status = request_irq(err_irq, dma_ccerr_handler, 0,
+                               "edma_error", &pdev->dev);
+       if (status < 0) {
+               dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+                       err_irq, status);
+               goto fail;
+       }
+
+       if (tc_errs_handled) {
+               status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+                                       "edma_tc0", &pdev->dev);
+               if (status < 0) {
+                       dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+                               IRQ_TCERRINT0, status);
+                       return status;
+               }
+               status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+                                       "edma_tc1", &pdev->dev);
+               if (status < 0) {
+                       dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+                               IRQ_TCERRINT, status);
+                       return status;
+               }
+       }
+
+       /* Everything lives on transfer controller 1 until otherwise specified.
+        * This way, long transfers on the low priority queue
+        * started by the codec engine will not cause audio defects.
+        */
+       for (i = 0; i < num_channels; i++)
+               map_dmach_queue(i, EVENTQ_1);
+
+       /* Event queue to TC mapping */
+       for (i = 0; queue_tc_mapping[i][0] != -1; i++)
+               map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);
+
+       /* Event queue priority mapping */
+       for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+               assign_priority_to_queue(queue_priority_mapping[i][0],
+                                        queue_priority_mapping[i][1]);
+
+       for (i = 0; i < info->n_region; i++) {
+               edma_write_array2(EDMA_DRAE, i, 0, 0x0);
+               edma_write_array2(EDMA_DRAE, i, 1, 0x0);
+               edma_write_array(EDMA_QRAE, i, 0x0);
+       }
+
+       return 0;
+
+fail:
+       if (err_irq)
+               free_irq(err_irq, NULL);
+       if (irq)
+               free_irq(irq, NULL);
+       return status;
+}
+
+
+static struct platform_driver edma_driver = {
+       .driver.name    = "edma",
+};
+
+static int __init edma_init(void)
+{
+       return platform_driver_probe(&edma_driver, edma_probe);
+}
+arch_initcall(edma_init);
+
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -91,16 +91,6 @@ struct edmacc_param {
 #define TRWORD (0x7<<2)
 #define PAENTRY (0x1ff<<5)
 
-
-#define DAVINCI_EDMA_NUM_DMACH           64
-
-#define DAVINCI_EDMA_NUM_PARAMENTRY     128
-#define DAVINCI_EDMA_NUM_EVQUE            2
-#define DAVINCI_EDMA_CHMAPEXIST           0
-#define DAVINCI_EDMA_NUM_REGIONS          4
-#define DAVINCI_EDMA_MEMPROTECT           0
-
-
 /* Drivers should avoid using these symbolic names for dm644x
  * channels, and use platform_device IORESOURCE_DMA resources
  * instead.  (Other DaVinci chips have different peripherals
@@ -221,4 +211,18 @@ void edma_resume(unsigned channel);
 /* UNRELATED TO DMA */
 int davinci_alloc_iram(unsigned size);
 void davinci_free_iram(unsigned addr, unsigned size);
+
+/* platform_data for EDMA driver */
+struct edma_soc_info {
+
+       /* how many dma resources of each type */
+       unsigned        n_channel;
+       unsigned        n_region;
+       unsigned        n_slot;
+       unsigned        n_tc;
+
+       /* list of channels with no even trigger; terminated by "-1" */
+       const s8        *noevent;
+};
+
 #endif

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to