From: David Brownell <[email protected]> Learn that the dm355 and dm644x chips have different sets of valid DMA event channels. Those channels are now represented using a bitmap, which is small and much quicker to test than the previous array.
MMC1 DMA now works on dm355; it uses channels that dm6446 doesn't. Minor cleanups of the DMA code: spelling/grammar, and marking const data arrays as such. Shrink some data. Signed-off-by: David Brownell <[email protected]> --- CHANGE since last version: represent valid DMA event channels using a bitmap. It's much cleaner. arch/arm/mach-davinci/dma.c | 146 +++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 71 deletions(-) --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -29,6 +29,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/spinlock.h> +#include <linux/compiler.h> #include <linux/io.h> #include <mach/cpu.h> @@ -259,27 +260,27 @@ static struct dma_interrupt_data { } intr_data[64]; /* - Each bit field of the elements bellow indicate the corresponding EDMA channel + Each bit field of the elements below indicates corresponding EDMA channel availability on arm side events */ -static unsigned long edma_channels_arm[] = { +static const unsigned long edma_channels_arm[] = { 0xffffffff, 0xffffffff }; /* - Each bit field of the elements bellow indicate the corresponding QDMA channel + Each bit field of the elements below indicates corresponding QDMA channel availability on arm side events */ -static unsigned char qdma_channels_arm[] = { +static const unsigned char qdma_channels_arm[] = { 0x00 }; /* - Each bit field of the elements bellow indicate corresponding PARAM entry - availibility on arm side events + Each bit field of the elements below indicates corresponding PARAM entry + availability on arm side events */ -static unsigned long param_entry_arm[] = { +static const unsigned long param_entry_arm[] = { 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, @@ -287,7 +288,7 @@ static unsigned long param_entry_arm[] = }; /* - Each bit field of the elements bellow indicate whether a PARAM entry + Each bit field of the elements below indicates whether a PARAM entry is free or in use 1 - free 0 - in use @@ -300,7 +301,7 @@ static unsigned long param_entry_use_sta }; /* - Each bit field of the elements bellow indicate whether a intrerrupt + Each bit field of the elements below indicates whether an interrupt is free or in use 1 - free 0 - in use @@ -310,23 +311,28 @@ static unsigned long dma_intr_use_status 0xffffffff }; -/* - This lists the DMA channel numbers which does not have any events - associated with it -*/ -static int dma_chan_no_event[] = { +/* The edma_noevent bit for each master 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 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 int queue_tc_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = { +static const int queue_tc_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = { /* {event queue no, TC no} */ {0, 0}, {1, 1}, {-1, -1} }; -static int queue_priority_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = { +static const int queue_priority_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = { /* {event queue no, Priority} */ {0, 3}, {1, 7}, @@ -335,7 +341,6 @@ static int queue_priority_mapping[DAVINC static int qdam_to_param_mapping[8] = { 0 }; - /*****************************************************************************/ static void map_dmach_queue(int ch_no, int queue_no) @@ -386,7 +391,8 @@ static void __init assign_priority_to_qu *****************************************************************************/ static int request_param(int lch, int dev_id) { - int i = 0, j = 0, is_break = 0; + int i = 0; + if (lch >= 0 && lch < DAVINCI_EDMA_NUM_DMACH) { /* In davinci there is 1:1 mapping between edma channels @@ -416,17 +422,16 @@ static int request_param(int lch, int de LOCK; while (i < DAVINCI_EDMA_NUM_PARAMENTRY) { - j = 0, is_break = 1; if ((param_entry_arm[i / 32] & (1 << (i % 32))) && (param_entry_use_status[i / 32] & (1 << (i % 32)))) { + /* if (dev_id == DAVINCI_DMA_CHANNEL_ANY + * || DAVINCI_EDMA_IS_Q(dev_id)) ... + */ if (dev_id != DAVINCI_EDMA_PARAM_ANY) { - while (dma_chan_no_event[j] != -1) { - if (dma_chan_no_event[j] == i) - is_break = 0; - j++; - } - if (!is_break) + if (i >= DAVINCI_EDMA_NUM_DMACH) + continue; + if (test_bit(i, edma_noevent)) break; } else { break; @@ -491,7 +496,8 @@ static int request_dma_interrupt(int lch void *data, int param_no, int requested_tcc) { signed int free_intr_no = -1; - int i = 0, j = 0, is_break = 0; + int i = 0; + /* edma channels */ if (lch >= 0 && lch < DAVINCI_EDMA_NUM_DMACH) { /* Bitmap dma_intr_use_status is used to identify availabe tcc @@ -524,17 +530,9 @@ static int request_dma_interrupt(int lch LOCK; if (dma_intr_use_status[requested_tcc / 32] & (1 << (requested_tcc % 32))) { - j = 0; - is_break = 1; - while (dma_chan_no_event[j] != -1) { - if (dma_chan_no_event[j] == - requested_tcc) { - is_break = 0; - break; - } - j++; - } - if (!is_break) { + if (requested_tcc < DAVINCI_EDMA_NUM_DMACH + && test_bit(requested_tcc, + edma_noevent)) { dma_intr_use_status[requested_tcc / 32] &= (~(1 << (requested_tcc % 32))); free_intr_no = requested_tcc; @@ -558,18 +556,9 @@ static int request_dma_interrupt(int lch i = 0; LOCK; while (i < DAVINCI_EDMA_NUM_DMACH) { - j = 0; - is_break = 1; if (dma_intr_use_status[i / 32] & (1 << (i % 32))) { - while (dma_chan_no_event[j] != -1) { - if (dma_chan_no_event[j] == i) { - is_break = 0; - break; - } - j++; - } - if (!is_break) { + if (test_bit(i, edma_noevent)) { dma_intr_use_status[i / 32] &= (~(1 << (i % 32))); free_intr_no = i; @@ -586,12 +575,10 @@ static int request_dma_interrupt(int lch } UNLOCK; } - } else { - dev_dbg(&edma_dev.dev, "ERROR lch = %d\r\n", lch); } - if (is_break) { - dev_dbg(&edma_dev.dev, - "While allocating EDMA channel for QDMA"); + if (free_intr_no < 0) { + dev_dbg(&edma_dev.dev, "no IRQ for channel %d\n", lch); + return -EIO; } if (DAVINCI_EDMA_IS_Q(lch)) { edma_or_array2(EDMA_DRAE, 0, free_intr_no >> 5, @@ -801,6 +788,7 @@ static int __init davinci_dma_init(void) { int i; int status; + const s8 *noevent; platform_driver_register(&edma_driver); platform_device_register(&edma_dev); @@ -817,6 +805,17 @@ static int __init davinci_dma_init(void) 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 { + /* request_dma(DAVINCI_DMA_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); @@ -1013,17 +1012,24 @@ int davinci_request_dma(int dev_id, cons map_dmach_queue(dev_id, eventq_no); ret_val = 0; } + + /* return some master channel with no event association */ } else if (dev_id == DAVINCI_DMA_CHANNEL_ANY) { i = 0; ret_val = 0; - while (dma_chan_no_event[i] != -1) { - if (!dma_chan[dma_chan_no_event[i]].in_use) { + for (;;) { + i = find_next_bit(edma_noevent, i, + DAVINCI_EDMA_NUM_DMACH); + if (i == DAVINCI_EDMA_NUM_DMACH) + break; + if (!dma_chan[i].in_use) { int j; - *lch = dma_chan_no_event[i]; - j = dma_chan[*lch].param_no = - request_param(*lch, dev_id); + + *lch = i; + j = request_param(*lch, dev_id); if (j == -1) return -EINVAL; + dma_chan[*lch].param_no = j; dev_dbg(&edma_dev.dev, "param_no=%d\r\n", j); if (DAVINCI_EDMA_IS_Q(j)) { edma_or_array(EDMA_QRAE, 0, 1 << (j - @@ -1047,8 +1053,9 @@ int davinci_request_dma(int dev_id, cons ret_val = 0; break; } - i++; } + + /* return some slave channel */ } else if (dev_id == DAVINCI_EDMA_PARAM_ANY) { ret_val = 0; for (i = DAVINCI_EDMA_QEND; @@ -1080,7 +1087,7 @@ int davinci_request_dma(int dev_id, cons } if (!ret_val) { if (DAVINCI_EDMA_IS_Q(dev_id)) { - /* Master Channel */ + /* Channel used for QDMA */ unsigned int opt; int temp_ch = dma_chan[*lch].param_no; qdam_to_param_mapping[dev_id - DAVINCI_EDMA_QSTART] = @@ -1106,7 +1113,7 @@ int davinci_request_dma(int dev_id, cons edma_parm_or(PARM_LINK_BCNTRLD, temp_ch, 0xffff); } else { int j; - /* Slave Channel */ + /* Normal master or slave Channel */ LOCK; /* Global structure to identify whether resoures is available or not */ @@ -1377,20 +1384,17 @@ int davinci_start_dma(int lch) { int ret_val = 0; if ((lch >= 0) && (lch < DAVINCI_EDMA_NUM_DMACH)) { - int i = 0; int j = lch >> 5; unsigned int mask = (1 << (lch & 0x1f)); - /* If the dma start request is for the unused events */ - while (dma_chan_no_event[i] != -1) { - if (dma_chan_no_event[i] == lch) { - /* EDMA channels without event association */ - dev_dbg(&edma_dev.dev, "ESR%d=%x\r\n", j, - edma_shadow0_read_array(SH_ESR, j)); - edma_shadow0_write_array(SH_ESR, j, mask); - return ret_val; - } - i++; + + /* EDMA channels without event association */ + if (test_bit(lch, edma_noevent)) { + dev_dbg(&edma_dev.dev, "ESR%d %08x\n", j, + edma_shadow0_read_array(SH_ESR, j)); + edma_shadow0_write_array(SH_ESR, j, mask); + return ret_val; } + /* EDMA channel with event association */ dev_dbg(&edma_dev.dev, "ER%d=%x\r\n", j, edma_shadow0_read_array(SH_ER, j)); _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
