From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:45:28 +0000 Subject: [PATCH] add boot partition size --- kernel/drivers/dma/ti/edma.c | 398 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 288 insertions(+), 110 deletions(-) diff --git a/kernel/drivers/dma/ti/edma.c b/kernel/drivers/dma/ti/edma.c index 44158fa..35d81bd 100644 --- a/kernel/drivers/dma/ti/edma.c +++ b/kernel/drivers/dma/ti/edma.c @@ -15,7 +15,7 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> -#include <linux/edma.h> +#include <linux/bitmap.h> #include <linux/err.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -133,6 +133,17 @@ #define EDMA_CONT_PARAMS_FIXED_EXACT 1002 #define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003 +/* + * 64bit array registers are split into two 32bit registers: + * reg0: channel/event 0-31 + * reg1: channel/event 32-63 + * + * bit 5 in the channel number tells the array index (0/1) + * bit 0-4 (0x1f) is the bit offset within the register + */ +#define EDMA_REG_ARRAY_INDEX(channel) ((channel) >> 5) +#define EDMA_CHANNEL_BIT(channel) (BIT((channel) & 0x1f)) + /* PaRAM slots are laid out like this */ struct edmacc_param { u32 opt; @@ -169,6 +180,7 @@ struct list_head node; enum dma_transfer_direction direction; int cyclic; + bool polled; int absync; int pset_nr; struct edma_chan *echan; @@ -199,7 +211,7 @@ u32 residue; u32 residue_stat; - struct edma_pset pset[0]; + struct edma_pset pset[]; }; struct edma_cc; @@ -247,6 +259,13 @@ * in use by Linux or if it is allocated to be used by DSP. */ unsigned long *slot_inuse; + + /* + * For tracking reserved channels used by DSP. + * If the bit is cleared, the channel is allocated to be used by DSP + * and Linux must not touch it. + */ + unsigned long *channels_mask; struct dma_device dma_slave; struct dma_device *dma_memcpy; @@ -412,12 +431,6 @@ edma_or(ecc, EDMA_PARM + offset + (param_no << 5), or); } -static inline void edma_set_bits(int offset, int len, unsigned long *p) -{ - for (; len > 0; len--) - set_bit(offset + (len - 1), p); -} - static void edma_assign_priority_to_queue(struct edma_cc *ecc, int queue_no, int priority) { @@ -441,15 +454,14 @@ { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); if (enable) { - edma_shadow0_write_array(ecc, SH_ICR, channel >> 5, - BIT(channel & 0x1f)); - edma_shadow0_write_array(ecc, SH_IESR, channel >> 5, - BIT(channel & 0x1f)); + edma_shadow0_write_array(ecc, SH_ICR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_IESR, idx, ch_bit); } else { - edma_shadow0_write_array(ecc, SH_IECR, channel >> 5, - BIT(channel & 0x1f)); + edma_shadow0_write_array(ecc, SH_IECR, idx, ch_bit); } } @@ -587,26 +599,26 @@ { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - int j = (channel >> 5); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); if (!echan->hw_triggered) { /* EDMA channels without event association */ - dev_dbg(ecc->dev, "ESR%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_ESR, j)); - edma_shadow0_write_array(ecc, SH_ESR, j, mask); + dev_dbg(ecc->dev, "ESR%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_ESR, idx)); + edma_shadow0_write_array(ecc, SH_ESR, idx, ch_bit); } else { /* EDMA channel with event association */ - dev_dbg(ecc->dev, "ER%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_ER, j)); + dev_dbg(ecc->dev, "ER%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_ER, idx)); /* Clear any pending event or error */ - edma_write_array(ecc, EDMA_ECR, j, mask); - edma_write_array(ecc, EDMA_EMCR, j, mask); + edma_write_array(ecc, EDMA_ECR, idx, ch_bit); + edma_write_array(ecc, EDMA_EMCR, idx, ch_bit); /* Clear any SER */ - edma_shadow0_write_array(ecc, SH_SECR, j, mask); - edma_shadow0_write_array(ecc, SH_EESR, j, mask); - dev_dbg(ecc->dev, "EER%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_EER, j)); + edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_EESR, idx, ch_bit); + dev_dbg(ecc->dev, "EER%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_EER, idx)); } } @@ -614,19 +626,19 @@ { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - int j = (channel >> 5); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); - edma_shadow0_write_array(ecc, SH_EECR, j, mask); - edma_shadow0_write_array(ecc, SH_ECR, j, mask); - edma_shadow0_write_array(ecc, SH_SECR, j, mask); - edma_write_array(ecc, EDMA_EMCR, j, mask); + edma_shadow0_write_array(ecc, SH_EECR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_ECR, idx, ch_bit); + edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit); + edma_write_array(ecc, EDMA_EMCR, idx, ch_bit); /* clear possibly pending completion interrupt */ - edma_shadow0_write_array(ecc, SH_ICR, j, mask); + edma_shadow0_write_array(ecc, SH_ICR, idx, ch_bit); - dev_dbg(ecc->dev, "EER%d %08x\n", j, - edma_shadow0_read_array(ecc, SH_EER, j)); + dev_dbg(ecc->dev, "EER%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_EER, idx)); /* REVISIT: consider guarding against inappropriate event * chaining by overwriting with dummy_paramset. @@ -640,45 +652,49 @@ static void edma_pause(struct edma_chan *echan) { int channel = EDMA_CHAN_SLOT(echan->ch_num); - unsigned int mask = BIT(channel & 0x1f); - edma_shadow0_write_array(echan->ecc, SH_EECR, channel >> 5, mask); + edma_shadow0_write_array(echan->ecc, SH_EECR, + EDMA_REG_ARRAY_INDEX(channel), + EDMA_CHANNEL_BIT(channel)); } /* Re-enable EDMA hardware events on the specified channel. */ static void edma_resume(struct edma_chan *echan) { int channel = EDMA_CHAN_SLOT(echan->ch_num); - unsigned int mask = BIT(channel & 0x1f); - edma_shadow0_write_array(echan->ecc, SH_EESR, channel >> 5, mask); + edma_shadow0_write_array(echan->ecc, SH_EESR, + EDMA_REG_ARRAY_INDEX(channel), + EDMA_CHANNEL_BIT(channel)); } static void edma_trigger_channel(struct edma_chan *echan) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); - edma_shadow0_write_array(ecc, SH_ESR, (channel >> 5), mask); + edma_shadow0_write_array(ecc, SH_ESR, idx, ch_bit); - dev_dbg(ecc->dev, "ESR%d %08x\n", (channel >> 5), - edma_shadow0_read_array(ecc, SH_ESR, (channel >> 5))); + dev_dbg(ecc->dev, "ESR%d %08x\n", idx, + edma_shadow0_read_array(ecc, SH_ESR, idx)); } static void edma_clean_channel(struct edma_chan *echan) { struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); - int j = (channel >> 5); - unsigned int mask = BIT(channel & 0x1f); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); - dev_dbg(ecc->dev, "EMR%d %08x\n", j, edma_read_array(ecc, EDMA_EMR, j)); - edma_shadow0_write_array(ecc, SH_ECR, j, mask); + dev_dbg(ecc->dev, "EMR%d %08x\n", idx, + edma_read_array(ecc, EDMA_EMR, idx)); + edma_shadow0_write_array(ecc, SH_ECR, idx, ch_bit); /* Clear the corresponding EMR bits */ - edma_write_array(ecc, EDMA_EMCR, j, mask); + edma_write_array(ecc, EDMA_EMCR, idx, ch_bit); /* Clear any SER */ - edma_shadow0_write_array(ecc, SH_SECR, j, mask); + edma_shadow0_write_array(ecc, SH_SECR, idx, ch_bit); edma_write(ecc, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0)); } @@ -707,8 +723,15 @@ struct edma_cc *ecc = echan->ecc; int channel = EDMA_CHAN_SLOT(echan->ch_num); + if (!test_bit(echan->ch_num, ecc->channels_mask)) { + dev_err(ecc->dev, "Channel%d is reserved, can not be used!\n", + echan->ch_num); + return -EINVAL; + } + /* ensure access through shadow region 0 */ - edma_or_array2(ecc, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f)); + edma_or_array2(ecc, EDMA_DRAE, 0, EDMA_REG_ARRAY_INDEX(channel), + EDMA_CHANNEL_BIT(channel)); /* ensure no events are pending */ edma_stop(echan); @@ -1011,6 +1034,7 @@ src_cidx = cidx; dst_bidx = acnt; dst_cidx = cidx; + epset->addr = src_addr; } else { dev_err(dev, "%s: direction not implemented yet\n", __func__); return -EINVAL; @@ -1211,8 +1235,9 @@ edesc->pset[0].param.opt |= ITCCHEN; if (nslots == 1) { - /* Enable transfer complete interrupt */ - edesc->pset[0].param.opt |= TCINTEN; + /* Enable transfer complete interrupt if requested */ + if (tx_flags & DMA_PREP_INTERRUPT) + edesc->pset[0].param.opt |= TCINTEN; } else { /* Enable transfer complete chaining for the first slot */ edesc->pset[0].param.opt |= TCCHEN; @@ -1239,8 +1264,88 @@ } edesc->pset[1].param.opt |= ITCCHEN; - edesc->pset[1].param.opt |= TCINTEN; + /* Enable transfer complete interrupt if requested */ + if (tx_flags & DMA_PREP_INTERRUPT) + edesc->pset[1].param.opt |= TCINTEN; } + + if (!(tx_flags & DMA_PREP_INTERRUPT)) + edesc->polled = true; + + return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); +} + +static struct dma_async_tx_descriptor * +edma_prep_dma_interleaved(struct dma_chan *chan, + struct dma_interleaved_template *xt, + unsigned long tx_flags) +{ + struct device *dev = chan->device->dev; + struct edma_chan *echan = to_edma_chan(chan); + struct edmacc_param *param; + struct edma_desc *edesc; + size_t src_icg, dst_icg; + int src_bidx, dst_bidx; + + /* Slave mode is not supported */ + if (is_slave_direction(xt->dir)) + return NULL; + + if (xt->frame_size != 1 || xt->numf == 0) + return NULL; + + if (xt->sgl[0].size > SZ_64K || xt->numf > SZ_64K) + return NULL; + + src_icg = dmaengine_get_src_icg(xt, &xt->sgl[0]); + if (src_icg) { + src_bidx = src_icg + xt->sgl[0].size; + } else if (xt->src_inc) { + src_bidx = xt->sgl[0].size; + } else { + dev_err(dev, "%s: SRC constant addressing is not supported\n", + __func__); + return NULL; + } + + dst_icg = dmaengine_get_dst_icg(xt, &xt->sgl[0]); + if (dst_icg) { + dst_bidx = dst_icg + xt->sgl[0].size; + } else if (xt->dst_inc) { + dst_bidx = xt->sgl[0].size; + } else { + dev_err(dev, "%s: DST constant addressing is not supported\n", + __func__); + return NULL; + } + + if (src_bidx > SZ_64K || dst_bidx > SZ_64K) + return NULL; + + edesc = kzalloc(struct_size(edesc, pset, 1), GFP_ATOMIC); + if (!edesc) + return NULL; + + edesc->direction = DMA_MEM_TO_MEM; + edesc->echan = echan; + edesc->pset_nr = 1; + + param = &edesc->pset[0].param; + + param->src = xt->src_start; + param->dst = xt->dst_start; + param->a_b_cnt = xt->numf << 16 | xt->sgl[0].size; + param->ccnt = 1; + param->src_dst_bidx = (dst_bidx << 16) | src_bidx; + param->src_dst_cidx = 0; + + param->opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num)); + param->opt |= ITCCHEN; + /* Enable transfer complete interrupt if requested */ + if (tx_flags & DMA_PREP_INTERRUPT) + param->opt |= TCINTEN; + else + edesc->polled = true; return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); } @@ -1721,7 +1826,11 @@ int loop_count = EDMA_MAX_TR_WAIT_LOOPS; struct edma_chan *echan = edesc->echan; struct edma_pset *pset = edesc->pset; - dma_addr_t done, pos; + dma_addr_t done, pos, pos_old; + int channel = EDMA_CHAN_SLOT(echan->ch_num); + int idx = EDMA_REG_ARRAY_INDEX(channel); + int ch_bit = EDMA_CHANNEL_BIT(channel); + int event_reg; int i; /* @@ -1734,16 +1843,20 @@ * "pos" may represent a transfer request that is still being * processed by the EDMACC or EDMATC. We will busy wait until * any one of the situations occurs: - * 1. the DMA hardware is idle - * 2. a new transfer request is setup + * 1. while and event is pending for the channel + * 2. a position updated * 3. we hit the loop limit */ - while (edma_read(echan->ecc, EDMA_CCSTAT) & EDMA_CCSTAT_ACTV) { - /* check if a new transfer request is setup */ - if (edma_get_position(echan->ecc, - echan->slot[0], dst) != pos) { + if (is_slave_direction(edesc->direction)) + event_reg = SH_ER; + else + event_reg = SH_ESR; + + pos_old = pos; + while (edma_shadow0_read_array(echan->ecc, event_reg, idx) & ch_bit) { + pos = edma_get_position(echan->ecc, echan->slot[0], dst); + if (pos != pos_old) break; - } if (!--loop_count) { dev_dbg_ratelimited(echan->vchan.chan.device->dev, @@ -1768,6 +1881,12 @@ return edesc->residue_stat; } + /* + * If the position is 0, then EDMA loaded the closing dummy slot, the + * transfer is completed + */ + if (!pos) + return 0; /* * For SG operation we catch up with the last processed * status. @@ -1796,19 +1915,46 @@ struct dma_tx_state *txstate) { struct edma_chan *echan = to_edma_chan(chan); - struct virt_dma_desc *vdesc; + struct dma_tx_state txstate_tmp; enum dma_status ret; unsigned long flags; ret = dma_cookie_status(chan, cookie, txstate); - if (ret == DMA_COMPLETE || !txstate) + + if (ret == DMA_COMPLETE) return ret; + /* Provide a dummy dma_tx_state for completion checking */ + if (!txstate) + txstate = &txstate_tmp; + spin_lock_irqsave(&echan->vchan.lock, flags); - if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) + if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) { txstate->residue = edma_residue(echan->edesc); - else if ((vdesc = vchan_find_desc(&echan->vchan, cookie))) - txstate->residue = to_edma_desc(&vdesc->tx)->residue; + } else { + struct virt_dma_desc *vdesc = vchan_find_desc(&echan->vchan, + cookie); + + if (vdesc) + txstate->residue = to_edma_desc(&vdesc->tx)->residue; + else + txstate->residue = 0; + } + + /* + * Mark the cookie completed if the residue is 0 for non cyclic + * transfers + */ + if (ret != DMA_COMPLETE && !txstate->residue && + echan->edesc && echan->edesc->polled && + echan->edesc->vdesc.tx.cookie == cookie) { + edma_stop(echan); + vchan_cookie_complete(&echan->edesc->vdesc); + echan->edesc = NULL; + edma_execute(echan); + ret = DMA_COMPLETE; + } + spin_unlock_irqrestore(&echan->vchan.lock, flags); return ret; @@ -1846,7 +1992,9 @@ "Legacy memcpy is enabled, things might not work\n"); dma_cap_set(DMA_MEMCPY, s_ddev->cap_mask); + dma_cap_set(DMA_INTERLEAVE, s_ddev->cap_mask); s_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy; + s_ddev->device_prep_interleaved_dma = edma_prep_dma_interleaved; s_ddev->directions = BIT(DMA_MEM_TO_MEM); } @@ -1882,8 +2030,10 @@ dma_cap_zero(m_ddev->cap_mask); dma_cap_set(DMA_MEMCPY, m_ddev->cap_mask); + dma_cap_set(DMA_INTERLEAVE, m_ddev->cap_mask); m_ddev->device_prep_dma_memcpy = edma_prep_dma_memcpy; + m_ddev->device_prep_interleaved_dma = edma_prep_dma_interleaved; m_ddev->device_alloc_chan_resources = edma_alloc_chan_resources; m_ddev->device_free_chan_resources = edma_free_chan_resources; m_ddev->device_issue_pending = edma_issue_pending; @@ -2185,14 +2335,14 @@ } #endif +static bool edma_filter_fn(struct dma_chan *chan, void *param); + static int edma_probe(struct platform_device *pdev) { struct edma_soc_info *info = pdev->dev.platform_data; s8 (*queue_priority_mapping)[2]; - int i, off, ln; - const s16 (*rsv_slots)[2]; - const s16 (*xbar_chans)[2]; - int irq; + const s16 (*reserved)[2]; + int i, irq; char *irq_name; struct resource *mem; struct device_node *node = pdev->dev.of_node; @@ -2217,13 +2367,6 @@ if (!info) return -ENODEV; - - pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - dev_err(dev, "pm_runtime_get_sync() failed\n"); - return ret; - } ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) @@ -2255,33 +2398,54 @@ platform_set_drvdata(pdev, ecc); + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "pm_runtime_get_sync() failed\n"); + pm_runtime_disable(dev); + return ret; + } + /* Get eDMA3 configuration from IP */ ret = edma_setup_from_hw(dev, info, ecc); if (ret) - return ret; + goto err_disable_pm; /* Allocate memory based on the information we got from the IP */ ecc->slave_chans = devm_kcalloc(dev, ecc->num_channels, sizeof(*ecc->slave_chans), GFP_KERNEL); - if (!ecc->slave_chans) - return -ENOMEM; ecc->slot_inuse = devm_kcalloc(dev, BITS_TO_LONGS(ecc->num_slots), sizeof(unsigned long), GFP_KERNEL); - if (!ecc->slot_inuse) - return -ENOMEM; + + ecc->channels_mask = devm_kcalloc(dev, + BITS_TO_LONGS(ecc->num_channels), + sizeof(unsigned long), GFP_KERNEL); + if (!ecc->slave_chans || !ecc->slot_inuse || !ecc->channels_mask) { + ret = -ENOMEM; + goto err_disable_pm; + } + + /* Mark all channels available initially */ + bitmap_fill(ecc->channels_mask, ecc->num_channels); ecc->default_queue = info->default_queue; if (info->rsv) { /* Set the reserved slots in inuse list */ - rsv_slots = info->rsv->rsv_slots; - if (rsv_slots) { - for (i = 0; rsv_slots[i][0] != -1; i++) { - off = rsv_slots[i][0]; - ln = rsv_slots[i][1]; - edma_set_bits(off, ln, ecc->slot_inuse); - } + reserved = info->rsv->rsv_slots; + if (reserved) { + for (i = 0; reserved[i][0] != -1; i++) + bitmap_set(ecc->slot_inuse, reserved[i][0], + reserved[i][1]); + } + + /* Clear channels not usable for Linux */ + reserved = info->rsv->rsv_chans; + if (reserved) { + for (i = 0; reserved[i][0] != -1; i++) + bitmap_clear(ecc->channels_mask, reserved[i][0], + reserved[i][1]); } } @@ -2289,14 +2453,6 @@ /* Reset only unused - not reserved - paRAM slots */ if (!test_bit(i, ecc->slot_inuse)) edma_write_slot(ecc, i, &dummy_paramset); - } - - /* Clear the xbar mapped channels in unused list */ - xbar_chans = info->xbar_chans; - if (xbar_chans) { - for (i = 0; xbar_chans[i][1] != -1; i++) { - off = xbar_chans[i][1]; - } } irq = platform_get_irq_byname(pdev, "edma3_ccint"); @@ -2310,7 +2466,7 @@ ecc); if (ret) { dev_err(dev, "CCINT (%d) failed --> %d\n", irq, ret); - return ret; + goto err_disable_pm; } ecc->ccint = irq; } @@ -2326,7 +2482,7 @@ ecc); if (ret) { dev_err(dev, "CCERRINT (%d) failed --> %d\n", irq, ret); - return ret; + goto err_disable_pm; } ecc->ccerrint = irq; } @@ -2334,13 +2490,15 @@ ecc->dummy_slot = edma_alloc_slot(ecc, EDMA_SLOT_ANY); if (ecc->dummy_slot < 0) { dev_err(dev, "Can't allocate PaRAM dummy slot\n"); - return ecc->dummy_slot; + ret = ecc->dummy_slot; + goto err_disable_pm; } queue_priority_mapping = info->queue_priority_mapping; if (!ecc->legacy_mode) { int lowest_priority = 0; + unsigned int array_max; struct of_phandle_args tc_args; ecc->tc_list = devm_kcalloc(dev, ecc->num_tc, @@ -2364,6 +2522,18 @@ info->default_queue = i; } } + + /* See if we have optional dma-channel-mask array */ + array_max = DIV_ROUND_UP(ecc->num_channels, BITS_PER_TYPE(u32)); + ret = of_property_read_variable_u32_array(node, + "dma-channel-mask", + (u32 *)ecc->channels_mask, + 1, array_max); + if (ret > 0 && ret != array_max) + dev_warn(dev, "dma-channel-mask is not complete.\n"); + else if (ret == -EOVERFLOW || ret == -ENODATA) + dev_warn(dev, + "dma-channel-mask is out of range or empty\n"); } /* Event queue priority mapping */ @@ -2371,17 +2541,20 @@ edma_assign_priority_to_queue(ecc, queue_priority_mapping[i][0], queue_priority_mapping[i][1]); - for (i = 0; i < ecc->num_region; i++) { - edma_write_array2(ecc, EDMA_DRAE, i, 0, 0x0); - edma_write_array2(ecc, EDMA_DRAE, i, 1, 0x0); - edma_write_array(ecc, EDMA_QRAE, i, 0x0); - } + edma_write_array2(ecc, EDMA_DRAE, 0, 0, 0x0); + edma_write_array2(ecc, EDMA_DRAE, 0, 1, 0x0); + edma_write_array(ecc, EDMA_QRAE, 0, 0x0); + ecc->info = info; /* Init the dma device and channels */ edma_dma_init(ecc, legacy_mode); for (i = 0; i < ecc->num_channels; i++) { + /* Do not touch reserved channels */ + if (!test_bit(i, ecc->channels_mask)) + continue; + /* Assign all channels to the default queue */ edma_assign_channel_eventq(&ecc->slave_chans[i], info->default_queue); @@ -2418,6 +2591,9 @@ err_reg1: edma_free_slot(ecc, ecc->dummy_slot); +err_disable_pm: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); return ret; } @@ -2448,6 +2624,8 @@ if (ecc->dma_memcpy) dma_async_device_unregister(ecc->dma_memcpy); edma_free_slot(ecc, ecc->dummy_slot); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); return 0; } @@ -2487,8 +2665,9 @@ for (i = 0; i < ecc->num_channels; i++) { if (echan[i].alloced) { /* ensure access through shadow region 0 */ - edma_or_array2(ecc, EDMA_DRAE, 0, i >> 5, - BIT(i & 0x1f)); + edma_or_array2(ecc, EDMA_DRAE, 0, + EDMA_REG_ARRAY_INDEX(i), + EDMA_CHANNEL_BIT(i)); edma_setup_interrupt(&echan[i], true); @@ -2529,7 +2708,7 @@ }, }; -bool edma_filter_fn(struct dma_chan *chan, void *param) +static bool edma_filter_fn(struct dma_chan *chan, void *param) { bool match = false; @@ -2544,7 +2723,6 @@ } return match; } -EXPORT_SYMBOL(edma_filter_fn); static int edma_init(void) { -- Gitblit v1.6.2