On Tue, Apr 15, 2014 at 05:13:37PM +0200, Laurent Pinchart wrote: > The MMP/PXA DMA engine supports transfer initiation by external chips > through DMA request (DREQ) signals. Support them by clearing pending DMA > requests for the associated source when starting a channel. > > The request ID to DREQ index mapping depends on the hardware and is > passed through platform data or DT. > > Cc: devicetree@xxxxxxxxxxxxxxx > Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > --- > Documentation/devicetree/bindings/dma/mmp-dma.txt | 2 + > drivers/dma/mmp_pdma.c | 96 ++++++++++++++++++++--- > include/linux/platform_data/mmp_dma.h | 2 + > 3 files changed, 87 insertions(+), 13 deletions(-) > > diff --git a/Documentation/devicetree/bindings/dma/mmp-dma.txt b/Documentation/devicetree/bindings/dma/mmp-dma.txt > index 7a802f6..edb9ff3 100644 > --- a/Documentation/devicetree/bindings/dma/mmp-dma.txt > +++ b/Documentation/devicetree/bindings/dma/mmp-dma.txt > @@ -12,6 +12,8 @@ Required properties: > Optional properties: > - #dma-channels: Number of DMA channels supported by the controller (defaults > to 32 when not specified) > +- marvell,dreq: Array of the DMA request IDs corresponding to each of the > + external device request (DREQ) lines > > "marvell,pdma-1.0" > Used platforms: pxa25x, pxa27x, pxa3xx, pxa93x, pxa168, pxa910, pxa688. Can you please split the binding to separate patch and we need to get an ACK on it from DT folks. The below looks fine to me -- ~Vinod > diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c > index 849bf75..4546a1c 100644 > --- a/drivers/dma/mmp_pdma.c > +++ b/drivers/dma/mmp_pdma.c > @@ -27,6 +27,7 @@ > > #define DCSR 0x0000 > #define DALGN 0x00a0 > +#define DRQSR(n) (0x00e0 + ((n) << 2)) > #define DINT 0x00f0 > #define DDADR 0x0200 > #define DSADR 0x0204 > @@ -50,6 +51,9 @@ > #define DCSR_CMPST BIT(10) /* The Descriptor Compare Status */ > #define DCSR_EORINTR BIT(9) /* The end of Receive */ > > +#define DRQSR_CLR BIT(8) /* Clear Pending Requests */ > +#define DRQSR_REQPEND 0x1f /* Requests Pending */ > + > #define DRCMR(n) ((((n) < 64) ? 0x0100 : 0x1100) + (((n) & 0x3f) << 2)) > #define DRCMR_MAPVLD BIT(7) /* Map Valid (read / write) */ > #define DRCMR_CHLNUM 0x1f /* mask for Channel Number (read / write) */ > @@ -108,6 +112,7 @@ struct mmp_pdma_chan { > u32 dcmd; > u32 drcmr; > u32 dev_addr; > + int drq; > > /* list for desc */ > spinlock_t desc_lock; /* Descriptor list lock */ > @@ -127,6 +132,8 @@ struct mmp_pdma_phy { > > struct mmp_pdma_device { > int dma_channels; > + unsigned int num_dreq; > + const u32 *dreq; > void __iomem *base; > struct device *dev; > struct dma_device device; > @@ -167,6 +174,9 @@ static void enable_chan(struct mmp_pdma_phy *phy) > dalgn &= ~(1 << phy->idx); > writel(dalgn, phy->base + DALGN); > > + if (phy->vchan->drq != -1) > + writel(DRQSR_CLR, phy->base + DRQSR(phy->vchan->drq)); > + > reg = (phy->idx << 2) + DCSR; > writel(readl(phy->base + reg) | DCSR_RUN, phy->base + reg); > } > @@ -685,6 +695,22 @@ fail: > return NULL; > } > > +static void mmp_pdma_set_drcmr(struct mmp_pdma_chan *chan, unsigned int drmcr) > +{ > + struct mmp_pdma_device *pdev = to_mmp_pdma_dev(cchan->chan.device); > + unsigned int i; > + > + chan->drcmr = drmcr; > + chan->drq = -1; > + > + for (i = 0; i < pdev->num_dreq; ++i) { > + if (pdev->dreq[i] == drmcr) { > + chan->drq = i; > + break; > + } > + } > +} > + > static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, > unsigned long arg) > { > @@ -745,7 +771,7 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, > * be removed. > */ > if (cfg->slave_id) > - chan->drcmr = cfg->slave_id; > + mmp_pdma_set_drcmr(chan, cfg->slave_id); > break; > default: > return -ENOSYS; > @@ -909,16 +935,64 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec, > if (!chan) > return NULL; > > - to_mmp_pdma_chan(chan)->drcmr = dma_spec->args[0]; > + mmp_pdma_set_drcmr(to_mmp_pdma_chan(chan), dma_spec->args[0]); > > return chan; > } > > +static int mmap_pdma_parse_platform_data(struct mmp_pdma_device *pdev) > +{ > + struct device_node *np = pdev->dev->of_node; > + struct property *prop; > + > + /* Default values: 32 channels, no external DREQ. */ > + pdev->dma_channels = 32; > + pdev->num_dreq = 0; > + > + if (!IS_ENABLED(CONFIG_OF) || !np) { > + struct mmp_dma_platdata *pdata = dev_get_platdata(pdev->dev); > + > + if (!pdata) > + return 0; > + > + if (pdata->dma_channels) > + pdev->dma_channels = pdata->dma_channels; > + if (pdata->num_dreq) { > + pdev->num_dreq = pdata->num_dreq; > + pdev->dreq = pdata->dreq; > + } > + > + return 0; > + } > + > + of_property_read_u32(np, "#dma-channels", &pdev->dma_channels); > + > + prop = of_find_property(np, "marvell,dreq"); > + if (prop) { > + unsigned int num_dreq = prop->length / sizeof(unsigned long); > + u32 *dreq; > + > + dreq = devm_kcalloc(pdev->dev, num_dreq, sizeof(*pdreq), > + GFP_KERNEL); > + if (dreq == NULL) > + return -ENOMEM; > + > + ret = of_property_read_u32_array(np, "marvell,dreq", dreq, > + num_dreq); > + if (ret < 0) > + return ret; > + > + pdev->num_dreq = num_dreq; > + pdev->dreq = dreq; > + } > + > + return 0; > +} > + > static int mmp_pdma_probe(struct platform_device *op) > { > struct mmp_pdma_device *pdev; > const struct of_device_id *of_id; > - struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev); > struct resource *iores; > int i, ret, irq = 0; > int dma_channels = 0, irq_num = 0; > @@ -936,15 +1010,11 @@ static int mmp_pdma_probe(struct platform_device *op) > if (IS_ERR(pdev->base)) > return PTR_ERR(pdev->base); > > - of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev); > - if (of_id) > - of_property_read_u32(pdev->dev->of_node, "#dma-channels", > - &dma_channels); > - else if (pdata && pdata->dma_channels) > - dma_channels = pdata->dma_channels; > - else > - dma_channels = 32; /* default 32 channel */ > - pdev->dma_channels = dma_channels; > + ret = mmp_pdma_parse_platform_data(pdev); > + if (ret < 0) > + return ret; > + > + dma_channels = pdev->dma_channels; > > for (i = 0; i < dma_channels; i++) { > if (platform_get_irq(op, i) > 0) > @@ -1038,7 +1108,7 @@ bool mmp_pdma_filter_fn(struct dma_chan *chan, void *param) > if (chan->device->dev->driver != &mmp_pdma_driver.driver) > return false; > > - c->drcmr = *(unsigned int *)param; > + mmp_pdma_set_drcmr(c, *(unsigned int *)param); > > return true; > } > diff --git a/include/linux/platform_data/mmp_dma.h b/include/linux/platform_data/mmp_dma.h > index 2a330ec..32595b8 100644 > --- a/include/linux/platform_data/mmp_dma.h > +++ b/include/linux/platform_data/mmp_dma.h > @@ -14,6 +14,8 @@ > > struct mmp_dma_platdata { > int dma_channels; > + unsigned int num_dreq; > + const u32 *dreq; > }; > > #endif /* MMP_DMA_H */ > -- > 1.8.3.2 > > -- > To unsubscribe from this list: send the line "unsubscribe dmaengine" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html