* [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure
2014-04-15 15:13 [PATCH 0/6] dma: mmp_pdma: fly-by transfers and external DMA requests support Laurent Pinchart
@ 2014-04-15 15:13 ` Laurent Pinchart
2014-05-02 15:46 ` Vinod Koul
2014-05-05 17:26 ` Lars-Peter Clausen
2014-04-15 15:13 ` [PATCH 2/6] dma: mmp_pdma: Fix the #dma-channels DT property documentation Laurent Pinchart
` (4 subsequent siblings)
5 siblings, 2 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-04-15 15:13 UTC (permalink / raw)
To: linux-arm-kernel
Fly-by transfer mode cuts down the number of bus transactions by letting
the slave drive or latch the memory data bus during memory transactions
instead of performing a dedicated transaction to read data from or write
data to the slave.
Support for fly-by mode by adding a new flag field to struct
dma_slave_config.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
include/linux/dmaengine.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index c5c92d5..ae99153 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -304,6 +304,17 @@ enum dma_slave_buswidth {
};
/**
+ * enum dma_slave_flags - DMA slave configuration flags
+ * @DMA_SLAVE_FLAG_FLY_BY - perform DMA transfers for the slave in fly-by mode.
+ * Instead of performing a bus transaction to read (write) data from (to) the
+ * slave, let the slave drive (latch) the memory bus data signals during the
+ * memory write (read) transaction.
+ */
+enum dma_slave_flags {
+ DMA_SLAVE_FLAG_FLY_BY = (1 << 0),
+};
+
+/**
* struct dma_slave_config - dma slave channel runtime config
* @direction: whether the data shall go in or out on this slave
* channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are
@@ -333,6 +344,7 @@ enum dma_slave_buswidth {
* @slave_id: Slave requester id. Only valid for slave channels. The dma
* slave peripheral will have unique id as dma requester which need to be
* pass as slave config.
+ * @flags: DMA slave flags, a combination of enum dma_slave_flags flags.
*
* This struct is passed in as configuration data to a DMA engine
* in order to set up a certain channel for DMA transport@runtime.
@@ -361,6 +373,7 @@ struct dma_slave_config {
u32 dst_maxburst;
bool device_fc;
unsigned int slave_id;
+ u32 flags;
};
/**
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure
2014-04-15 15:13 ` [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure Laurent Pinchart
@ 2014-05-02 15:46 ` Vinod Koul
2014-05-02 15:47 ` Vinod Koul
2014-05-05 17:26 ` Lars-Peter Clausen
1 sibling, 1 reply; 14+ messages in thread
From: Vinod Koul @ 2014-05-02 15:46 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Apr 15, 2014 at 05:13:32PM +0200, Laurent Pinchart wrote:
> Fly-by transfer mode cuts down the number of bus transactions by letting
> the slave drive or latch the memory data bus during memory transactions
?? ^^^^^^^^^^^
> instead of performing a dedicated transaction to read data from or write
/ ^^^^
> data to the slave.
>
> Support for fly-by mode by adding a new flag field to struct
> dma_slave_config.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> include/linux/dmaengine.h | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index c5c92d5..ae99153 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -304,6 +304,17 @@ enum dma_slave_buswidth {
> };
>
> /**
> + * enum dma_slave_flags - DMA slave configuration flags
> + * @DMA_SLAVE_FLAG_FLY_BY - perform DMA transfers for the slave in fly-by mode.
> + * Instead of performing a bus transaction to read (write) data from (to) the
> + * slave, let the slave drive (latch) the memory bus data signals during the
> + * memory write (read) transaction.
> + */
> +enum dma_slave_flags {
> + DMA_SLAVE_FLAG_FLY_BY = (1 << 0),
> +};
> +
> +/**
> * struct dma_slave_config - dma slave channel runtime config
> * @direction: whether the data shall go in or out on this slave
> * channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are
> @@ -333,6 +344,7 @@ enum dma_slave_buswidth {
> * @slave_id: Slave requester id. Only valid for slave channels. The dma
> * slave peripheral will have unique id as dma requester which need to be
> * pass as slave config.
> + * @flags: DMA slave flags, a combination of enum dma_slave_flags flags.
> *
> * This struct is passed in as configuration data to a DMA engine
> * in order to set up a certain channel for DMA transport at runtime.
> @@ -361,6 +373,7 @@ struct dma_slave_config {
> u32 dst_maxburst;
> bool device_fc;
> unsigned int slave_id;
> + u32 flags;
> };
I am not sure about this. Should we have a generic flag for this or just add a
bool for fly_by mode?
Suggestions?
--
~Vinod
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure
2014-05-02 15:46 ` Vinod Koul
@ 2014-05-02 15:47 ` Vinod Koul
0 siblings, 0 replies; 14+ messages in thread
From: Vinod Koul @ 2014-05-02 15:47 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, May 02, 2014 at 09:16:34PM +0530, Vinod Koul wrote:
+ Dan
Pls cc Dan as well
~Vinod
> On Tue, Apr 15, 2014 at 05:13:32PM +0200, Laurent Pinchart wrote:
> > Fly-by transfer mode cuts down the number of bus transactions by letting
> > the slave drive or latch the memory data bus during memory transactions
> ?? ^^^^^^^^^^^
> > instead of performing a dedicated transaction to read data from or write
> / ^^^^
> > data to the slave.
> >
> > Support for fly-by mode by adding a new flag field to struct
> > dma_slave_config.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > include/linux/dmaengine.h | 13 +++++++++++++
> > 1 file changed, 13 insertions(+)
> >
> > diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> > index c5c92d5..ae99153 100644
> > --- a/include/linux/dmaengine.h
> > +++ b/include/linux/dmaengine.h
> > @@ -304,6 +304,17 @@ enum dma_slave_buswidth {
> > };
> >
> > /**
> > + * enum dma_slave_flags - DMA slave configuration flags
> > + * @DMA_SLAVE_FLAG_FLY_BY - perform DMA transfers for the slave in fly-by mode.
> > + * Instead of performing a bus transaction to read (write) data from (to) the
> > + * slave, let the slave drive (latch) the memory bus data signals during the
> > + * memory write (read) transaction.
> > + */
> > +enum dma_slave_flags {
> > + DMA_SLAVE_FLAG_FLY_BY = (1 << 0),
> > +};
> > +
> > +/**
> > * struct dma_slave_config - dma slave channel runtime config
> > * @direction: whether the data shall go in or out on this slave
> > * channel, right now. DMA_MEM_TO_DEV and DMA_DEV_TO_MEM are
> > @@ -333,6 +344,7 @@ enum dma_slave_buswidth {
> > * @slave_id: Slave requester id. Only valid for slave channels. The dma
> > * slave peripheral will have unique id as dma requester which need to be
> > * pass as slave config.
> > + * @flags: DMA slave flags, a combination of enum dma_slave_flags flags.
> > *
> > * This struct is passed in as configuration data to a DMA engine
> > * in order to set up a certain channel for DMA transport at runtime.
> > @@ -361,6 +373,7 @@ struct dma_slave_config {
> > u32 dst_maxburst;
> > bool device_fc;
> > unsigned int slave_id;
> > + u32 flags;
> > };
> I am not sure about this. Should we have a generic flag for this or just add a
> bool for fly_by mode?
>
> Suggestions?
>
> --
> ~Vinod
>
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure
2014-04-15 15:13 ` [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure Laurent Pinchart
2014-05-02 15:46 ` Vinod Koul
@ 2014-05-05 17:26 ` Lars-Peter Clausen
1 sibling, 0 replies; 14+ messages in thread
From: Lars-Peter Clausen @ 2014-05-05 17:26 UTC (permalink / raw)
To: linux-arm-kernel
On 04/15/2014 05:13 PM, Laurent Pinchart wrote:
> Fly-by transfer mode cuts down the number of bus transactions by letting
> the slave drive or latch the memory data bus during memory transactions
> instead of performing a dedicated transaction to read data from or write
> data to the slave.
>
> Support for fly-by mode by adding a new flag field to struct
> dma_slave_config.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> include/linux/dmaengine.h | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index c5c92d5..ae99153 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -304,6 +304,17 @@ enum dma_slave_buswidth {
> };
>
> /**
> + * enum dma_slave_flags - DMA slave configuration flags
> + * @DMA_SLAVE_FLAG_FLY_BY - perform DMA transfers for the slave in fly-by mode.
> + * Instead of performing a bus transaction to read (write) data from (to) the
> + * slave, let the slave drive (latch) the memory bus data signals during the
> + * memory write (read) transaction.
> + */
Is there any reason not to use fly-by mode for memory to peripheral or
peripheral to memory transfers, if fly-by mode is available? And if not how
should generic drivers using the DMAengine API decide when to use fly-by mode
and when not?
- Lars
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] dma: mmp_pdma: Fix the #dma-channels DT property documentation
2014-04-15 15:13 [PATCH 0/6] dma: mmp_pdma: fly-by transfers and external DMA requests support Laurent Pinchart
2014-04-15 15:13 ` [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure Laurent Pinchart
@ 2014-04-15 15:13 ` Laurent Pinchart
2014-05-02 15:50 ` Vinod Koul
2014-04-15 15:13 ` [PATCH 3/6] dma: mmp_pdma: Simplify access to channel drcmr value Laurent Pinchart
` (3 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2014-04-15 15:13 UTC (permalink / raw)
To: linux-arm-kernel
The property is optional and defaults to 32. Document it as such.
Cc: devicetree at vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/devicetree/bindings/dma/mmp-dma.txt | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/mmp-dma.txt b/Documentation/devicetree/bindings/dma/mmp-dma.txt
index a4fa4ef..7a802f6 100644
--- a/Documentation/devicetree/bindings/dma/mmp-dma.txt
+++ b/Documentation/devicetree/bindings/dma/mmp-dma.txt
@@ -1,17 +1,20 @@
* MARVELL MMP DMA controller
Marvell Peripheral DMA Controller
-Used platfroms: pxa688, pxa910, pxa3xx, etc
+Used platforms: pxa688, pxa910, pxa3xx, etc
Required properties:
- compatible: Should be "marvell,pdma-1.0"
- reg: Should contain DMA registers location and length.
- interrupts: Either contain all of the per-channel DMA interrupts
or one irq for pdma device
-- #dma-channels: Number of DMA channels supported by the controller.
+
+Optional properties:
+- #dma-channels: Number of DMA channels supported by the controller (defaults
+ to 32 when not specified)
"marvell,pdma-1.0"
-Used platfroms: pxa25x, pxa27x, pxa3xx, pxa93x, pxa168, pxa910, pxa688.
+Used platforms: pxa25x, pxa27x, pxa3xx, pxa93x, pxa168, pxa910, pxa688.
Examples:
@@ -45,7 +48,7 @@ pdma: dma-controller at d4000000 {
Marvell Two Channel DMA Controller used specifically for audio
-Used platfroms: pxa688, pxa910
+Used platforms: pxa688, pxa910
Required properties:
- compatible: Should be "marvell,adma-1.0" or "marvell,pxa910-squ"
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 3/6] dma: mmp_pdma: Simplify access to channel drcmr value
2014-04-15 15:13 [PATCH 0/6] dma: mmp_pdma: fly-by transfers and external DMA requests support Laurent Pinchart
2014-04-15 15:13 ` [PATCH 1/6] dmaengine: Add fly-by transfer flag to slave configuration structure Laurent Pinchart
2014-04-15 15:13 ` [PATCH 2/6] dma: mmp_pdma: Fix the #dma-channels DT property documentation Laurent Pinchart
@ 2014-04-15 15:13 ` Laurent Pinchart
2014-05-02 15:51 ` Vinod Koul
2014-04-15 15:13 ` [PATCH 4/6] dma: mmp_pdma: Fix physical channel memory allocation size Laurent Pinchart
` (2 subsequent siblings)
5 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2014-04-15 15:13 UTC (permalink / raw)
To: linux-arm-kernel
As the physical channel and virtual channel point to each other,
pchan->phy->vchan is always equal to pchan. Simplify the code
accordingly.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/dma/mmp_pdma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index b439679..643f225 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -277,7 +277,7 @@ static void mmp_pdma_free_phy(struct mmp_pdma_chan *pchan)
return;
/* clear the channel mapping in DRCMR */
- reg = DRCMR(pchan->phy->vchan->drcmr);
+ reg = DRCMR(pchan->drcmr);
writel(0, pchan->phy->base + reg);
spin_lock_irqsave(&pdev->phy_lock, flags);
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 4/6] dma: mmp_pdma: Fix physical channel memory allocation size
2014-04-15 15:13 [PATCH 0/6] dma: mmp_pdma: fly-by transfers and external DMA requests support Laurent Pinchart
` (2 preceding siblings ...)
2014-04-15 15:13 ` [PATCH 3/6] dma: mmp_pdma: Simplify access to channel drcmr value Laurent Pinchart
@ 2014-04-15 15:13 ` Laurent Pinchart
2014-05-02 15:52 ` Vinod Koul
2014-04-15 15:13 ` [PATCH 5/6] dma: mmp_pdma: Add support for fly-by transfers Laurent Pinchart
2014-04-15 15:13 ` [PATCH 6/6] dma: mmp_pdma: Add support externel DMA requests Laurent Pinchart
5 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2014-04-15 15:13 UTC (permalink / raw)
To: linux-arm-kernel
Use sizeof(*var) instead of sizeof(type) when calling devm_k*alloc().
This avoids using the wrong type as was done to allocate the physical
channels array.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/dma/mmp_pdma.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 643f225..7ed7850 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -858,8 +858,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq)
struct mmp_pdma_chan *chan;
int ret;
- chan = devm_kzalloc(pdev->dev, sizeof(struct mmp_pdma_chan),
- GFP_KERNEL);
+ chan = devm_kzalloc(pdev->dev, sizeof(*chan), GFP_KERNEL);
if (chan == NULL)
return -ENOMEM;
@@ -946,8 +945,7 @@ static int mmp_pdma_probe(struct platform_device *op)
irq_num++;
}
- pdev->phy = devm_kcalloc(pdev->dev,
- dma_channels, sizeof(struct mmp_pdma_chan),
+ pdev->phy = devm_kcalloc(pdev->dev, dma_channels, sizeof(*pdev->phy),
GFP_KERNEL);
if (pdev->phy == NULL)
return -ENOMEM;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 5/6] dma: mmp_pdma: Add support for fly-by transfers
2014-04-15 15:13 [PATCH 0/6] dma: mmp_pdma: fly-by transfers and external DMA requests support Laurent Pinchart
` (3 preceding siblings ...)
2014-04-15 15:13 ` [PATCH 4/6] dma: mmp_pdma: Fix physical channel memory allocation size Laurent Pinchart
@ 2014-04-15 15:13 ` Laurent Pinchart
2014-04-15 15:13 ` [PATCH 6/6] dma: mmp_pdma: Add support externel DMA requests Laurent Pinchart
5 siblings, 0 replies; 14+ messages in thread
From: Laurent Pinchart @ 2014-04-15 15:13 UTC (permalink / raw)
To: linux-arm-kernel
Enable fly-by mode when the DMA_SLAVE_FLAG_FLY_BY flag is set in the
slave configuration.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/dma/mmp_pdma.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 7ed7850..849bf75 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -63,6 +63,8 @@
#define DCMD_FLOWTRG BIT(28) /* Flow Control by the target. */
#define DCMD_STARTIRQEN BIT(22) /* Start Interrupt Enable */
#define DCMD_ENDIRQEN BIT(21) /* End Interrupt Enable */
+#define DCMD_FLYBYS BIT(20) /* Fly-By Source */
+#define DCMD_FLYBYT BIT(19) /* Fly-By Target */
#define DCMD_ENDIAN BIT(18) /* Device Endian-ness. */
#define DCMD_BURST8 (1 << 16) /* 8 byte burst */
#define DCMD_BURST16 (2 << 16) /* 16 byte burst */
@@ -708,11 +710,15 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
case DMA_SLAVE_CONFIG:
if (cfg->direction == DMA_DEV_TO_MEM) {
chan->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC;
+ if (cfg->flags & DMA_SLAVE_FLAG_FLY_BY)
+ chan->dcmd |= DCMD_FLYBYT;
maxburst = cfg->src_maxburst;
width = cfg->src_addr_width;
addr = cfg->src_addr;
} else if (cfg->direction == DMA_MEM_TO_DEV) {
chan->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+ if (cfg->flags & DMA_SLAVE_FLAG_FLY_BY)
+ chan->dcmd |= DCMD_FLYBYS;
maxburst = cfg->dst_maxburst;
width = cfg->dst_addr_width;
addr = cfg->dst_addr;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 6/6] dma: mmp_pdma: Add support externel DMA requests
2014-04-15 15:13 [PATCH 0/6] dma: mmp_pdma: fly-by transfers and external DMA requests support Laurent Pinchart
` (4 preceding siblings ...)
2014-04-15 15:13 ` [PATCH 5/6] dma: mmp_pdma: Add support for fly-by transfers Laurent Pinchart
@ 2014-04-15 15:13 ` Laurent Pinchart
2014-05-02 16:09 ` Vinod Koul
5 siblings, 1 reply; 14+ messages in thread
From: Laurent Pinchart @ 2014-04-15 15:13 UTC (permalink / raw)
To: linux-arm-kernel
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 at vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
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.
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
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 6/6] dma: mmp_pdma: Add support externel DMA requests
2014-04-15 15:13 ` [PATCH 6/6] dma: mmp_pdma: Add support externel DMA requests Laurent Pinchart
@ 2014-05-02 16:09 ` Vinod Koul
0 siblings, 0 replies; 14+ messages in thread
From: Vinod Koul @ 2014-05-02 16:09 UTC (permalink / raw)
To: linux-arm-kernel
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 at vger.kernel.org
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> 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 at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
^ permalink raw reply [flat|nested] 14+ messages in thread