* [PATCH RFC v12 0/7] MPC512x DMA slave s/g support, OF DMA lookup
@ 2014-04-23 13:53 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
2013/7/14 Gerhard Sittig <gsi-ynQEQJNshbs@public.gmane.org>:
> this series
> - introduces slave s/g support (that's support for DMA transfers which
> involve peripherals in contrast to mem-to-mem transfers)
> - adds device tree based lookup support for DMA channels
> - combines floating patches and related feedback which already covered
> several aspects of what the suggested LPB driver needs, to demonstrate
> how integration might be done
> - carries Q&D SD card support to enable another DMA client during test,
> while this patch needs to get dropped upon pickup
Changes in v2:
> - re-order mpc8308 related code paths for improved readability, no
> change in behaviour, introduction of symbolic channel names here
> already
> - squash 'execute() start condition' and 'terminate all' into the
> introduction of 'slave s/g prep' and 'device control' support; refuse
> s/g lists with more than one item since slave support is operational
> yet proper s/g support is missing (can get addressed later)
> - always start transfers from software on MPC8308 as there are no
> external request lines for peripheral flow control
> - drop dt-bindings header file and symbolic channel names in OF nodes
Changes in v3 and v4:
Part 1/5:
- use #define instead of enum since individual channels don't require
special handling.
Part 2/5:
- add a flag "will_access_peripheral" to DMA transfer descriptor
according recommendations of Gerhard Sittig.
This flag is set in mpc_dma_prep_memcpy() and mpc_dma_prep_slave_sg()
and is evaluated in mpc_dma_execute() to choose a type of start for
the transfer.
- prevent descriptors of transfers which involve peripherals from
being chained together;
each of such transfers needs hardware initiated start.
- add locking while working with struct mpc_dma_chan
according recommendations of Lars-Peter Clausen.
- remove default nbytes value. Client kernel modules must set
src_maxburst and dst_maxburst fields of struct dma_slave_config (dmaengine.h).
Changes in v5:
Part 2/5:
- add and improve comments;
- improve the code moving transfer descriptors from 'queued' to 'active' list
in mpc_dma_execute();
- allow mpc_dma_prep_slave_sg() to run with non-empty 'active' list;
- take 'mdesc' back to 'free' list in case of error in mpc_dma_prep_slave_sg();
- improve checks of the transfer parameters;
- provide the default value for 'maxburst' in mpc_dma_device_control().
Changes in v6:
Part 2/5:
- remove doubtful comment;
- fix coding style issues;
- set default value for 'maxburst' to 1 which applies to most cases;
Part 3/5:
- use dma_get_slave_channel() instead of dma_request_channel()
in new function of_dma_xlate_by_chan_id() according recommendations of
Arnd Bergmann;
Part 4/5:
- set DMA_PRIVATE flag for MPC512x DMA controller since its driver relies on
of_dma_xlate_by_chan_id() which doesn't use dma_request_channel()
any more; (removed in v7)
- resolve little patch conflict;
Part 5/5:
- resolve little patch conflict;
Changes in v7:
Part 2:
- improve comment;
Part 4:
- split in two separate patches. Part 4/6 contains device tree
binding document and in part 5/6 MPC512x DMA controller is registered
for device tree channel lookup;
- remove setting DMA_PRIVATE flag for MPC512x DMA controller from part 5/6;
Changes in v8:
Part 2:
- improve comments;
- fix style issues;
Part 6:
- remove since it has become obsolete;
Changes in v9:
A new patch (part 3/6) is added to this series according the
feedback of Andy Shevchenko.
Part 2/6:
- keep style of the comments;
- use is_slave_direction() instead of manual checks;
- remove redundant else branches of the conditions;
- make mpc_dma_device_control() return -ENXIO for unknown command;
Part 6/6:
- change according the new part 3/6;
- fix style issues;
Changes in v10:
Part 2/6:
- don't use direction field of dma_slave_config in mpc_dma_device_control()
but store settings in mpc_dma_chan for both DMA_DEV_TO_MEM and
DMA_MEM_TO_DEV cases; then retrieve the needed values in
mpc_dma_prep_slave_sg();
- fix style issue and put 2014 instead of 2013;
Part 3/6:
- fix mpc_dma_probe() error path and mpc_dma_remove(): manually free IRQs and
dispose IRQ mappings before devm_* takes care of other resources;
Part 6/6:
- change according the new part 3/6;
- fix style issue;
Changes in v11:
Part 5/6:
- remake device tree binding document according the recommendations of
Gerhard Sittig, Mark Rutland and Arnd Bergmann;
Changes in v12:
A new patch (part 2/7) is added to this series.
Part 6/7:
- change the description of 'compatible' property according part 2/7;
- improve the document according Gerhard's feedback;
> known issues:
> - it's yet to get confirmed whether MPC8308 can use slave support or
> whether the DMA controller's driver shall actively reject it, the
> information that's available so far suggests that peripheral transfers
> to IP bus attached I/O is useful and shall not get blocked right away
- adding support for transfers which don't increment the RAM address or
do increment the peripheral "port's" address is easy with
this implementation; but which options of the common API
should be used for specifying such transfers?
Alexander Popov (7):
dma: mpc512x: reorder mpc8308 specific instructions
dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
dma: mpc512x: add support for peripheral transfers
dma: mpc512x: fix freeing resources in mpc_dma_probe() and
mpc_dma_remove()
dma: of: add common xlate function for matching by channel id
dma: mpc512x: add device tree binding document
dma: mpc512x: register for device tree channel lookup
.../devicetree/bindings/dma/mpc512x-dma.txt | 40 +++
arch/powerpc/boot/dts/mpc5121.dtsi | 1 +
arch/powerpc/boot/dts/mpc8308_p1m.dts | 2 +-
arch/powerpc/boot/dts/mpc8308rdb.dts | 2 +-
drivers/dma/mpc512x_dma.c | 346 ++++++++++++++++++---
drivers/dma/of-dma.c | 35 +++
include/linux/of_dma.h | 4 +
7 files changed, 390 insertions(+), 40 deletions(-)
create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt
--
1.8.4.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH RFC v12 0/7] MPC512x DMA slave s/g support, OF DMA lookup
@ 2014-04-23 13:53 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Cc: devicetree
2013/7/14 Gerhard Sittig <gsi@denx.de>:
> this series
> - introduces slave s/g support (that's support for DMA transfers which
> involve peripherals in contrast to mem-to-mem transfers)
> - adds device tree based lookup support for DMA channels
> - combines floating patches and related feedback which already covered
> several aspects of what the suggested LPB driver needs, to demonstrate
> how integration might be done
> - carries Q&D SD card support to enable another DMA client during test,
> while this patch needs to get dropped upon pickup
Changes in v2:
> - re-order mpc8308 related code paths for improved readability, no
> change in behaviour, introduction of symbolic channel names here
> already
> - squash 'execute() start condition' and 'terminate all' into the
> introduction of 'slave s/g prep' and 'device control' support; refuse
> s/g lists with more than one item since slave support is operational
> yet proper s/g support is missing (can get addressed later)
> - always start transfers from software on MPC8308 as there are no
> external request lines for peripheral flow control
> - drop dt-bindings header file and symbolic channel names in OF nodes
Changes in v3 and v4:
Part 1/5:
- use #define instead of enum since individual channels don't require
special handling.
Part 2/5:
- add a flag "will_access_peripheral" to DMA transfer descriptor
according recommendations of Gerhard Sittig.
This flag is set in mpc_dma_prep_memcpy() and mpc_dma_prep_slave_sg()
and is evaluated in mpc_dma_execute() to choose a type of start for
the transfer.
- prevent descriptors of transfers which involve peripherals from
being chained together;
each of such transfers needs hardware initiated start.
- add locking while working with struct mpc_dma_chan
according recommendations of Lars-Peter Clausen.
- remove default nbytes value. Client kernel modules must set
src_maxburst and dst_maxburst fields of struct dma_slave_config (dmaengine.h).
Changes in v5:
Part 2/5:
- add and improve comments;
- improve the code moving transfer descriptors from 'queued' to 'active' list
in mpc_dma_execute();
- allow mpc_dma_prep_slave_sg() to run with non-empty 'active' list;
- take 'mdesc' back to 'free' list in case of error in mpc_dma_prep_slave_sg();
- improve checks of the transfer parameters;
- provide the default value for 'maxburst' in mpc_dma_device_control().
Changes in v6:
Part 2/5:
- remove doubtful comment;
- fix coding style issues;
- set default value for 'maxburst' to 1 which applies to most cases;
Part 3/5:
- use dma_get_slave_channel() instead of dma_request_channel()
in new function of_dma_xlate_by_chan_id() according recommendations of
Arnd Bergmann;
Part 4/5:
- set DMA_PRIVATE flag for MPC512x DMA controller since its driver relies on
of_dma_xlate_by_chan_id() which doesn't use dma_request_channel()
any more; (removed in v7)
- resolve little patch conflict;
Part 5/5:
- resolve little patch conflict;
Changes in v7:
Part 2:
- improve comment;
Part 4:
- split in two separate patches. Part 4/6 contains device tree
binding document and in part 5/6 MPC512x DMA controller is registered
for device tree channel lookup;
- remove setting DMA_PRIVATE flag for MPC512x DMA controller from part 5/6;
Changes in v8:
Part 2:
- improve comments;
- fix style issues;
Part 6:
- remove since it has become obsolete;
Changes in v9:
A new patch (part 3/6) is added to this series according the
feedback of Andy Shevchenko.
Part 2/6:
- keep style of the comments;
- use is_slave_direction() instead of manual checks;
- remove redundant else branches of the conditions;
- make mpc_dma_device_control() return -ENXIO for unknown command;
Part 6/6:
- change according the new part 3/6;
- fix style issues;
Changes in v10:
Part 2/6:
- don't use direction field of dma_slave_config in mpc_dma_device_control()
but store settings in mpc_dma_chan for both DMA_DEV_TO_MEM and
DMA_MEM_TO_DEV cases; then retrieve the needed values in
mpc_dma_prep_slave_sg();
- fix style issue and put 2014 instead of 2013;
Part 3/6:
- fix mpc_dma_probe() error path and mpc_dma_remove(): manually free IRQs and
dispose IRQ mappings before devm_* takes care of other resources;
Part 6/6:
- change according the new part 3/6;
- fix style issue;
Changes in v11:
Part 5/6:
- remake device tree binding document according the recommendations of
Gerhard Sittig, Mark Rutland and Arnd Bergmann;
Changes in v12:
A new patch (part 2/7) is added to this series.
Part 6/7:
- change the description of 'compatible' property according part 2/7;
- improve the document according Gerhard's feedback;
> known issues:
> - it's yet to get confirmed whether MPC8308 can use slave support or
> whether the DMA controller's driver shall actively reject it, the
> information that's available so far suggests that peripheral transfers
> to IP bus attached I/O is useful and shall not get blocked right away
- adding support for transfers which don't increment the RAM address or
do increment the peripheral "port's" address is easy with
this implementation; but which options of the common API
should be used for specifying such transfers?
Alexander Popov (7):
dma: mpc512x: reorder mpc8308 specific instructions
dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
dma: mpc512x: add support for peripheral transfers
dma: mpc512x: fix freeing resources in mpc_dma_probe() and
mpc_dma_remove()
dma: of: add common xlate function for matching by channel id
dma: mpc512x: add device tree binding document
dma: mpc512x: register for device tree channel lookup
.../devicetree/bindings/dma/mpc512x-dma.txt | 40 +++
arch/powerpc/boot/dts/mpc5121.dtsi | 1 +
arch/powerpc/boot/dts/mpc8308_p1m.dts | 2 +-
arch/powerpc/boot/dts/mpc8308rdb.dts | 2 +-
drivers/dma/mpc512x_dma.c | 346 ++++++++++++++++++---
drivers/dma/of-dma.c | 35 +++
include/linux/of_dma.h | 4 +
7 files changed, 390 insertions(+), 40 deletions(-)
create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt
--
1.8.4.2
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH RFC v12 1/7] dma: mpc512x: reorder mpc8308 specific instructions
2014-04-23 13:53 ` Alexander Popov
(?)
@ 2014-04-23 13:53 ` Alexander Popov
2014-05-02 17:06 ` Vinod Koul
-1 siblings, 1 reply; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Concentrate the specific code for MPC8308 in the 'if' branch
and handle MPC512x in the 'else' branch.
This modification only reorders instructions but doesn't change behaviour.
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
Acked-by: Anatolij Gustschin <agust@denx.de>
---
drivers/dma/mpc512x_dma.c | 42 +++++++++++++++++++++++++-----------------
1 file changed, 25 insertions(+), 17 deletions(-)
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 448750d..2ce248b 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -52,9 +52,17 @@
#define MPC_DMA_DESCRIPTORS 64
/* Macro definitions */
-#define MPC_DMA_CHANNELS 64
#define MPC_DMA_TCD_OFFSET 0x1000
+/*
+ * Maximum channel counts for individual hardware variants
+ * and the maximum channel count over all supported controllers,
+ * used for data structure size
+ */
+#define MPC8308_DMACHAN_MAX 16
+#define MPC512x_DMACHAN_MAX 64
+#define MPC_DMA_CHANNELS 64
+
/* Arbitration mode of group and channel */
#define MPC_DMA_DMACR_EDCG (1 << 31)
#define MPC_DMA_DMACR_ERGA (1 << 3)
@@ -710,10 +718,10 @@ static int mpc_dma_probe(struct platform_device *op)
dma = &mdma->dma;
dma->dev = dev;
- if (!mdma->is_mpc8308)
- dma->chancnt = MPC_DMA_CHANNELS;
+ if (mdma->is_mpc8308)
+ dma->chancnt = MPC8308_DMACHAN_MAX;
else
- dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */
+ dma->chancnt = MPC512x_DMACHAN_MAX;
dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
dma->device_free_chan_resources = mpc_dma_free_chan_resources;
dma->device_issue_pending = mpc_dma_issue_pending;
@@ -747,7 +755,19 @@ static int mpc_dma_probe(struct platform_device *op)
* - Round-robin group arbitration,
* - Round-robin channel arbitration.
*/
- if (!mdma->is_mpc8308) {
+ if (mdma->is_mpc8308) {
+ /* MPC8308 has 16 channels and lacks some registers */
+ out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
+
+ /* enable snooping */
+ out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
+ /* Disable error interrupts */
+ out_be32(&mdma->regs->dmaeeil, 0);
+
+ /* Clear interrupts status */
+ out_be32(&mdma->regs->dmaintl, 0xFFFF);
+ out_be32(&mdma->regs->dmaerrl, 0xFFFF);
+ } else {
out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
@@ -768,18 +788,6 @@ static int mpc_dma_probe(struct platform_device *op)
/* Route interrupts to IPIC */
out_be32(&mdma->regs->dmaihsa, 0);
out_be32(&mdma->regs->dmailsa, 0);
- } else {
- /* MPC8308 has 16 channels and lacks some registers */
- out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
-
- /* enable snooping */
- out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
- /* Disable error interrupts */
- out_be32(&mdma->regs->dmaeeil, 0);
-
- /* Clear interrupts status */
- out_be32(&mdma->regs->dmaintl, 0xFFFF);
- out_be32(&mdma->regs->dmaerrl, 0xFFFF);
}
/* Register DMA engine */
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 2/7] dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
2014-04-23 13:53 ` Alexander Popov
@ 2014-04-23 13:53 ` Alexander Popov
-1 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
MPC512x and MPC8308 have similar DMA controllers, but are independent SoCs.
DMA controller driver should have separate 'compatible' values for these SoCs.
Signed-off-by: Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
arch/powerpc/boot/dts/mpc8308_p1m.dts | 2 +-
arch/powerpc/boot/dts/mpc8308rdb.dts | 2 +-
drivers/dma/mpc512x_dma.c | 1 +
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
index 651e4f5..57f86cd 100644
--- a/arch/powerpc/boot/dts/mpc8308_p1m.dts
+++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts
@@ -296,7 +296,7 @@
};
dma@2c000 {
- compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma";
+ compatible = "fsl,mpc8308-dma";
reg = <0x2c000 0x1800>;
interrupts = <3 0x8
94 0x8>;
diff --git a/arch/powerpc/boot/dts/mpc8308rdb.dts b/arch/powerpc/boot/dts/mpc8308rdb.dts
index 9ce45f2..d0211f0 100644
--- a/arch/powerpc/boot/dts/mpc8308rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8308rdb.dts
@@ -265,7 +265,7 @@
};
dma@2c000 {
- compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma";
+ compatible = "fsl,mpc8308-dma";
reg = <0x2c000 0x1800>;
interrupts = <3 0x8
94 0x8>;
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2ce248b..0b17f4d 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -815,6 +815,7 @@ static int mpc_dma_remove(struct platform_device *op)
static struct of_device_id mpc_dma_match[] = {
{ .compatible = "fsl,mpc5121-dma", },
+ { .compatible = "fsl,mpc8308-dma", },
{},
};
--
1.8.4.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 2/7] dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
@ 2014-04-23 13:53 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Cc: devicetree
MPC512x and MPC8308 have similar DMA controllers, but are independent SoCs.
DMA controller driver should have separate 'compatible' values for these SoCs.
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
arch/powerpc/boot/dts/mpc8308_p1m.dts | 2 +-
arch/powerpc/boot/dts/mpc8308rdb.dts | 2 +-
drivers/dma/mpc512x_dma.c | 1 +
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
index 651e4f5..57f86cd 100644
--- a/arch/powerpc/boot/dts/mpc8308_p1m.dts
+++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts
@@ -296,7 +296,7 @@
};
dma@2c000 {
- compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma";
+ compatible = "fsl,mpc8308-dma";
reg = <0x2c000 0x1800>;
interrupts = <3 0x8
94 0x8>;
diff --git a/arch/powerpc/boot/dts/mpc8308rdb.dts b/arch/powerpc/boot/dts/mpc8308rdb.dts
index 9ce45f2..d0211f0 100644
--- a/arch/powerpc/boot/dts/mpc8308rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8308rdb.dts
@@ -265,7 +265,7 @@
};
dma@2c000 {
- compatible = "fsl,mpc8308-dma", "fsl,mpc5121-dma";
+ compatible = "fsl,mpc8308-dma";
reg = <0x2c000 0x1800>;
interrupts = <3 0x8
94 0x8>;
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2ce248b..0b17f4d 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -815,6 +815,7 @@ static int mpc_dma_remove(struct platform_device *op)
static struct of_device_id mpc_dma_match[] = {
{ .compatible = "fsl,mpc5121-dma", },
+ { .compatible = "fsl,mpc8308-dma", },
{},
};
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 3/7] dma: mpc512x: add support for peripheral transfers
2014-04-23 13:53 ` Alexander Popov
(?)
(?)
@ 2014-04-23 13:53 ` Alexander Popov
2014-05-02 17:03 ` Vinod Koul
-1 siblings, 1 reply; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Introduce support for slave s/g transfer preparation and the associated
device control callback in the MPC512x DMA controller driver, which adds
support for data transfers between memory and peripheral I/O to the
previously supported mem-to-mem transfers.
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
drivers/dma/mpc512x_dma.c | 239 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 234 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 0b17f4d..ca2fe03 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -2,6 +2,7 @@
* Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
* Copyright (C) Semihalf 2009
* Copyright (C) Ilya Yanok, Emcraft Systems 2010
+ * Copyright (C) Alexander Popov, Promcontroller 2014
*
* Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
* (defines, structures and comments) was taken from MPC5121 DMA driver
@@ -29,8 +30,17 @@
*/
/*
- * This is initial version of MPC5121 DMA driver. Only memory to memory
- * transfers are supported (tested using dmatest module).
+ * MPC512x and MPC8308 DMA driver. It supports
+ * memory to memory data transfers (tested using dmatest module) and
+ * data transfers between memory and peripheral I/O memory
+ * by means of slave s/g with these limitations:
+ * - chunked transfers (transfers with more than one part) are refused
+ * as long as proper support for scatter/gather is missing;
+ * - transfers on MPC8308 always start from software as this SoC appears
+ * not to have external request lines for peripheral flow control;
+ * - minimal memory <-> I/O memory transfer chunk is 4 bytes and consequently
+ * source and destination addresses must be 4-byte aligned
+ * and transfer size must be aligned on (4 * maxburst) boundary;
*/
#include <linux/module.h>
@@ -189,6 +199,7 @@ struct mpc_dma_desc {
dma_addr_t tcd_paddr;
int error;
struct list_head node;
+ int will_access_peripheral;
};
struct mpc_dma_chan {
@@ -201,6 +212,12 @@ struct mpc_dma_chan {
struct mpc_dma_tcd *tcd;
dma_addr_t tcd_paddr;
+ /* Settings for access to peripheral FIFO */
+ dma_addr_t src_per_paddr;
+ u32 src_tcd_nunits;
+ dma_addr_t dst_per_paddr;
+ u32 dst_tcd_nunits;
+
/* Lock for this structure */
spinlock_t lock;
};
@@ -251,8 +268,23 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
struct mpc_dma_desc *mdesc;
int cid = mchan->chan.chan_id;
- /* Move all queued descriptors to active list */
- list_splice_tail_init(&mchan->queued, &mchan->active);
+ while (!list_empty(&mchan->queued)) {
+ mdesc = list_first_entry(&mchan->queued,
+ struct mpc_dma_desc, node);
+ /*
+ * Grab either several mem-to-mem transfer descriptors
+ * or one peripheral transfer descriptor,
+ * don't mix mem-to-mem and peripheral transfer descriptors
+ * within the same 'active' list.
+ */
+ if (mdesc->will_access_peripheral) {
+ if (list_empty(&mchan->active))
+ list_move_tail(&mdesc->node, &mchan->active);
+ break;
+ } else {
+ list_move_tail(&mdesc->node, &mchan->active);
+ }
+ }
/* Chain descriptors into one transaction */
list_for_each_entry(mdesc, &mchan->active, node) {
@@ -278,7 +310,17 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
if (first != prev)
mdma->tcd[cid].e_sg = 1;
- out_8(&mdma->regs->dmassrt, cid);
+
+ if (mdma->is_mpc8308) {
+ /* MPC8308, no request lines, software initiated start */
+ out_8(&mdma->regs->dmassrt, cid);
+ } else if (first->will_access_peripheral) {
+ /* Peripherals involved, start by external request signal */
+ out_8(&mdma->regs->dmaserq, cid);
+ } else {
+ /* Memory to memory transfer, software initiated start */
+ out_8(&mdma->regs->dmassrt, cid);
+ }
}
/* Handle interrupt on one half of DMA controller (32 channels) */
@@ -596,6 +638,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
}
mdesc->error = 0;
+ mdesc->will_access_peripheral = 0;
tcd = mdesc->tcd;
/* Prepare Transfer Control Descriptor for this transaction */
@@ -643,6 +686,189 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
return &mdesc->desc;
}
+static struct dma_async_tx_descriptor *
+mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
+ struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+ struct mpc_dma_desc *mdesc = NULL;
+ dma_addr_t per_paddr;
+ u32 tcd_nunits;
+ struct mpc_dma_tcd *tcd;
+ unsigned long iflags;
+ struct scatterlist *sg;
+ size_t len;
+ int iter, i;
+
+ /* Currently there is no proper support for scatter/gather */
+ if (sg_len != 1)
+ return NULL;
+
+ if (!is_slave_direction(direction))
+ return NULL;
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ spin_lock_irqsave(&mchan->lock, iflags);
+
+ mdesc = list_first_entry(&mchan->free,
+ struct mpc_dma_desc, node);
+ if (!mdesc) {
+ spin_unlock_irqrestore(&mchan->lock, iflags);
+ /* Try to free completed descriptors */
+ mpc_dma_process_completed(mdma);
+ return NULL;
+ }
+
+ list_del(&mdesc->node);
+
+ if (direction == DMA_DEV_TO_MEM) {
+ per_paddr = mchan->src_per_paddr;
+ tcd_nunits = mchan->src_tcd_nunits;
+ } else {
+ per_paddr = mchan->dst_per_paddr;
+ tcd_nunits = mchan->dst_tcd_nunits;
+ }
+
+ spin_unlock_irqrestore(&mchan->lock, iflags);
+
+ if (per_paddr == 0 || tcd_nunits == 0)
+ goto err_prep;
+
+ mdesc->error = 0;
+ mdesc->will_access_peripheral = 1;
+
+ /* Prepare Transfer Control Descriptor for this transaction */
+ tcd = mdesc->tcd;
+
+ memset(tcd, 0, sizeof(struct mpc_dma_tcd));
+
+ if (!IS_ALIGNED(sg_dma_address(sg), 4))
+ goto err_prep;
+
+ if (direction == DMA_DEV_TO_MEM) {
+ tcd->saddr = per_paddr;
+ tcd->daddr = sg_dma_address(sg);
+ tcd->soff = 0;
+ tcd->doff = 4;
+ } else {
+ tcd->saddr = sg_dma_address(sg);
+ tcd->daddr = per_paddr;
+ tcd->soff = 4;
+ tcd->doff = 0;
+ }
+
+ tcd->ssize = MPC_DMA_TSIZE_4;
+ tcd->dsize = MPC_DMA_TSIZE_4;
+
+ len = sg_dma_len(sg);
+ tcd->nbytes = tcd_nunits * 4;
+ if (!IS_ALIGNED(len, tcd->nbytes))
+ goto err_prep;
+
+ iter = len / tcd->nbytes;
+ if (iter >= 1 << 15) {
+ /* len is too big */
+ goto err_prep;
+ }
+ /* citer_linkch contains the high bits of iter */
+ tcd->biter = iter & 0x1ff;
+ tcd->biter_linkch = iter >> 9;
+ tcd->citer = tcd->biter;
+ tcd->citer_linkch = tcd->biter_linkch;
+
+ tcd->e_sg = 0;
+ tcd->d_req = 1;
+
+ /* Place descriptor in prepared list */
+ spin_lock_irqsave(&mchan->lock, iflags);
+ list_add_tail(&mdesc->node, &mchan->prepared);
+ spin_unlock_irqrestore(&mchan->lock, iflags);
+ }
+
+ return &mdesc->desc;
+
+err_prep:
+ /* Put the descriptor back */
+ spin_lock_irqsave(&mchan->lock, iflags);
+ list_add_tail(&mdesc->node, &mchan->free);
+ spin_unlock_irqrestore(&mchan->lock, iflags);
+
+ return NULL;
+}
+
+static int mpc_dma_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct mpc_dma_chan *mchan;
+ struct mpc_dma *mdma;
+ struct dma_slave_config *cfg;
+ unsigned long flags;
+
+ mchan = dma_chan_to_mpc_dma_chan(chan);
+ switch (cmd) {
+ case DMA_TERMINATE_ALL:
+ /* Disable channel requests */
+ mdma = dma_chan_to_mpc_dma(chan);
+
+ spin_lock_irqsave(&mchan->lock, flags);
+
+ out_8(&mdma->regs->dmacerq, chan->chan_id);
+ list_splice_tail_init(&mchan->prepared, &mchan->free);
+ list_splice_tail_init(&mchan->queued, &mchan->free);
+ list_splice_tail_init(&mchan->active, &mchan->free);
+
+ spin_unlock_irqrestore(&mchan->lock, flags);
+
+ return 0;
+ case DMA_SLAVE_CONFIG:
+ /*
+ * Constraints:
+ * - only transfers between a peripheral device and
+ * memory are supported;
+ * - minimal transfer chunk is 4 bytes and consequently
+ * source and destination addresses must be 4-byte aligned
+ * and transfer size must be aligned on (4 * maxburst)
+ * boundary;
+ * - during the transfer RAM address is being incremented by
+ * the size of minimal transfer chunk;
+ * - peripheral port's address is constant during the transfer.
+ */
+
+ cfg = (void *)arg;
+
+ if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
+ cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
+ !IS_ALIGNED(cfg->src_addr, 4) ||
+ !IS_ALIGNED(cfg->dst_addr, 4)) {
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&mchan->lock, flags);
+
+ mchan->src_per_paddr = cfg->src_addr;
+ mchan->src_tcd_nunits = cfg->src_maxburst;
+ mchan->dst_per_paddr = cfg->dst_addr;
+ mchan->dst_tcd_nunits = cfg->dst_maxburst;
+
+ /* Apply defaults */
+ if (mchan->src_tcd_nunits == 0)
+ mchan->src_tcd_nunits = 1;
+ if (mchan->dst_tcd_nunits == 0)
+ mchan->dst_tcd_nunits = 1;
+
+ spin_unlock_irqrestore(&mchan->lock, flags);
+
+ return 0;
+ default:
+ /* Unknown command */
+ break;
+ }
+
+ return -ENXIO;
+}
+
static int mpc_dma_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
@@ -727,9 +953,12 @@ static int mpc_dma_probe(struct platform_device *op)
dma->device_issue_pending = mpc_dma_issue_pending;
dma->device_tx_status = mpc_dma_tx_status;
dma->device_prep_dma_memcpy = mpc_dma_prep_memcpy;
+ dma->device_prep_slave_sg = mpc_dma_prep_slave_sg;
+ dma->device_control = mpc_dma_device_control;
INIT_LIST_HEAD(&dma->channels);
dma_cap_set(DMA_MEMCPY, dma->cap_mask);
+ dma_cap_set(DMA_SLAVE, dma->cap_mask);
for (i = 0; i < dma->chancnt; i++) {
mchan = &mdma->channels[i];
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 4/7] dma: mpc512x: fix freeing resources in mpc_dma_probe() and mpc_dma_remove()
2014-04-23 13:53 ` Alexander Popov
` (2 preceding siblings ...)
(?)
@ 2014-04-23 13:53 ` Alexander Popov
2014-05-02 17:07 ` Vinod Koul
-1 siblings, 1 reply; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Fix mpc_dma_probe() error path and mpc_dma_remove(): manually free IRQs and
dispose IRQ mappings before devm_* takes care of other resources.
Moreover replace devm_request_irq() with request_irq() since there is no need
to use it because the original code always frees IRQ manually with
devm_free_irq(). Replace devm_free_irq() with free_irq() accordingly.
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
drivers/dma/mpc512x_dma.c | 55 ++++++++++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 17 deletions(-)
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index ca2fe03..d2c5f79 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -883,13 +883,15 @@ static int mpc_dma_probe(struct platform_device *op)
mdma = devm_kzalloc(dev, sizeof(struct mpc_dma), GFP_KERNEL);
if (!mdma) {
dev_err(dev, "Memory exhausted!\n");
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto err;
}
mdma->irq = irq_of_parse_and_map(dn, 0);
if (mdma->irq == NO_IRQ) {
dev_err(dev, "Error mapping IRQ!\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto err;
}
if (of_device_is_compatible(dn, "fsl,mpc8308-dma")) {
@@ -897,14 +899,15 @@ static int mpc_dma_probe(struct platform_device *op)
mdma->irq2 = irq_of_parse_and_map(dn, 1);
if (mdma->irq2 == NO_IRQ) {
dev_err(dev, "Error mapping IRQ!\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto err_dispose1;
}
}
retval = of_address_to_resource(dn, 0, &res);
if (retval) {
dev_err(dev, "Error parsing memory region!\n");
- return retval;
+ goto err_dispose2;
}
regs_start = res.start;
@@ -912,31 +915,34 @@ static int mpc_dma_probe(struct platform_device *op)
if (!devm_request_mem_region(dev, regs_start, regs_size, DRV_NAME)) {
dev_err(dev, "Error requesting memory region!\n");
- return -EBUSY;
+ retval = -EBUSY;
+ goto err_dispose2;
}
mdma->regs = devm_ioremap(dev, regs_start, regs_size);
if (!mdma->regs) {
dev_err(dev, "Error mapping memory region!\n");
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto err_dispose2;
}
mdma->tcd = (struct mpc_dma_tcd *)((u8 *)(mdma->regs)
+ MPC_DMA_TCD_OFFSET);
- retval = devm_request_irq(dev, mdma->irq, &mpc_dma_irq, 0, DRV_NAME,
- mdma);
+ retval = request_irq(mdma->irq, &mpc_dma_irq, 0, DRV_NAME, mdma);
if (retval) {
dev_err(dev, "Error requesting IRQ!\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto err_dispose2;
}
if (mdma->is_mpc8308) {
- retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0,
- DRV_NAME, mdma);
+ retval = request_irq(mdma->irq2, &mpc_dma_irq, 0,
+ DRV_NAME, mdma);
if (retval) {
dev_err(dev, "Error requesting IRQ2!\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto err_free1;
}
}
@@ -1022,12 +1028,23 @@ static int mpc_dma_probe(struct platform_device *op)
/* Register DMA engine */
dev_set_drvdata(dev, mdma);
retval = dma_async_device_register(dma);
- if (retval) {
- devm_free_irq(dev, mdma->irq, mdma);
- irq_dispose_mapping(mdma->irq);
- }
+ if (retval)
+ goto err_free2;
return retval;
+
+err_free2:
+ if (mdma->is_mpc8308)
+ free_irq(mdma->irq2, mdma);
+err_free1:
+ free_irq(mdma->irq, mdma);
+err_dispose2:
+ if (mdma->is_mpc8308)
+ irq_dispose_mapping(mdma->irq2);
+err_dispose1:
+ irq_dispose_mapping(mdma->irq);
+err:
+ return retval;
}
static int mpc_dma_remove(struct platform_device *op)
@@ -1036,7 +1053,11 @@ static int mpc_dma_remove(struct platform_device *op)
struct mpc_dma *mdma = dev_get_drvdata(dev);
dma_async_device_unregister(&mdma->dma);
- devm_free_irq(dev, mdma->irq, mdma);
+ if (mdma->is_mpc8308) {
+ free_irq(mdma->irq2, mdma);
+ irq_dispose_mapping(mdma->irq2);
+ }
+ free_irq(mdma->irq, mdma);
irq_dispose_mapping(mdma->irq);
return 0;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 5/7] dma: of: add common xlate function for matching by channel id
2014-04-23 13:53 ` Alexander Popov
@ 2014-04-23 13:53 ` Alexander Popov
-1 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
This patch adds a new common OF dma xlate callback function which will match a
channel by it's id. The binding expects one integer argument which it will use to
lookup the channel by the id.
Unlike of_dma_simple_xlate this function is able to handle a system with
multiple DMA controllers. When registering the of dma provider with
of_dma_controller_register a pointer to the dma_device struct which is
associated with the dt node needs to passed as the data parameter.
New function will use this pointer to match only channels which belong to the
specified DMA controller.
Signed-off-by: Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/dma/of-dma.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/of_dma.h | 4 ++++
2 files changed, 39 insertions(+)
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
index e8fe9dc..d5fbeaa 100644
--- a/drivers/dma/of-dma.c
+++ b/drivers/dma/of-dma.c
@@ -218,3 +218,38 @@ struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
&dma_spec->args[0]);
}
EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
+
+/**
+ * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id
+ * @dma_spec: pointer to DMA specifier as found in the device tree
+ * @of_dma: pointer to DMA controller data
+ *
+ * This function can be used as the of xlate callback for DMA driver which wants
+ * to match the channel based on the channel id. When using this xlate function
+ * the #dma-cells propety of the DMA controller dt node needs to be set to 1.
+ * The data parameter of of_dma_controller_register must be a pointer to the
+ * dma_device struct the function should match upon.
+ *
+ * Returns pointer to appropriate dma channel on success or NULL on error.
+ */
+struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct dma_device *dev = ofdma->of_dma_data;
+ struct dma_chan *chan, *candidate = NULL;
+
+ if (!dev || dma_spec->args_count != 1)
+ return NULL;
+
+ list_for_each_entry(chan, &dev->channels, device_node)
+ if (chan->chan_id == dma_spec->args[0]) {
+ candidate = chan;
+ break;
+ }
+
+ if (!candidate)
+ return NULL;
+
+ return dma_get_slave_channel(candidate);
+}
+EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id);
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
index ae36298..56bc026 100644
--- a/include/linux/of_dma.h
+++ b/include/linux/of_dma.h
@@ -41,6 +41,8 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name);
extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma);
+extern struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma);
#else
static inline int of_dma_controller_register(struct device_node *np,
struct dma_chan *(*of_dma_xlate)
@@ -66,6 +68,8 @@ static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_s
return NULL;
}
+#define of_dma_xlate_by_chan_id NULL
+
#endif
#endif /* __LINUX_OF_DMA_H */
--
1.8.4.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 5/7] dma: of: add common xlate function for matching by channel id
@ 2014-04-23 13:53 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Cc: devicetree
This patch adds a new common OF dma xlate callback function which will match a
channel by it's id. The binding expects one integer argument which it will use to
lookup the channel by the id.
Unlike of_dma_simple_xlate this function is able to handle a system with
multiple DMA controllers. When registering the of dma provider with
of_dma_controller_register a pointer to the dma_device struct which is
associated with the dt node needs to passed as the data parameter.
New function will use this pointer to match only channels which belong to the
specified DMA controller.
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
drivers/dma/of-dma.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/of_dma.h | 4 ++++
2 files changed, 39 insertions(+)
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
index e8fe9dc..d5fbeaa 100644
--- a/drivers/dma/of-dma.c
+++ b/drivers/dma/of-dma.c
@@ -218,3 +218,38 @@ struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
&dma_spec->args[0]);
}
EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
+
+/**
+ * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id
+ * @dma_spec: pointer to DMA specifier as found in the device tree
+ * @of_dma: pointer to DMA controller data
+ *
+ * This function can be used as the of xlate callback for DMA driver which wants
+ * to match the channel based on the channel id. When using this xlate function
+ * the #dma-cells propety of the DMA controller dt node needs to be set to 1.
+ * The data parameter of of_dma_controller_register must be a pointer to the
+ * dma_device struct the function should match upon.
+ *
+ * Returns pointer to appropriate dma channel on success or NULL on error.
+ */
+struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct dma_device *dev = ofdma->of_dma_data;
+ struct dma_chan *chan, *candidate = NULL;
+
+ if (!dev || dma_spec->args_count != 1)
+ return NULL;
+
+ list_for_each_entry(chan, &dev->channels, device_node)
+ if (chan->chan_id == dma_spec->args[0]) {
+ candidate = chan;
+ break;
+ }
+
+ if (!candidate)
+ return NULL;
+
+ return dma_get_slave_channel(candidate);
+}
+EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id);
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
index ae36298..56bc026 100644
--- a/include/linux/of_dma.h
+++ b/include/linux/of_dma.h
@@ -41,6 +41,8 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name);
extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma);
+extern struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma);
#else
static inline int of_dma_controller_register(struct device_node *np,
struct dma_chan *(*of_dma_xlate)
@@ -66,6 +68,8 @@ static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_s
return NULL;
}
+#define of_dma_xlate_by_chan_id NULL
+
#endif
#endif /* __LINUX_OF_DMA_H */
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 6/7] dma: mpc512x: add device tree binding document
2014-04-23 13:53 ` Alexander Popov
@ 2014-04-23 13:53 ` Alexander Popov
-1 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
Introduce a device tree binding document for the MPC512x DMA controller
Signed-off-by: Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
.../devicetree/bindings/dma/mpc512x-dma.txt | 40 ++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt
diff --git a/Documentation/devicetree/bindings/dma/mpc512x-dma.txt b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
new file mode 100644
index 0000000..b1cbc3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
@@ -0,0 +1,40 @@
+* Freescale MPC512x and MPC8308 DMA Controller
+
+The DMA controller in Freescale MPC512x and MPC8308 SoCs can move
+blocks of memory contents between memory and peripherals or
+from memory to memory.
+
+Refer to "Generic DMA Controller and DMA request bindings" in
+the dma/dma.txt file for a more detailed description of binding.
+
+Required properties:
+- compatible: Should be "fsl,mpc5121-dma" or "fsl,mpc8308-dma"
+- reg: Address and size of the DMA controller's register set
+- Interrupt for the DMA controller. Syntax of interrupt client node
+ is described in interrupt-controller/interrupts.txt
+
+Optional properties:
+- #dma-cells: The length of the DMA specifier, must be <1>.
+ Each channel of this DMA controller has a peripheral request line,
+ this assignment is fixed in hardware. The cell in dmas property
+ of a client device represents the channel number
+
+Example:
+
+ dma0: dma@14000 {
+ compatible = "fsl,mpc5121-dma";
+ reg = <0x14000 0x1800>;
+ interrupts = <65 0x8>;
+ #dma-cells = <1>;
+ };
+
+DMA clients must use the format described in dma/dma.txt
+
+Example:
+
+ sdhc@1500 {
+ compatible = "fsl,mpc5121-sdhc";
+ /* ... */
+ dmas = <&dma0 30>;
+ dma-names = "rx-tx";
+ };
--
1.8.4.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 6/7] dma: mpc512x: add device tree binding document
@ 2014-04-23 13:53 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Cc: devicetree
Introduce a device tree binding document for the MPC512x DMA controller
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
.../devicetree/bindings/dma/mpc512x-dma.txt | 40 ++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt
diff --git a/Documentation/devicetree/bindings/dma/mpc512x-dma.txt b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
new file mode 100644
index 0000000..b1cbc3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/mpc512x-dma.txt
@@ -0,0 +1,40 @@
+* Freescale MPC512x and MPC8308 DMA Controller
+
+The DMA controller in Freescale MPC512x and MPC8308 SoCs can move
+blocks of memory contents between memory and peripherals or
+from memory to memory.
+
+Refer to "Generic DMA Controller and DMA request bindings" in
+the dma/dma.txt file for a more detailed description of binding.
+
+Required properties:
+- compatible: Should be "fsl,mpc5121-dma" or "fsl,mpc8308-dma"
+- reg: Address and size of the DMA controller's register set
+- Interrupt for the DMA controller. Syntax of interrupt client node
+ is described in interrupt-controller/interrupts.txt
+
+Optional properties:
+- #dma-cells: The length of the DMA specifier, must be <1>.
+ Each channel of this DMA controller has a peripheral request line,
+ this assignment is fixed in hardware. The cell in dmas property
+ of a client device represents the channel number
+
+Example:
+
+ dma0: dma@14000 {
+ compatible = "fsl,mpc5121-dma";
+ reg = <0x14000 0x1800>;
+ interrupts = <65 0x8>;
+ #dma-cells = <1>;
+ };
+
+DMA clients must use the format described in dma/dma.txt
+
+Example:
+
+ sdhc@1500 {
+ compatible = "fsl,mpc5121-sdhc";
+ /* ... */
+ dmas = <&dma0 30>;
+ dma-names = "rx-tx";
+ };
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 7/7] dma: mpc512x: register for device tree channel lookup
2014-04-23 13:53 ` Alexander Popov
@ 2014-04-23 13:53 ` Alexander Popov
-1 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
Register the controller for device tree based lookup of DMA channels
(non-fatal for backwards compatibility with older device trees) and
provide the '#dma-cells' property in the shared mpc5121.dtsi file
Signed-off-by: Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
arch/powerpc/boot/dts/mpc5121.dtsi | 1 +
drivers/dma/mpc512x_dma.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 2c0e155..7f9d14f 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -498,6 +498,7 @@
compatible = "fsl,mpc5121-dma";
reg = <0x14000 0x1800>;
interrupts = <65 0x8>;
+ #dma-cells = <1>;
};
};
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index d2c5f79..fa0614e 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -52,6 +52,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/of_dma.h>
#include <linux/of_platform.h>
#include <linux/random.h>
@@ -1031,7 +1032,15 @@ static int mpc_dma_probe(struct platform_device *op)
if (retval)
goto err_free2;
- return retval;
+ /* Register with OF helpers for DMA lookups (nonfatal) */
+ if (dev->of_node) {
+ retval = of_dma_controller_register(dev->of_node,
+ of_dma_xlate_by_chan_id, mdma);
+ if (retval)
+ dev_warn(dev, "Could not register for OF lookup\n");
+ }
+
+ return 0;
err_free2:
if (mdma->is_mpc8308)
@@ -1052,6 +1061,8 @@ static int mpc_dma_remove(struct platform_device *op)
struct device *dev = &op->dev;
struct mpc_dma *mdma = dev_get_drvdata(dev);
+ if (dev->of_node)
+ of_dma_controller_free(dev->of_node);
dma_async_device_unregister(&mdma->dma);
if (mdma->is_mpc8308) {
free_irq(mdma->irq2, mdma);
--
1.8.4.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH RFC v12 7/7] dma: mpc512x: register for device tree channel lookup
@ 2014-04-23 13:53 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-23 13:53 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Cc: devicetree
Register the controller for device tree based lookup of DMA channels
(non-fatal for backwards compatibility with older device trees) and
provide the '#dma-cells' property in the shared mpc5121.dtsi file
Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
---
arch/powerpc/boot/dts/mpc5121.dtsi | 1 +
drivers/dma/mpc512x_dma.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi
index 2c0e155..7f9d14f 100644
--- a/arch/powerpc/boot/dts/mpc5121.dtsi
+++ b/arch/powerpc/boot/dts/mpc5121.dtsi
@@ -498,6 +498,7 @@
compatible = "fsl,mpc5121-dma";
reg = <0x14000 0x1800>;
interrupts = <65 0x8>;
+ #dma-cells = <1>;
};
};
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index d2c5f79..fa0614e 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -52,6 +52,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
+#include <linux/of_dma.h>
#include <linux/of_platform.h>
#include <linux/random.h>
@@ -1031,7 +1032,15 @@ static int mpc_dma_probe(struct platform_device *op)
if (retval)
goto err_free2;
- return retval;
+ /* Register with OF helpers for DMA lookups (nonfatal) */
+ if (dev->of_node) {
+ retval = of_dma_controller_register(dev->of_node,
+ of_dma_xlate_by_chan_id, mdma);
+ if (retval)
+ dev_warn(dev, "Could not register for OF lookup\n");
+ }
+
+ return 0;
err_free2:
if (mdma->is_mpc8308)
@@ -1052,6 +1061,8 @@ static int mpc_dma_remove(struct platform_device *op)
struct device *dev = &op->dev;
struct mpc_dma *mdma = dev_get_drvdata(dev);
+ if (dev->of_node)
+ of_dma_controller_free(dev->of_node);
dma_async_device_unregister(&mdma->dma);
if (mdma->is_mpc8308) {
free_irq(mdma->irq2, mdma);
--
1.8.4.2
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 0/7] MPC512x DMA slave s/g support, OF DMA lookup
2014-04-23 13:53 ` Alexander Popov
@ 2014-04-30 5:46 ` Alexander Popov
-1 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-30 5:46 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA
Hello
2014-04-23 17:53 GMT+04:00 Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> Changes in v12:
> A new patch (part 2/7) is added to this series.
> Part 6/7:
> - change the description of 'compatible' property according part 2/7;
> - improve the document according Gerhard's feedback;
Could I have a feedback? Is the binding document fine now?
Thanks!
> Alexander Popov (7):
> dma: mpc512x: reorder mpc8308 specific instructions
> dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
> dma: mpc512x: add support for peripheral transfers
> dma: mpc512x: fix freeing resources in mpc_dma_probe() and
> mpc_dma_remove()
> dma: of: add common xlate function for matching by channel id
> dma: mpc512x: add device tree binding document
> dma: mpc512x: register for device tree channel lookup
>
> .../devicetree/bindings/dma/mpc512x-dma.txt | 40 +++
> arch/powerpc/boot/dts/mpc5121.dtsi | 1 +
> arch/powerpc/boot/dts/mpc8308_p1m.dts | 2 +-
> arch/powerpc/boot/dts/mpc8308rdb.dts | 2 +-
> drivers/dma/mpc512x_dma.c | 346 ++++++++++++++++++---
> drivers/dma/of-dma.c | 35 +++
> include/linux/of_dma.h | 4 +
> 7 files changed, 390 insertions(+), 40 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt
>
> --
> 1.8.4.2
>
Best regards,
Alexander
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 0/7] MPC512x DMA slave s/g support, OF DMA lookup
@ 2014-04-30 5:46 ` Alexander Popov
0 siblings, 0 replies; 24+ messages in thread
From: Alexander Popov @ 2014-04-30 5:46 UTC (permalink / raw)
To: Gerhard Sittig, Dan Williams, Vinod Koul, Lars-Peter Clausen,
Arnd Bergmann, Anatolij Gustschin, Andy Shevchenko,
Alexander Popov, linuxppc-dev, dmaengine
Cc: devicetree
Hello
2014-04-23 17:53 GMT+04:00 Alexander Popov <a13xp0p0v88@gmail.com>:
> Changes in v12:
> A new patch (part 2/7) is added to this series.
> Part 6/7:
> - change the description of 'compatible' property according part 2/7;
> - improve the document according Gerhard's feedback;
Could I have a feedback? Is the binding document fine now?
Thanks!
> Alexander Popov (7):
> dma: mpc512x: reorder mpc8308 specific instructions
> dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
> dma: mpc512x: add support for peripheral transfers
> dma: mpc512x: fix freeing resources in mpc_dma_probe() and
> mpc_dma_remove()
> dma: of: add common xlate function for matching by channel id
> dma: mpc512x: add device tree binding document
> dma: mpc512x: register for device tree channel lookup
>
> .../devicetree/bindings/dma/mpc512x-dma.txt | 40 +++
> arch/powerpc/boot/dts/mpc5121.dtsi | 1 +
> arch/powerpc/boot/dts/mpc8308_p1m.dts | 2 +-
> arch/powerpc/boot/dts/mpc8308rdb.dts | 2 +-
> drivers/dma/mpc512x_dma.c | 346 ++++++++++++++++++---
> drivers/dma/of-dma.c | 35 +++
> include/linux/of_dma.h | 4 +
> 7 files changed, 390 insertions(+), 40 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/dma/mpc512x-dma.txt
>
> --
> 1.8.4.2
>
Best regards,
Alexander
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 3/7] dma: mpc512x: add support for peripheral transfers
2014-04-23 13:53 ` [PATCH RFC v12 3/7] dma: mpc512x: add support for peripheral transfers Alexander Popov
@ 2014-05-02 17:03 ` Vinod Koul
2014-05-08 9:49 ` Alexander Popov
0 siblings, 1 reply; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:03 UTC (permalink / raw)
To: Alexander Popov
Cc: Lars-Peter Clausen, Arnd Bergmann, Gerhard Sittig,
Andy Shevchenko, dmaengine, Dan Williams, Anatolij Gustschin,
linuxppc-dev
On Wed, Apr 23, 2014 at 05:53:25PM +0400, Alexander Popov wrote:
> Introduce support for slave s/g transfer preparation and the associated
> device control callback in the MPC512x DMA controller driver, which adds
> support for data transfers between memory and peripheral I/O to the
> previously supported mem-to-mem transfers.
>
> Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
> ---
> drivers/dma/mpc512x_dma.c | 239 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 234 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
> index 0b17f4d..ca2fe03 100644
> --- a/drivers/dma/mpc512x_dma.c
> +++ b/drivers/dma/mpc512x_dma.c
> @@ -2,6 +2,7 @@
> * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
> * Copyright (C) Semihalf 2009
> * Copyright (C) Ilya Yanok, Emcraft Systems 2010
> + * Copyright (C) Alexander Popov, Promcontroller 2014
> *
> * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
> * (defines, structures and comments) was taken from MPC5121 DMA driver
> @@ -29,8 +30,17 @@
> */
>
> /*
> - * This is initial version of MPC5121 DMA driver. Only memory to memory
> - * transfers are supported (tested using dmatest module).
> + * MPC512x and MPC8308 DMA driver. It supports
> + * memory to memory data transfers (tested using dmatest module) and
> + * data transfers between memory and peripheral I/O memory
> + * by means of slave s/g with these limitations:
> + * - chunked transfers (transfers with more than one part) are refused
> + * as long as proper support for scatter/gather is missing;
> + * - transfers on MPC8308 always start from software as this SoC appears
> + * not to have external request lines for peripheral flow control;
> + * - minimal memory <-> I/O memory transfer chunk is 4 bytes and consequently
> + * source and destination addresses must be 4-byte aligned
> + * and transfer size must be aligned on (4 * maxburst) boundary;
> */
>
> #include <linux/module.h>
> @@ -189,6 +199,7 @@ struct mpc_dma_desc {
> dma_addr_t tcd_paddr;
> int error;
> struct list_head node;
> + int will_access_peripheral;
> };
>
> struct mpc_dma_chan {
> @@ -201,6 +212,12 @@ struct mpc_dma_chan {
> struct mpc_dma_tcd *tcd;
> dma_addr_t tcd_paddr;
>
> + /* Settings for access to peripheral FIFO */
> + dma_addr_t src_per_paddr;
> + u32 src_tcd_nunits;
> + dma_addr_t dst_per_paddr;
> + u32 dst_tcd_nunits;
> +
> /* Lock for this structure */
> spinlock_t lock;
> };
> @@ -251,8 +268,23 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
> struct mpc_dma_desc *mdesc;
> int cid = mchan->chan.chan_id;
>
> - /* Move all queued descriptors to active list */
> - list_splice_tail_init(&mchan->queued, &mchan->active);
> + while (!list_empty(&mchan->queued)) {
> + mdesc = list_first_entry(&mchan->queued,
> + struct mpc_dma_desc, node);
> + /*
> + * Grab either several mem-to-mem transfer descriptors
> + * or one peripheral transfer descriptor,
> + * don't mix mem-to-mem and peripheral transfer descriptors
> + * within the same 'active' list.
> + */
> + if (mdesc->will_access_peripheral) {
> + if (list_empty(&mchan->active))
> + list_move_tail(&mdesc->node, &mchan->active);
> + break;
> + } else {
> + list_move_tail(&mdesc->node, &mchan->active);
> + }
> + }
>
> /* Chain descriptors into one transaction */
> list_for_each_entry(mdesc, &mchan->active, node) {
> @@ -278,7 +310,17 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
>
> if (first != prev)
> mdma->tcd[cid].e_sg = 1;
> - out_8(&mdma->regs->dmassrt, cid);
> +
> + if (mdma->is_mpc8308) {
> + /* MPC8308, no request lines, software initiated start */
> + out_8(&mdma->regs->dmassrt, cid);
> + } else if (first->will_access_peripheral) {
> + /* Peripherals involved, start by external request signal */
> + out_8(&mdma->regs->dmaserq, cid);
> + } else {
> + /* Memory to memory transfer, software initiated start */
> + out_8(&mdma->regs->dmassrt, cid);
> + }
> }
>
> /* Handle interrupt on one half of DMA controller (32 channels) */
> @@ -596,6 +638,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
> }
>
> mdesc->error = 0;
> + mdesc->will_access_peripheral = 0;
> tcd = mdesc->tcd;
>
> /* Prepare Transfer Control Descriptor for this transaction */
> @@ -643,6 +686,189 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
> return &mdesc->desc;
> }
>
> +static struct dma_async_tx_descriptor *
> +mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
> + unsigned int sg_len, enum dma_transfer_direction direction,
> + unsigned long flags, void *context)
> +{
> + struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
> + struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
> + struct mpc_dma_desc *mdesc = NULL;
> + dma_addr_t per_paddr;
> + u32 tcd_nunits;
> + struct mpc_dma_tcd *tcd;
> + unsigned long iflags;
> + struct scatterlist *sg;
> + size_t len;
> + int iter, i;
> +
> + /* Currently there is no proper support for scatter/gather */
Why? Is this HW or SW limitation?
> + if (sg_len != 1)
> + return NULL;
> +
> + if (!is_slave_direction(direction))
> + return NULL;
> +
> + for_each_sg(sgl, sg, sg_len, i) {
Then this doesn't make sense...
> + spin_lock_irqsave(&mchan->lock, iflags);
> +
> + mdesc = list_first_entry(&mchan->free,
> + struct mpc_dma_desc, node);
> + if (!mdesc) {
> + spin_unlock_irqrestore(&mchan->lock, iflags);
> + /* Try to free completed descriptors */
> + mpc_dma_process_completed(mdma);
> + return NULL;
> + }
> +
> + list_del(&mdesc->node);
> +
> + if (direction == DMA_DEV_TO_MEM) {
> + per_paddr = mchan->src_per_paddr;
> + tcd_nunits = mchan->src_tcd_nunits;
> + } else {
> + per_paddr = mchan->dst_per_paddr;
> + tcd_nunits = mchan->dst_tcd_nunits;
> + }
> +
> + spin_unlock_irqrestore(&mchan->lock, iflags);
> +
> + if (per_paddr == 0 || tcd_nunits == 0)
> + goto err_prep;
> +
> + mdesc->error = 0;
> + mdesc->will_access_peripheral = 1;
> +
> + /* Prepare Transfer Control Descriptor for this transaction */
> + tcd = mdesc->tcd;
> +
> + memset(tcd, 0, sizeof(struct mpc_dma_tcd));
> +
> + if (!IS_ALIGNED(sg_dma_address(sg), 4))
> + goto err_prep;
> +
> + if (direction == DMA_DEV_TO_MEM) {
> + tcd->saddr = per_paddr;
> + tcd->daddr = sg_dma_address(sg);
> + tcd->soff = 0;
> + tcd->doff = 4;
what are these?
> + } else {
> + tcd->saddr = sg_dma_address(sg);
> + tcd->daddr = per_paddr;
> + tcd->soff = 4;
> + tcd->doff = 0;
> + }
> +
> + tcd->ssize = MPC_DMA_TSIZE_4;
> + tcd->dsize = MPC_DMA_TSIZE_4;
> +
> + len = sg_dma_len(sg);
> + tcd->nbytes = tcd_nunits * 4;
> + if (!IS_ALIGNED(len, tcd->nbytes))
> + goto err_prep;
> +
> + iter = len / tcd->nbytes;
> + if (iter >= 1 << 15) {
> + /* len is too big */
> + goto err_prep;
> + }
> + /* citer_linkch contains the high bits of iter */
> + tcd->biter = iter & 0x1ff;
> + tcd->biter_linkch = iter >> 9;
> + tcd->citer = tcd->biter;
> + tcd->citer_linkch = tcd->biter_linkch;
> +
> + tcd->e_sg = 0;
> + tcd->d_req = 1;
> +
> + /* Place descriptor in prepared list */
> + spin_lock_irqsave(&mchan->lock, iflags);
> + list_add_tail(&mdesc->node, &mchan->prepared);
> + spin_unlock_irqrestore(&mchan->lock, iflags);
> + }
> +
> + return &mdesc->desc;
> +
> +err_prep:
> + /* Put the descriptor back */
> + spin_lock_irqsave(&mchan->lock, iflags);
> + list_add_tail(&mdesc->node, &mchan->free);
> + spin_unlock_irqrestore(&mchan->lock, iflags);
> +
> + return NULL;
> +}
> +
> +static int mpc_dma_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
> + unsigned long arg)
> +{
> + struct mpc_dma_chan *mchan;
> + struct mpc_dma *mdma;
> + struct dma_slave_config *cfg;
> + unsigned long flags;
> +
> + mchan = dma_chan_to_mpc_dma_chan(chan);
> + switch (cmd) {
> + case DMA_TERMINATE_ALL:
> + /* Disable channel requests */
> + mdma = dma_chan_to_mpc_dma(chan);
> +
> + spin_lock_irqsave(&mchan->lock, flags);
> +
> + out_8(&mdma->regs->dmacerq, chan->chan_id);
> + list_splice_tail_init(&mchan->prepared, &mchan->free);
> + list_splice_tail_init(&mchan->queued, &mchan->free);
> + list_splice_tail_init(&mchan->active, &mchan->free);
> +
> + spin_unlock_irqrestore(&mchan->lock, flags);
> +
> + return 0;
empty line after this pls
> + case DMA_SLAVE_CONFIG:
> + /*
> + * Constraints:
> + * - only transfers between a peripheral device and
> + * memory are supported;
> + * - minimal transfer chunk is 4 bytes and consequently
> + * source and destination addresses must be 4-byte aligned
> + * and transfer size must be aligned on (4 * maxburst)
> + * boundary;
> + * - during the transfer RAM address is being incremented by
> + * the size of minimal transfer chunk;
> + * - peripheral port's address is constant during the transfer.
> + */
> +
> + cfg = (void *)arg;
> +
> + if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
> + cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
and why this limtation, doesnt seem covered above?
> + !IS_ALIGNED(cfg->src_addr, 4) ||
> + !IS_ALIGNED(cfg->dst_addr, 4)) {
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mchan->lock, flags);
> +
> + mchan->src_per_paddr = cfg->src_addr;
> + mchan->src_tcd_nunits = cfg->src_maxburst;
> + mchan->dst_per_paddr = cfg->dst_addr;
> + mchan->dst_tcd_nunits = cfg->dst_maxburst;
> +
> + /* Apply defaults */
> + if (mchan->src_tcd_nunits == 0)
> + mchan->src_tcd_nunits = 1;
> + if (mchan->dst_tcd_nunits == 0)
> + mchan->dst_tcd_nunits = 1;
> +
> + spin_unlock_irqrestore(&mchan->lock, flags);
> +
> + return 0;
empty line here too
> + default:
> + /* Unknown command */
> + break;
> + }
> +
> + return -ENXIO;
> +}
> +
> static int mpc_dma_probe(struct platform_device *op)
> {
> struct device_node *dn = op->dev.of_node;
> @@ -727,9 +953,12 @@ static int mpc_dma_probe(struct platform_device *op)
> dma->device_issue_pending = mpc_dma_issue_pending;
> dma->device_tx_status = mpc_dma_tx_status;
> dma->device_prep_dma_memcpy = mpc_dma_prep_memcpy;
> + dma->device_prep_slave_sg = mpc_dma_prep_slave_sg;
> + dma->device_control = mpc_dma_device_control;
>
> INIT_LIST_HEAD(&dma->channels);
> dma_cap_set(DMA_MEMCPY, dma->cap_mask);
> + dma_cap_set(DMA_SLAVE, dma->cap_mask);
>
> for (i = 0; i < dma->chancnt; i++) {
> mchan = &mdma->channels[i];
> --
> 1.8.4.2
>
--
~Vinod
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 5/7] dma: of: add common xlate function for matching by channel id
2014-04-23 13:53 ` Alexander Popov
@ 2014-05-02 17:04 ` Vinod Koul
-1 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:04 UTC (permalink / raw)
To: Alexander Popov, Arnd Bergmann
Cc: Gerhard Sittig, Dan Williams, Lars-Peter Clausen,
Anatolij Gustschin, Andy Shevchenko,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
On Wed, Apr 23, 2014 at 05:53:27PM +0400, Alexander Popov wrote:
> This patch adds a new common OF dma xlate callback function which will match a
> channel by it's id. The binding expects one integer argument which it will use to
> lookup the channel by the id.
>
> Unlike of_dma_simple_xlate this function is able to handle a system with
> multiple DMA controllers. When registering the of dma provider with
> of_dma_controller_register a pointer to the dma_device struct which is
> associated with the dt node needs to passed as the data parameter.
> New function will use this pointer to match only channels which belong to the
> specified DMA controller.
This patch needs review by DT folks too
>
> Signed-off-by: Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> drivers/dma/of-dma.c | 35 +++++++++++++++++++++++++++++++++++
> include/linux/of_dma.h | 4 ++++
> 2 files changed, 39 insertions(+)
>
> diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
> index e8fe9dc..d5fbeaa 100644
> --- a/drivers/dma/of-dma.c
> +++ b/drivers/dma/of-dma.c
> @@ -218,3 +218,38 @@ struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
> &dma_spec->args[0]);
> }
> EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
> +
> +/**
> + * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id
> + * @dma_spec: pointer to DMA specifier as found in the device tree
> + * @of_dma: pointer to DMA controller data
> + *
> + * This function can be used as the of xlate callback for DMA driver which wants
> + * to match the channel based on the channel id. When using this xlate function
> + * the #dma-cells propety of the DMA controller dt node needs to be set to 1.
> + * The data parameter of of_dma_controller_register must be a pointer to the
> + * dma_device struct the function should match upon.
> + *
> + * Returns pointer to appropriate dma channel on success or NULL on error.
> + */
> +struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
> + struct of_dma *ofdma)
> +{
> + struct dma_device *dev = ofdma->of_dma_data;
> + struct dma_chan *chan, *candidate = NULL;
> +
> + if (!dev || dma_spec->args_count != 1)
> + return NULL;
> +
> + list_for_each_entry(chan, &dev->channels, device_node)
> + if (chan->chan_id == dma_spec->args[0]) {
> + candidate = chan;
> + break;
> + }
> +
> + if (!candidate)
> + return NULL;
> +
> + return dma_get_slave_channel(candidate);
> +}
> +EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id);
> diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
> index ae36298..56bc026 100644
> --- a/include/linux/of_dma.h
> +++ b/include/linux/of_dma.h
> @@ -41,6 +41,8 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
> const char *name);
> extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
> struct of_dma *ofdma);
> +extern struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
> + struct of_dma *ofdma);
> #else
> static inline int of_dma_controller_register(struct device_node *np,
> struct dma_chan *(*of_dma_xlate)
> @@ -66,6 +68,8 @@ static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_s
> return NULL;
> }
>
> +#define of_dma_xlate_by_chan_id NULL
> +
> #endif
>
> #endif /* __LINUX_OF_DMA_H */
> --
> 1.8.4.2
>
--
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 5/7] dma: of: add common xlate function for matching by channel id
@ 2014-05-02 17:04 ` Vinod Koul
0 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:04 UTC (permalink / raw)
To: Alexander Popov, Arnd Bergmann
Cc: devicetree, Lars-Peter Clausen, Gerhard Sittig, Andy Shevchenko,
dmaengine, Dan Williams, Anatolij Gustschin, linuxppc-dev
On Wed, Apr 23, 2014 at 05:53:27PM +0400, Alexander Popov wrote:
> This patch adds a new common OF dma xlate callback function which will match a
> channel by it's id. The binding expects one integer argument which it will use to
> lookup the channel by the id.
>
> Unlike of_dma_simple_xlate this function is able to handle a system with
> multiple DMA controllers. When registering the of dma provider with
> of_dma_controller_register a pointer to the dma_device struct which is
> associated with the dt node needs to passed as the data parameter.
> New function will use this pointer to match only channels which belong to the
> specified DMA controller.
This patch needs review by DT folks too
>
> Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
> ---
> drivers/dma/of-dma.c | 35 +++++++++++++++++++++++++++++++++++
> include/linux/of_dma.h | 4 ++++
> 2 files changed, 39 insertions(+)
>
> diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c
> index e8fe9dc..d5fbeaa 100644
> --- a/drivers/dma/of-dma.c
> +++ b/drivers/dma/of-dma.c
> @@ -218,3 +218,38 @@ struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
> &dma_spec->args[0]);
> }
> EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
> +
> +/**
> + * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id
> + * @dma_spec: pointer to DMA specifier as found in the device tree
> + * @of_dma: pointer to DMA controller data
> + *
> + * This function can be used as the of xlate callback for DMA driver which wants
> + * to match the channel based on the channel id. When using this xlate function
> + * the #dma-cells propety of the DMA controller dt node needs to be set to 1.
> + * The data parameter of of_dma_controller_register must be a pointer to the
> + * dma_device struct the function should match upon.
> + *
> + * Returns pointer to appropriate dma channel on success or NULL on error.
> + */
> +struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
> + struct of_dma *ofdma)
> +{
> + struct dma_device *dev = ofdma->of_dma_data;
> + struct dma_chan *chan, *candidate = NULL;
> +
> + if (!dev || dma_spec->args_count != 1)
> + return NULL;
> +
> + list_for_each_entry(chan, &dev->channels, device_node)
> + if (chan->chan_id == dma_spec->args[0]) {
> + candidate = chan;
> + break;
> + }
> +
> + if (!candidate)
> + return NULL;
> +
> + return dma_get_slave_channel(candidate);
> +}
> +EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id);
> diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
> index ae36298..56bc026 100644
> --- a/include/linux/of_dma.h
> +++ b/include/linux/of_dma.h
> @@ -41,6 +41,8 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
> const char *name);
> extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
> struct of_dma *ofdma);
> +extern struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
> + struct of_dma *ofdma);
> #else
> static inline int of_dma_controller_register(struct device_node *np,
> struct dma_chan *(*of_dma_xlate)
> @@ -66,6 +68,8 @@ static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_s
> return NULL;
> }
>
> +#define of_dma_xlate_by_chan_id NULL
> +
> #endif
>
> #endif /* __LINUX_OF_DMA_H */
> --
> 1.8.4.2
>
--
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 1/7] dma: mpc512x: reorder mpc8308 specific instructions
2014-04-23 13:53 ` [PATCH RFC v12 1/7] dma: mpc512x: reorder mpc8308 specific instructions Alexander Popov
@ 2014-05-02 17:06 ` Vinod Koul
0 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:06 UTC (permalink / raw)
To: Alexander Popov
Cc: Lars-Peter Clausen, Arnd Bergmann, Gerhard Sittig,
Andy Shevchenko, dmaengine, Dan Williams, Anatolij Gustschin,
linuxppc-dev
On Wed, Apr 23, 2014 at 05:53:23PM +0400, Alexander Popov wrote:
> Concentrate the specific code for MPC8308 in the 'if' branch
> and handle MPC512x in the 'else' branch.
> This modification only reorders instructions but doesn't change behaviour.
>
> Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
> Acked-by: Anatolij Gustschin <agust@denx.de>
Applied, thanks
--
~Vinod
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 2/7] dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
2014-04-23 13:53 ` Alexander Popov
@ 2014-05-02 17:07 ` Vinod Koul
-1 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:07 UTC (permalink / raw)
To: Alexander Popov
Cc: Gerhard Sittig, Dan Williams, Lars-Peter Clausen, Arnd Bergmann,
Anatolij Gustschin, Andy Shevchenko,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
On Wed, Apr 23, 2014 at 05:53:24PM +0400, Alexander Popov wrote:
> MPC512x and MPC8308 have similar DMA controllers, but are independent SoCs.
> DMA controller driver should have separate 'compatible' values for these SoCs.
>
> Signed-off-by: Alexander Popov <a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Applied, thanks
--
~Vinod
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 2/7] dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308
@ 2014-05-02 17:07 ` Vinod Koul
0 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:07 UTC (permalink / raw)
To: Alexander Popov
Cc: devicetree, Lars-Peter Clausen, Arnd Bergmann, Gerhard Sittig,
Andy Shevchenko, dmaengine, Dan Williams, Anatolij Gustschin,
linuxppc-dev
On Wed, Apr 23, 2014 at 05:53:24PM +0400, Alexander Popov wrote:
> MPC512x and MPC8308 have similar DMA controllers, but are independent SoCs.
> DMA controller driver should have separate 'compatible' values for these SoCs.
>
> Signed-off-by: Alexander Popov <a13xp0p0v88@gmail.com>
Applied, thanks
--
~Vinod
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 4/7] dma: mpc512x: fix freeing resources in mpc_dma_probe() and mpc_dma_remove()
2014-04-23 13:53 ` [PATCH RFC v12 4/7] dma: mpc512x: fix freeing resources in mpc_dma_probe() and mpc_dma_remove() Alexander Popov
@ 2014-05-02 17:07 ` Vinod Koul
0 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-02 17:07 UTC (permalink / raw)
To: Alexander Popov
Cc: Lars-Peter Clausen, Arnd Bergmann, Gerhard Sittig,
Andy Shevchenko, dmaengine, Dan Williams, Anatolij Gustschin,
linuxppc-dev
On Wed, Apr 23, 2014 at 05:53:26PM +0400, Alexander Popov wrote:
> Fix mpc_dma_probe() error path and mpc_dma_remove(): manually free IRQs and
> dispose IRQ mappings before devm_* takes care of other resources.
> Moreover replace devm_request_irq() with request_irq() since there is no need
> to use it because the original code always frees IRQ manually with
> devm_free_irq(). Replace devm_free_irq() with free_irq() accordingly.
Applied, thanks
--
~Vinod
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 3/7] dma: mpc512x: add support for peripheral transfers
2014-05-02 17:03 ` Vinod Koul
@ 2014-05-08 9:49 ` Alexander Popov
2014-05-21 3:14 ` Vinod Koul
0 siblings, 1 reply; 24+ messages in thread
From: Alexander Popov @ 2014-05-08 9:49 UTC (permalink / raw)
To: Vinod Koul
Cc: Lars-Peter Clausen, Arnd Bergmann, Gerhard Sittig,
Andy Shevchenko, Alexander Popov, dmaengine, Dan Williams,
Anatolij Gustschin, linuxppc-dev
Hello, Vinod.
Thanks for your feedback.
2014-05-02 21:03 GMT+04:00 Vinod Koul <vinod.koul@intel.com>:
> On Wed, Apr 23, 2014 at 05:53:25PM +0400, Alexander Popov wrote:
>> +static struct dma_async_tx_descriptor *
>> +mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
>> + unsigned int sg_len, enum dma_transfer_direction direction,
>> + unsigned long flags, void *context)
>> +{
>> + struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
>> + struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
>> + struct mpc_dma_desc *mdesc = NULL;
>> + dma_addr_t per_paddr;
>> + u32 tcd_nunits;
>> + struct mpc_dma_tcd *tcd;
>> + unsigned long iflags;
>> + struct scatterlist *sg;
>> + size_t len;
>> + int iter, i;
>> +
>> + /* Currently there is no proper support for scatter/gather */
> Why? Is this HW or SW limitation?
This is the software limitation.
As Gerhard noticed, unfortunately the Linux DMA API combines
peripheral access with scatter/gather function.
But the original MPC512x DMA driver already uses scatter/gather feature
of the hardware for chaining together individual mpc_dma_desc's
in mpc_dma_execute() while mpc_dma_desc itself cannot use
scatter/gather feature, because each mpc_dma_desc is associated
with exactly one mpc_dma_tcd.
>> + if (direction == DMA_DEV_TO_MEM) {
>> + tcd->saddr = per_paddr;
>> + tcd->daddr = sg_dma_address(sg);
>> + tcd->soff = 0;
>> + tcd->doff = 4;
> what are these?
SOFF is source address signed offset. It is applied to the current
source address to form the next-state value as each source read is completed.
DOFF is destination address signed offset.
>> + case DMA_TERMINATE_ALL:
>> + /* Disable channel requests */
>> + mdma = dma_chan_to_mpc_dma(chan);
>> +
>> + spin_lock_irqsave(&mchan->lock, flags);
>> +
>> + out_8(&mdma->regs->dmacerq, chan->chan_id);
>> + list_splice_tail_init(&mchan->prepared, &mchan->free);
>> + list_splice_tail_init(&mchan->queued, &mchan->free);
>> + list_splice_tail_init(&mchan->active, &mchan->free);
>> +
>> + spin_unlock_irqrestore(&mchan->lock, flags);
>> +
>> + return 0;
> empty line after this pls
ok
>> + case DMA_SLAVE_CONFIG:
>> + /*
>> + * Constraints:
>> + * - only transfers between a peripheral device and
>> + * memory are supported;
>> + * - minimal transfer chunk is 4 bytes and consequently
>> + * source and destination addresses must be 4-byte aligned
>> + * and transfer size must be aligned on (4 * maxburst)
>> + * boundary;
>> + * - during the transfer RAM address is being incremented by
>> + * the size of minimal transfer chunk;
>> + * - peripheral port's address is constant during the transfer.
>> + */
>> +
>> + cfg = (void *)arg;
>> +
>> + if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
>> + cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
> and why this limtation, doesnt seem covered above?
I created this limitation because FIFO registers of LPC and SDHC
support _only_ 4-byte access.
I tried to cover this limitation in the statement "minimal transfer chunk
is 4 bytes". Should I make it more explicit?
>> + !IS_ALIGNED(cfg->src_addr, 4) ||
>> + !IS_ALIGNED(cfg->dst_addr, 4)) {
>> + return -EINVAL;
>> + }
>> +
>> + spin_lock_irqsave(&mchan->lock, flags);
>> +
>> + mchan->src_per_paddr = cfg->src_addr;
>> + mchan->src_tcd_nunits = cfg->src_maxburst;
>> + mchan->dst_per_paddr = cfg->dst_addr;
>> + mchan->dst_tcd_nunits = cfg->dst_maxburst;
>> +
>> + /* Apply defaults */
>> + if (mchan->src_tcd_nunits == 0)
>> + mchan->src_tcd_nunits = 1;
>> + if (mchan->dst_tcd_nunits == 0)
>> + mchan->dst_tcd_nunits = 1;
>> +
>> + spin_unlock_irqrestore(&mchan->lock, flags);
>> +
>> + return 0;
> empty line here too
ok
Best regards,
Alexander
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH RFC v12 3/7] dma: mpc512x: add support for peripheral transfers
2014-05-08 9:49 ` Alexander Popov
@ 2014-05-21 3:14 ` Vinod Koul
0 siblings, 0 replies; 24+ messages in thread
From: Vinod Koul @ 2014-05-21 3:14 UTC (permalink / raw)
To: Alexander Popov
Cc: Lars-Peter Clausen, Arnd Bergmann, Gerhard Sittig,
Andy Shevchenko, dmaengine, Dan Williams, Anatolij Gustschin,
linuxppc-dev
On Thu, May 08, 2014 at 01:49:20PM +0400, Alexander Popov wrote:
> >> + case DMA_SLAVE_CONFIG:
> >> + /*
> >> + * Constraints:
> >> + * - only transfers between a peripheral device and
> >> + * memory are supported;
> >> + * - minimal transfer chunk is 4 bytes and consequently
> >> + * source and destination addresses must be 4-byte aligned
> >> + * and transfer size must be aligned on (4 * maxburst)
> >> + * boundary;
> >> + * - during the transfer RAM address is being incremented by
> >> + * the size of minimal transfer chunk;
> >> + * - peripheral port's address is constant during the transfer.
> >> + */
> >> +
> >> + cfg = (void *)arg;
> >> +
> >> + if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
> >> + cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
> > and why this limtation, doesnt seem covered above?
> I created this limitation because FIFO registers of LPC and SDHC
> support _only_ 4-byte access.
>
> I tried to cover this limitation in the statement "minimal transfer chunk
> is 4 bytes". Should I make it more explicit?
expose these as capablities and try to use these in your client driver. Already
we have audio drivers using those...
--
~Vinod
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2014-05-21 3:29 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-23 13:53 [PATCH RFC v12 0/7] MPC512x DMA slave s/g support, OF DMA lookup Alexander Popov
2014-04-23 13:53 ` Alexander Popov
2014-04-23 13:53 ` [PATCH RFC v12 1/7] dma: mpc512x: reorder mpc8308 specific instructions Alexander Popov
2014-05-02 17:06 ` Vinod Koul
2014-04-23 13:53 ` [PATCH RFC v12 3/7] dma: mpc512x: add support for peripheral transfers Alexander Popov
2014-05-02 17:03 ` Vinod Koul
2014-05-08 9:49 ` Alexander Popov
2014-05-21 3:14 ` Vinod Koul
2014-04-23 13:53 ` [PATCH RFC v12 4/7] dma: mpc512x: fix freeing resources in mpc_dma_probe() and mpc_dma_remove() Alexander Popov
2014-05-02 17:07 ` Vinod Koul
[not found] ` <1398261209-5578-1-git-send-email-a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-04-23 13:53 ` [PATCH RFC v12 2/7] dma: mpc512x: separate 'compatible' values for MPC512x and MPC8308 Alexander Popov
2014-04-23 13:53 ` Alexander Popov
[not found] ` <1398261209-5578-3-git-send-email-a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-05-02 17:07 ` Vinod Koul
2014-05-02 17:07 ` Vinod Koul
2014-04-23 13:53 ` [PATCH RFC v12 5/7] dma: of: add common xlate function for matching by channel id Alexander Popov
2014-04-23 13:53 ` Alexander Popov
[not found] ` <1398261209-5578-6-git-send-email-a13xp0p0v88-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-05-02 17:04 ` Vinod Koul
2014-05-02 17:04 ` Vinod Koul
2014-04-23 13:53 ` [PATCH RFC v12 6/7] dma: mpc512x: add device tree binding document Alexander Popov
2014-04-23 13:53 ` Alexander Popov
2014-04-23 13:53 ` [PATCH RFC v12 7/7] dma: mpc512x: register for device tree channel lookup Alexander Popov
2014-04-23 13:53 ` Alexander Popov
2014-04-30 5:46 ` [PATCH RFC v12 0/7] MPC512x DMA slave s/g support, OF DMA lookup Alexander Popov
2014-04-30 5:46 ` Alexander Popov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.