* [PATCH v2 1/3] dmaengine: sun6i: support parameterized compatible strings
[not found] ` <1411010680-4481-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
@ 2014-09-18 3:24 ` Chen-Yu Tsai
2014-09-18 3:24 ` [PATCH v2 2/3] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant Chen-Yu Tsai
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Chen-Yu Tsai @ 2014-09-18 3:24 UTC (permalink / raw)
To: Maxime Ripard, Vinod Koul, Dan Williams, Grant Likely,
Rob Herring
Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
This patch adds support for hardware parameters tied to compatible
strings, so similar hardware can reuse the driver.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/dma/sun6i-dma.c | 96 +++++++++++++++++++++++++++++++------------------
1 file changed, 61 insertions(+), 35 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 3aa10b3..89ca0c4 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_dma.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/slab.h>
@@ -26,24 +27,6 @@
#include "virt-dma.h"
/*
- * There's 16 physical channels that can work in parallel.
- *
- * However we have 30 different endpoints for our requests.
- *
- * Since the channels are able to handle only an unidirectional
- * transfer, we need to allocate more virtual channels so that
- * everyone can grab one channel.
- *
- * Some devices can't work in both direction (mostly because it
- * wouldn't make sense), so we have a bit fewer virtual channels than
- * 2 channels per endpoints.
- */
-
-#define NR_MAX_CHANNELS 16
-#define NR_MAX_REQUESTS 30
-#define NR_MAX_VCHANS 53
-
-/*
* Common registers
*/
#define DMA_IRQ_EN(x) ((x) * 0x04)
@@ -102,6 +85,19 @@
#define DRQ_SDRAM 1
/*
+ * Hardware channels / ports representation
+ *
+ * The hardware is used in several SoCs, with differing numbers
+ * of channels and endpoints. This structure ties those numbers
+ * to a certain compatible string.
+ */
+struct sun6i_dma_config {
+ u32 nr_max_channels;
+ u32 nr_max_requests;
+ u32 nr_max_vchans;
+};
+
+/*
* Hardware representation of the LLI
*
* The hardware will be fed the physical address of this structure,
@@ -159,6 +155,7 @@ struct sun6i_dma_dev {
struct dma_pool *pool;
struct sun6i_pchan *pchans;
struct sun6i_vchan *vchans;
+ const struct sun6i_dma_config *cfg;
};
static struct device *chan2dev(struct dma_chan *chan)
@@ -432,6 +429,7 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
static void sun6i_dma_tasklet(unsigned long data)
{
struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
+ const struct sun6i_dma_config *cfg = sdev->cfg;
struct sun6i_vchan *vchan;
struct sun6i_pchan *pchan;
unsigned int pchan_alloc = 0;
@@ -459,7 +457,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
spin_lock_irq(&sdev->lock);
- for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
+ for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
pchan = &sdev->pchans[pchan_idx];
if (pchan->vchan || list_empty(&sdev->pending))
@@ -480,7 +478,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
spin_unlock_irq(&sdev->lock);
- for (pchan_idx = 0; pchan_idx < NR_MAX_CHANNELS; pchan_idx++) {
+ for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
if (!(pchan_alloc & BIT(pchan_idx)))
continue;
@@ -502,7 +500,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
int i, j, ret = IRQ_NONE;
u32 status;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) {
status = readl(sdev->base + DMA_IRQ_STAT(i));
if (!status)
continue;
@@ -512,7 +510,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
writel(status, sdev->base + DMA_IRQ_STAT(i));
- for (j = 0; (j < 8) && status; j++) {
+ for (j = 0; (j < DMA_IRQ_CHAN_NR) && status; j++) {
if (status & DMA_IRQ_QUEUE) {
pchan = sdev->pchans + j;
vchan = pchan->vchan;
@@ -525,7 +523,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
}
}
- status = status >> 4;
+ status = status >> DMA_IRQ_CHAN_WIDTH;
}
if (!atomic_read(&sdev->tasklet_shutdown))
@@ -817,7 +815,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec,
struct dma_chan *chan;
u8 port = dma_spec->args[0];
- if (port > NR_MAX_REQUESTS)
+ if (port > sdev->cfg->nr_max_requests)
return NULL;
chan = dma_get_any_slave_channel(&sdev->slave);
@@ -850,7 +848,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev)
{
int i;
- for (i = 0; i < NR_MAX_VCHANS; i++) {
+ for (i = 0; i < sdev->cfg->nr_max_vchans; i++) {
struct sun6i_vchan *vchan = &sdev->vchans[i];
list_del(&vchan->vc.chan.device_node);
@@ -858,8 +856,36 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev)
}
}
+/*
+ * For A31:
+ *
+ * There's 16 physical channels that can work in parallel.
+ *
+ * However we have 30 different endpoints for our requests.
+ *
+ * Since the channels are able to handle only an unidirectional
+ * transfer, we need to allocate more virtual channels so that
+ * everyone can grab one channel.
+ *
+ * Some devices can't work in both direction (mostly because it
+ * wouldn't make sense), so we have a bit fewer virtual channels than
+ * 2 channels per endpoints.
+ */
+
+static struct sun6i_dma_config sun6i_a31_dma_cfg = {
+ .nr_max_channels = 16,
+ .nr_max_requests = 30,
+ .nr_max_vchans = 53,
+};
+
+static struct of_device_id sun6i_dma_match[] = {
+ { .compatible = "allwinner,sun6i-a31-dma", .data = &sun6i_a31_dma_cfg },
+ { /* sentinel */ }
+};
+
static int sun6i_dma_probe(struct platform_device *pdev)
{
+ const struct of_device_id *device;
struct sun6i_dma_dev *sdc;
struct resource *res;
int ret, i;
@@ -868,6 +894,11 @@ static int sun6i_dma_probe(struct platform_device *pdev)
if (!sdc)
return -ENOMEM;
+ device = of_match_device(sun6i_dma_match, &pdev->dev);
+ if (!device)
+ return -ENODEV;
+ sdc->cfg = device->data;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
sdc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sdc->base))
@@ -914,30 +945,30 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.device_prep_slave_sg = sun6i_dma_prep_slave_sg;
sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy;
sdc->slave.device_control = sun6i_dma_control;
- sdc->slave.chancnt = NR_MAX_VCHANS;
+ sdc->slave.chancnt = sdc->cfg->nr_max_vchans;
sdc->slave.dev = &pdev->dev;
- sdc->pchans = devm_kcalloc(&pdev->dev, NR_MAX_CHANNELS,
+ sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels,
sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
return -ENOMEM;
- sdc->vchans = devm_kcalloc(&pdev->dev, NR_MAX_VCHANS,
+ sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans,
sizeof(struct sun6i_vchan), GFP_KERNEL);
if (!sdc->vchans)
return -ENOMEM;
tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
- for (i = 0; i < NR_MAX_CHANNELS; i++) {
+ for (i = 0; i < sdc->cfg->nr_max_channels; i++) {
struct sun6i_pchan *pchan = &sdc->pchans[i];
pchan->idx = i;
pchan->base = sdc->base + 0x100 + i * 0x40;
}
- for (i = 0; i < NR_MAX_VCHANS; i++) {
+ for (i = 0; i < sdc->cfg->nr_max_vchans; i++) {
struct sun6i_vchan *vchan = &sdc->vchans[i];
INIT_LIST_HEAD(&vchan->node);
@@ -1009,11 +1040,6 @@ static int sun6i_dma_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id sun6i_dma_match[] = {
- { .compatible = "allwinner,sun6i-a31-dma" },
- { /* sentinel */ }
-};
-
static struct platform_driver sun6i_dma_driver = {
.probe = sun6i_dma_probe,
.remove = sun6i_dma_remove,
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/3] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant
[not found] ` <1411010680-4481-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-09-18 3:24 ` [PATCH v2 1/3] dmaengine: sun6i: support parameterized compatible strings Chen-Yu Tsai
@ 2014-09-18 3:24 ` Chen-Yu Tsai
[not found] ` <1411010680-4481-3-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-09-18 3:24 ` [PATCH v2 3/3] ARM: dts: sun8i: Add DMA controller node Chen-Yu Tsai
2014-09-26 3:06 ` [PATCH v2 0/3] ARM: sun8i: Add DMA controller support Chen-Yu Tsai
3 siblings, 1 reply; 10+ messages in thread
From: Chen-Yu Tsai @ 2014-09-18 3:24 UTC (permalink / raw)
To: Maxime Ripard, Vinod Koul, Dan Williams, Grant Likely,
Rob Herring
Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
The A23 SoC has the same dma engine as the A31 (sun6i), with a
reduced amount of endpoints and physical channels. Add the proper
config data and compatible string to support it.
A slight difference in sun8i is an undocumented register needs
to be toggled for dma to function.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
.../devicetree/bindings/dma/sun6i-dma.txt | 2 +-
drivers/dma/Kconfig | 4 ++--
drivers/dma/sun6i-dma.c | 27 ++++++++++++++++++++++
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 3e145c1..9cdcba24d 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -4,7 +4,7 @@ This driver follows the generic DMA bindings defined in dma.txt.
Required properties:
-- compatible: Must be "allwinner,sun6i-a31-dma"
+- compatible: Must be "allwinner,sun6i-a31-dma" or "allwinner,sun8i-a23-dma"
- reg: Should contain the registers base address and length
- interrupts: Should contain a reference to the interrupt used by this device
- clocks: Should contain a reference to the parent AHB clock
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 9b1ea0e..5361aa7 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -395,12 +395,12 @@ config XILINX_VDMA
config DMA_SUN6I
tristate "Allwinner A31 SoCs DMA support"
- depends on MACH_SUN6I || COMPILE_TEST
+ depends on MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
depends on RESET_CONTROLLER
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
help
- Support for the DMA engine for Allwinner A31 SoCs.
+ Support for the DMA engine first found in Allwinner A31 SoCs.
config NBPFAXI_DMA
tristate "Renesas Type-AXI NBPF DMA support"
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 89ca0c4..cb9aa43 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -43,6 +43,12 @@
#define DMA_STAT 0x30
/*
+ * sun8i specific registers
+ */
+#define SUN8I_DMA_GATE 0x20
+#define SUN8I_DMA_GATE_ENABLE 0x4
+
+/*
* Channels specific registers
*/
#define DMA_CHAN_ENABLE 0x00
@@ -878,8 +884,20 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_vchans = 53,
};
+/*
+ * The A23 only has 8 physical channels, a maximum DRQ port id of 24,
+ * and a total of 37 usable source and destination endpoints.
+ */
+
+static struct sun6i_dma_config sun8i_a23_dma_cfg = {
+ .nr_max_channels = 8,
+ .nr_max_requests = 24,
+ .nr_max_vchans = 37,
+};
+
static struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun6i-a31-dma", .data = &sun6i_a31_dma_cfg },
+ { .compatible = "allwinner,sun8i-a23-dma", .data = &sun8i_a23_dma_cfg },
{ /* sentinel */ }
};
@@ -1008,6 +1026,15 @@ static int sun6i_dma_probe(struct platform_device *pdev)
goto err_dma_unregister;
}
+ /*
+ * sun8i variant requires us to toggle a dma gating register,
+ * as seen in Allwinner's SDK. This register is not documented
+ * in the A23 user manual.
+ */
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "allwinner,sun8i-a23-dma"))
+ writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE);
+
return 0;
err_dma_unregister:
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 3/3] ARM: dts: sun8i: Add DMA controller node
[not found] ` <1411010680-4481-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-09-18 3:24 ` [PATCH v2 1/3] dmaengine: sun6i: support parameterized compatible strings Chen-Yu Tsai
2014-09-18 3:24 ` [PATCH v2 2/3] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant Chen-Yu Tsai
@ 2014-09-18 3:24 ` Chen-Yu Tsai
[not found] ` <1411010680-4481-4-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-09-26 3:06 ` [PATCH v2 0/3] ARM: sun8i: Add DMA controller support Chen-Yu Tsai
3 siblings, 1 reply; 10+ messages in thread
From: Chen-Yu Tsai @ 2014-09-18 3:24 UTC (permalink / raw)
To: Maxime Ripard, Vinod Koul, Dan Williams, Grant Likely,
Rob Herring
Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Add the DMA controller node and DMA bindings to the supported devices.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
---
arch/arm/boot/dts/sun8i-a23.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
index cc8c650..46a8cc9 100644
--- a/arch/arm/boot/dts/sun8i-a23.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -203,6 +203,15 @@
#size-cells = <1>;
ranges;
+ dma: dma-controller@01c02000 {
+ compatible = "allwinner,sun8i-a23-dma";
+ reg = <0x01c02000 0x1000>;
+ interrupts = <0 50 4>;
+ clocks = <&ahb1_gates 6>;
+ resets = <&ahb1_rst 6>;
+ #dma-cells = <1>;
+ };
+
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
@@ -332,6 +341,8 @@
reg-io-width = <4>;
clocks = <&apb2_gates 16>;
resets = <&apb2_rst 16>;
+ dmas = <&dma 6>, <&dma 6>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -343,6 +354,8 @@
reg-io-width = <4>;
clocks = <&apb2_gates 17>;
resets = <&apb2_rst 17>;
+ dmas = <&dma 7>, <&dma 7>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -354,6 +367,8 @@
reg-io-width = <4>;
clocks = <&apb2_gates 18>;
resets = <&apb2_rst 18>;
+ dmas = <&dma 8>, <&dma 8>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -365,6 +380,8 @@
reg-io-width = <4>;
clocks = <&apb2_gates 19>;
resets = <&apb2_rst 19>;
+ dmas = <&dma 9>, <&dma 9>;
+ dma-names = "rx", "tx";
status = "disabled";
};
@@ -376,6 +393,8 @@
reg-io-width = <4>;
clocks = <&apb2_gates 20>;
resets = <&apb2_rst 20>;
+ dmas = <&dma 10>, <&dma 10>;
+ dma-names = "rx", "tx";
status = "disabled";
};
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] ARM: sun8i: Add DMA controller support
[not found] ` <1411010680-4481-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
` (2 preceding siblings ...)
2014-09-18 3:24 ` [PATCH v2 3/3] ARM: dts: sun8i: Add DMA controller node Chen-Yu Tsai
@ 2014-09-26 3:06 ` Chen-Yu Tsai
[not found] ` <CAGb2v65ZkBvqSjwR0bVUu0-=5-pOmydp51K6GeMnxOa4vOtCRQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
3 siblings, 1 reply; 10+ messages in thread
From: Chen-Yu Tsai @ 2014-09-26 3:06 UTC (permalink / raw)
To: Vinod Koul
Cc: Chen-Yu Tsai, Rob Herring, Maxime Ripard, Dan Williams,
Grant Likely, linux-arm-kernel, linux-sunxi,
dmaengine-u79uwXL29TY76Z2rM5mHXA, devicetree
On Thu, Sep 18, 2014 at 11:24 AM, Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> wrote:
> Hi everyone,
>
> This is v2 of my sun8i DMA controller support series. This series
> adds support for the DMA controller found in the Allwinner A23 SoC.
> It is the same hardware as found in the A31 (sun6i) SoC. In addition
> to reduced physical channels and endpoints, the controller in the A23
> requires an undocumented register to be toggled. That seems to allow
> memory bus access.
>
> This series is based on my earlier "clk: sun6i: Unify AHB1 clock and
> fix rate calculation" series, which removes the clock muxing calls from
> the sun6i-dma driver. The default PLL6 pre-divider for AHB1 on the A23
> results in an exceedingly high clock rate for AHB1, and the system hangs.
> Also, on the A23, the dma controller happily works even when AHB1 is
> clocked from AXI.
>
>
> Patch 1 changes the channel count macros into runtime data binded to
> the DT compatible strings. It also gets rid of some hardcoded values
> in the interrupt handler.
>
> Patch 2 adds the channel number data for the A23 (sun8i), as well as
> the undocumented register quirk.
Hi, Vinod,
Any chance we can get patches 1 & 2 merged? You've already merged the
prerequisite patch "dmaengine: sun6i: Remove obsolete clk muxing code"
a few days ago, and patch 3 is already in arm-soc.
Thanks!
ChenYu
> Patch 3 adds the dma controller node, and related dma resources, to the
> DT.
>
> Changes since v1:
>
> - Added Maxime's Acked-by for patch 1
> - Added macros for sun8i specific dma gating registers, and updated
> comment to reflect its usage.
>
>
> Cheers
> ChenYu
>
>
> Chen-Yu Tsai (3):
> dmaengine: sun6i: support parameterized compatible strings
> dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant
> ARM: dts: sun8i: Add DMA controller node
>
> .../devicetree/bindings/dma/sun6i-dma.txt | 2 +-
> arch/arm/boot/dts/sun8i-a23.dtsi | 19 ++++
> drivers/dma/Kconfig | 4 +-
> drivers/dma/sun6i-dma.c | 123 +++++++++++++++------
> 4 files changed, 110 insertions(+), 38 deletions(-)
>
> --
> 2.1.0
>
^ permalink raw reply [flat|nested] 10+ messages in thread