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
