* [PATCH RESEND v2 0/2] ARM: sun8i: Add DMA controller support
@ 2014-11-07 4:15 Chen-Yu Tsai
[not found] ` <1415333747-24075-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: Chen-Yu Tsai @ 2014-11-07 4:15 UTC (permalink / raw)
To: Vinod Koul, Maxime Ripard, Dan Williams, Grant Likely,
Rob Herring
Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Hi Vinod,
This is my sun8i DMA controller series rebased onto slave-dma/next
(2ffff42 "dmaengine: xdmac: fix print warning on dma_addr_t variable")
Original cover letter:
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.
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 (2):
dmaengine: sun6i: support parameterized compatible strings
dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant
.../devicetree/bindings/dma/sun6i-dma.txt | 2 +-
drivers/dma/Kconfig | 4 +-
drivers/dma/sun6i-dma.c | 121 +++++++++++++++------
3 files changed, 90 insertions(+), 37 deletions(-)
--
2.1.1
--
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] 4+ messages in thread
* [PATCH RESEND v2 1/2] dmaengine: sun6i: support parameterized compatible strings
[not found] ` <1415333747-24075-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
@ 2014-11-07 4:15 ` Chen-Yu Tsai
2014-11-07 4:15 ` [PATCH RESEND v2 2/2] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant Chen-Yu Tsai
2014-11-12 9:36 ` [PATCH RESEND v2 0/2] ARM: sun8i: Add DMA controller support Vinod Koul
2 siblings, 0 replies; 4+ messages in thread
From: Chen-Yu Tsai @ 2014-11-07 4:15 UTC (permalink / raw)
To: Vinod Koul, Maxime Ripard, Dan Williams, Grant Likely,
Rob Herring
Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
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 | 94 +++++++++++++++++++++++++++++++------------------
1 file changed, 60 insertions(+), 34 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index a00157a..531abbf 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))
@@ -917,26 +948,26 @@ static int sun6i_dma_probe(struct platform_device *pdev)
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);
@@ -1008,11 +1039,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.1
--
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] 4+ messages in thread
* [PATCH RESEND v2 2/2] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant
[not found] ` <1415333747-24075-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-11-07 4:15 ` [PATCH RESEND v2 1/2] dmaengine: sun6i: support parameterized compatible strings Chen-Yu Tsai
@ 2014-11-07 4:15 ` Chen-Yu Tsai
2014-11-12 9:36 ` [PATCH RESEND v2 0/2] ARM: sun8i: Add DMA controller support Vinod Koul
2 siblings, 0 replies; 4+ messages in thread
From: Chen-Yu Tsai @ 2014-11-07 4:15 UTC (permalink / raw)
To: Vinod Koul, Maxime Ripard, Dan Williams, Grant Likely,
Rob Herring
Cc: Chen-Yu Tsai, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
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>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@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 607271a..aef8b9d 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -402,12 +402,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 531abbf..f9f8f4d 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 */ }
};
@@ -1007,6 +1025,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.1
--
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] 4+ messages in thread
* Re: [PATCH RESEND v2 0/2] ARM: sun8i: Add DMA controller support
[not found] ` <1415333747-24075-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-11-07 4:15 ` [PATCH RESEND v2 1/2] dmaengine: sun6i: support parameterized compatible strings Chen-Yu Tsai
2014-11-07 4:15 ` [PATCH RESEND v2 2/2] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant Chen-Yu Tsai
@ 2014-11-12 9:36 ` Vinod Koul
2 siblings, 0 replies; 4+ messages in thread
From: Vinod Koul @ 2014-11-12 9:36 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Maxime Ripard, Dan Williams, Grant Likely, Rob Herring,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
On Fri, Nov 07, 2014 at 12:15:45PM +0800, Chen-Yu Tsai wrote:
> Hi Vinod,
>
> This is my sun8i DMA controller series rebased onto slave-dma/next
> (2ffff42 "dmaengine: xdmac: fix print warning on dma_addr_t variable")
>
> Original cover letter:
>
> 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.
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] 4+ messages in thread
end of thread, other threads:[~2014-11-12 9:36 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-07 4:15 [PATCH RESEND v2 0/2] ARM: sun8i: Add DMA controller support Chen-Yu Tsai
[not found] ` <1415333747-24075-1-git-send-email-wens-jdAy2FN1RRM@public.gmane.org>
2014-11-07 4:15 ` [PATCH RESEND v2 1/2] dmaengine: sun6i: support parameterized compatible strings Chen-Yu Tsai
2014-11-07 4:15 ` [PATCH RESEND v2 2/2] dmaengine: sun6i: Add support for Allwinner A23 (sun8i) variant Chen-Yu Tsai
2014-11-12 9:36 ` [PATCH RESEND v2 0/2] ARM: sun8i: Add DMA controller support Vinod Koul
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).