* [PATCH v2 5/7] dt-bindings: dma: fsl-edma: add new i.mx7ulp-edma
From: yibin.gong @ 2019-05-27 8:51 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
In-Reply-To: <20190527085118.40423-1-yibin.gong@nxp.com>
From: Robin Gong <yibin.gong@nxp.com>
More channel interrupts, one more clock, and only one
dmamux on i.mx7ulp-edma.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
Documentation/devicetree/bindings/dma/fsl-edma.txt | 44 +++++++++++++++++++---
1 file changed, 39 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt b/Documentation/devicetree/bindings/dma/fsl-edma.txt
index 97e213e..29dd3cc 100644
--- a/Documentation/devicetree/bindings/dma/fsl-edma.txt
+++ b/Documentation/devicetree/bindings/dma/fsl-edma.txt
@@ -9,15 +9,16 @@ group, DMAMUX0 or DMAMUX1, but not both.
Required properties:
- compatible :
- "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC
+ - "fsl,imx7ulp-edma" for eDMA2 used similar to that on i.mx7ulp
- reg : Specifies base physical address(s) and size of the eDMA registers.
The 1st region is eDMA control register's address and size.
The 2nd and the 3rd regions are programmable channel multiplexing
control register's address and size.
- interrupts : A list of interrupt-specifiers, one for each entry in
- interrupt-names.
-- interrupt-names : Should contain:
- "edma-tx" - the transmission interrupt
- "edma-err" - the error interrupt
+ interrupt-names on vf610 similar SoC. But for i.mx7ulp per channel
+ per transmission interrupt, total 16 channel interrupt and 1
+ error interrupt(located in the last), no interrupt-names list on
+ i.mx7ulp for clean on dts.
- #dma-cells : Must be <2>.
The 1st cell specifies the DMAMUX(0 for DMAMUX0 and 1 for DMAMUX1).
Specific request source can only be multiplexed by specific channels
@@ -28,6 +29,7 @@ Required properties:
- clock-names : A list of channel group clock names. Should contain:
"dmamux0" - clock name of mux0 group
"dmamux1" - clock name of mux1 group
+ Note: No dmamux0 on i.mx7ulp, but another 'dma' clk added on i.mx7ulp.
- clocks : A list of phandle and clock-specifier pairs, one for each entry in
clock-names.
@@ -35,6 +37,10 @@ Optional properties:
- big-endian: If present registers and hardware scatter/gather descriptors
of the eDMA are implemented in big endian mode, otherwise in little
mode.
+- interrupt-names : Should contain the below on vf610 similar SoC but not used
+ on i.mx7ulp similar SoC:
+ "edma-tx" - the transmission interrupt
+ "edma-err" - the error interrupt
Examples:
@@ -52,8 +58,36 @@ edma0: dma-controller@40018000 {
clock-names = "dmamux0", "dmamux1";
clocks = <&clks VF610_CLK_DMAMUX0>,
<&clks VF610_CLK_DMAMUX1>;
-};
+}; /* vf610 */
+edma1: dma-controller@40080000 {
+ #dma-cells = <2>;
+ compatible = "fsl,imx7ulp-edma";
+ reg = <0x40080000 0x2000>,
+ <0x40210000 0x1000>;
+ dma-channels = <32>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ /* last is eDMA2-ERR interrupt */
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dma", "dmamux0";
+ clocks = <&pcc2 IMX7ULP_CLK_DMA1>,
+ <&pcc2 IMX7ULP_CLK_DMA_MUX1>;
+}; /* i.mx7ulp */
* DMA clients
DMA client drivers that uses the DMA function must use the format described
--
2.7.4
^ permalink raw reply related
* [PATCH v2 0/7] add edma2 for i.mx7ulp
From: yibin.gong @ 2019-05-27 8:51 UTC (permalink / raw)
To: robh, shawnguo, s.hauer, festevam, mark.rutland, vkoul,
dan.j.williams
Cc: linux-imx, linux-arm-kernel, linux-kernel, dmaengine, devicetree,
kernel
From: Robin Gong <yibin.gong@nxp.com>
This patch set add new version of edma for i.mx7ulp, the main changes
are as belows:
1. only one dmamux.
2. another clock dma_clk except dmamux clk.
3. 16 independent interrupts instead of only one interrupt for
all channels.
For the first change, need modify fsl-edma-common.c and mcf-edma,
so create the first two patches to prepare without any function impact.
For the third change, need request single irq for every channel with
the legacy handler. But actually 2 dma channels share one interrupt(16
channel interrupts, but 32 channels.),ch0/ch16,ch1/ch17... For now, just
simply request irq without IRQF_SHARED flag, since 16 channels are enough
on i.mx7ulp whose M4 domain own some peripherals.
change from v1:
1. Check .data of 'of_device_id' in probe instead of compatible name.
2. pull binding doc patch before driver patch.
Robin Gong (7):
dmaengine: fsl-edma: add dmamux_nr for next version
dmaengine: mcf-edma: update to 'dmamux_nr'
dmaengine: fsl-edma-common: move dmamux register to another single
function
dmaengine: fsl-edma-common: version check for v2 instead
dt-bindings: dma: fsl-edma: add new i.mx7ulp-edma
dmaengine: fsl-edma: add i.mx7ulp edma2 version support
ARM: dts: imx7ulp: add edma device node
Documentation/devicetree/bindings/dma/fsl-edma.txt | 44 ++++++++--
arch/arm/boot/dts/imx7ulp.dtsi | 28 +++++++
drivers/dma/fsl-edma-common.c | 74 +++++++++++------
drivers/dma/fsl-edma-common.h | 4 +
drivers/dma/fsl-edma.c | 95 +++++++++++++++++++---
drivers/dma/mcf-edma.c | 1 +
6 files changed, 204 insertions(+), 42 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [PATCH v1 4/6] dmaengine: fsl-edma: add i.mx7ulp edma2 version support
From: Robin Gong @ 2019-05-27 7:31 UTC (permalink / raw)
To: vkoul@kernel.org
Cc: dl-linux-imx, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, festevam@gmail.com,
dan.j.williams@intel.com, mark.rutland@arm.com,
dmaengine@vger.kernel.org, robh@kernel.org, shawnguo@kernel.org,
linux-arm-kernel@lists.infradead.org, kernel@pengutronix.de,
s.hauer@pengutronix.de
In-Reply-To: <20190527063431.GC15118@vkoul-mobl>
On 2019-05-27 at 06:34 +0000, Vinod Koul wrote:
> On 10-05-19, 10:14, Robin Gong wrote:
> >
> >
> > + if (of_device_is_compatible(np, "fsl,imx7ulp-edma")) {
> > + fsl_edma->dmamux_nr = 1;
> > + fsl_edma->version = v3;
> well this is not really scalable, we will keep adding versions and
> compatible and expanding this check. So it would make sense to create
> a
> driver data table which can be set for compatible and we use those
> values and avoid these runtime checks for compatible.
>
> Btw the binding documentation should precede the code usage, so this
> patch should come after that
>
Okay, will update in v2.
^ permalink raw reply
* Re: [PATCH 1/3][V3] include: fpga: adi-axi-common.h: add common regs & defs header
From: Vinod Koul @ 2019-05-27 7:06 UTC (permalink / raw)
To: Alexandru Ardelean; +Cc: dmaengine
In-Reply-To: <20190527065518.18613-1-alexandru.ardelean@analog.com>
On 27-05-19, 09:55, Alexandru Ardelean wrote:
> The AXI HDL cores provided for Analog Devices reference designs all share
> some common base registers (e.g. version register at address 0x00).
>
> To reduce duplication for this, a common header is added to define these
> registers as well as bitfields & macros to work with these registers.
Applied all, thanks
--
~Vinod
^ permalink raw reply
* [PATCH 3/3][V3] dmaengine: axi-dmac: assign `copy_align` property
From: Alexandru Ardelean @ 2019-05-27 6:55 UTC (permalink / raw)
To: dmaengine; +Cc: Alexandru Ardelean
In-Reply-To: <20190527065518.18613-1-alexandru.ardelean@analog.com>
The `copy_align` property is a generic property that describes alignment
for DMA memcpy & sg ops.
It serves mostly an informational purpose, and can be used in DMA tests, to
pass the info to know what alignment to expect.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
drivers/dma/dma-axi-dmac.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 74ae6246d9a5..d5e29bbc3d43 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -763,6 +763,8 @@ static int axi_dmac_probe(struct platform_device *pdev)
if (ret)
goto err_clk_disable;
+ dma_dev->copy_align = (dmac->chan.address_align_mask + 1);
+
axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x00);
ret = dma_async_device_register(dma_dev);
--
2.17.1
^ permalink raw reply related
* [PATCH 2/3][V3] dmaengine: axi-dmac: Discover length alignment requirement
From: Alexandru Ardelean @ 2019-05-27 6:55 UTC (permalink / raw)
To: dmaengine; +Cc: Lars-Peter Clausen, Alexandru Ardelean
In-Reply-To: <20190527065518.18613-1-alexandru.ardelean@analog.com>
From: Lars-Peter Clausen <lars@metafoo.de>
Starting with version 4.1.a the AXI-DMAC is capable of reporting the
required length alignment.
The LSBs that are required to be set for alignment will always read back as
set from the transfer length register. It is not possible to clear them by
writing a 0. This means the driver can discover the length alignment
requirement by writing 0 to that register and reading back the value.
Since the DMA will support length alignment requirements that are different
from the address alignment requirement track both of them independently.
For older versions of the peripheral assume that the length alignment
requirement is equal to the address alignment requirement.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
drivers/dma/dma-axi-dmac.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 0984ae6eb155..74ae6246d9a5 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -20,6 +20,7 @@
#include <linux/of_dma.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/fpga/adi-axi-common.h>
#include <dt-bindings/dma/axi-dmac.h>
@@ -110,7 +111,8 @@ struct axi_dmac_chan {
unsigned int dest_type;
unsigned int max_length;
- unsigned int align_mask;
+ unsigned int address_align_mask;
+ unsigned int length_align_mask;
bool hw_cyclic;
bool hw_2d;
@@ -169,14 +171,14 @@ static bool axi_dmac_check_len(struct axi_dmac_chan *chan, unsigned int len)
{
if (len == 0)
return false;
- if ((len & chan->align_mask) != 0) /* Not aligned */
+ if ((len & chan->length_align_mask) != 0) /* Not aligned */
return false;
return true;
}
static bool axi_dmac_check_addr(struct axi_dmac_chan *chan, dma_addr_t addr)
{
- if ((addr & chan->align_mask) != 0) /* Not aligned */
+ if ((addr & chan->address_align_mask) != 0) /* Not aligned */
return false;
return true;
}
@@ -394,7 +396,7 @@ static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
num_segments = DIV_ROUND_UP(period_len, chan->max_length);
segment_size = DIV_ROUND_UP(period_len, num_segments);
/* Take care of alignment */
- segment_size = ((segment_size - 1) | chan->align_mask) + 1;
+ segment_size = ((segment_size - 1) | chan->length_align_mask) + 1;
for (i = 0; i < num_periods; i++) {
len = period_len;
@@ -623,7 +625,7 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan,
return ret;
chan->dest_width = val / 8;
- chan->align_mask = max(chan->dest_width, chan->src_width) - 1;
+ chan->address_align_mask = max(chan->dest_width, chan->src_width) - 1;
if (axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
chan->direction = DMA_MEM_TO_MEM;
@@ -640,6 +642,9 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan,
static int axi_dmac_detect_caps(struct axi_dmac *dmac)
{
struct axi_dmac_chan *chan = &dmac->chan;
+ unsigned int version;
+
+ version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, AXI_DMAC_FLAG_CYCLIC);
if (axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS) == AXI_DMAC_FLAG_CYCLIC)
@@ -670,6 +675,14 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac)
return -ENODEV;
}
+ if (version >= ADI_AXI_PCORE_VER(4, 1, 'a')) {
+ axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, 0x00);
+ chan->length_align_mask =
+ axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH);
+ } else {
+ chan->length_align_mask = chan->address_align_mask;
+ }
+
return 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH 1/3][V3] include: fpga: adi-axi-common.h: add common regs & defs header
From: Alexandru Ardelean @ 2019-05-27 6:55 UTC (permalink / raw)
To: dmaengine; +Cc: Alexandru Ardelean
The AXI HDL cores provided for Analog Devices reference designs all share
some common base registers (e.g. version register at address 0x00).
To reduce duplication for this, a common header is added to define these
registers as well as bitfields & macros to work with these registers.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
Changelog v2 -> v3:
* fixed style for SPDX-License-Identifier in C header
* fixed minor checkpatch complaint about 80 col limit
include/linux/fpga/adi-axi-common.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 include/linux/fpga/adi-axi-common.h
diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h
new file mode 100644
index 000000000000..7fc95d5c95bb
--- /dev/null
+++ b/include/linux/fpga/adi-axi-common.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Analog Devices AXI common registers & definitions
+ *
+ * Copyright 2019 Analog Devices Inc.
+ *
+ * https://wiki.analog.com/resources/fpga/docs/axi_ip
+ * https://wiki.analog.com/resources/fpga/docs/hdl/regmap
+ */
+
+#ifndef ADI_AXI_COMMON_H_
+#define ADI_AXI_COMMON_H_
+
+#define ADI_AXI_REG_VERSION 0x0000
+
+#define ADI_AXI_PCORE_VER(major, minor, patch) \
+ (((major) << 16) | ((minor) << 8) | (patch))
+
+#endif /* ADI_AXI_COMMON_H_ */
--
2.17.1
^ permalink raw reply related
* Re: [PATCH] dmaengine: use to_platform_device()
From: Vinod Koul @ 2019-05-27 6:43 UTC (permalink / raw)
To: Weitao Hou
Cc: dan.j.williams, mcoquelin.stm32, alexandre.torgue, dmaengine,
linux-stm32, linux-arm-kernel, linux-kernel
In-Reply-To: <20190526071324.15307-1-houweitaoo@gmail.com>
On 26-05-19, 15:13, Weitao Hou wrote:
> Use to_platform_device() instead of open-coding it.
Applied after adding stm32 driver tag, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH 1/3][V2] include: fpga: adi-axi-common.h: add common regs & defs header
From: Ardelean, Alexandru @ 2019-05-27 6:40 UTC (permalink / raw)
To: vkoul@kernel.org; +Cc: dmaengine@vger.kernel.org
In-Reply-To: <20190527063743.GD15118@vkoul-mobl>
On Mon, 2019-05-27 at 12:07 +0530, Vinod Koul wrote:
> [External]
>
>
> On 21-05-19, 17:14, Alexandru Ardelean wrote:
> > The AXI HDL cores provided for Analog Devices reference designs all share
> > some common base registers (e.g. version register at address 0x00).
> >
> > To reduce duplication for this, a common header is added to define these
> > registers as well as bitfields & macros to work with these registers.
> >
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > ---
> > include/linux/fpga/adi-axi-common.h | 19 +++++++++++++++++++
> > 1 file changed, 19 insertions(+)
> > create mode 100644 include/linux/fpga/adi-axi-common.h
> >
> > diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h
> > new file mode 100644
> > index 000000000000..7966c89561b1
> > --- /dev/null
> > +++ b/include/linux/fpga/adi-axi-common.h
> > @@ -0,0 +1,19 @@
> > +// SPDX-License-Identifier: GPL-2.0
>
> For headers this is not the style to be used.
> See Documentation/process/license-rules.rst
>
> C source: // SPDX-License-Identifier: <SPDX License Expression>
> C header: /* SPDX-License-Identifier: <SPDX License Expression> */
>
Ack.
Will re-spin.
> > +/*
> > + * Analog Devices AXI common registers & definitions
> > + *
> > + * Copyright 2019 Analog Devices Inc.
> > + *
> > + * https://wiki.analog.com/resources/fpga/docs/axi_ip
> > + * https://wiki.analog.com/resources/fpga/docs/hdl/regmap
> > + */
> > +
> > +#ifndef ADI_AXI_COMMON_H_
> > +#define ADI_AXI_COMMON_H_
> > +
> > +#define ADI_AXI_REG_VERSION 0x0000
> > +
> > +#define ADI_AXI_PCORE_VER(major, minor, patch) \
> > + (((major) << 16) | ((minor) << 8) | (patch))
> > +
> > +#endif /* ADI_AXI_COMMON_H_ */
> > --
> > 2.17.1
>
> --
> ~Vinod
^ permalink raw reply
* Re: [PATCH 2/2] serial: 8250-mtk: modify uart DMA rx
From: Vinod Koul @ 2019-05-27 6:40 UTC (permalink / raw)
To: Long Cheng
Cc: Randy Dunlap, Rob Herring, Mark Rutland, Ryder Lee, Sean Wang,
Nicolas Boichat, Matthias Brugger, Dan Williams,
Greg Kroah-Hartman, Jiri Slaby, Sean Wang, dmaengine, devicetree,
linux-arm-kernel, linux-mediatek, linux-kernel, linux-serial,
srv_heupstream, Yingjoe Chen, YT Shen, Zhenbao Liu
In-Reply-To: <1558596909-14084-3-git-send-email-long.cheng@mediatek.com>
On 23-05-19, 15:35, Long Cheng wrote:
> Modify uart rx and complete for DMA
Reviewed-by: Vinod Koul <vkoul@kernel.org>
--
~Vinod
^ permalink raw reply
* Re: [PATCH v3 0/2] dmaengine: ti: edma: Polled completion support
From: Vinod Koul @ 2019-05-27 6:39 UTC (permalink / raw)
To: Peter Ujfalusi; +Cc: dan.j.williams, dmaengine, linux-arm-kernel, linux-omap
In-Reply-To: <19b0d346-5249-e832-8eea-685c8e7706e2@ti.com>
On 23-05-19, 13:57, Peter Ujfalusi wrote:
> Vinod,
>
> On 21/05/2019 12.36, Peter Ujfalusi wrote:
> > Hi,
> >
> > Changes since v2:
> > - Fix typo in the comment for patch 0
> >
> > Changes since v1:
> > - Cleanup patch for the array register handling
> > - typo fixed in patch2 commit message
> >
> > The code around the array register access was pretty confusing for the first
> > look, so clean them up first then use the cleaner way in the polled handling.
> >
> > When a DMA client driver decides that it is not providing callback for
> > completion of a transfer (and/or does not set the DMA_PREP_INTERRUPT) but
> > it will poll the status of the transfer (in case of short memcpy for
> > example) we will not get interrupt for the completion of the transfer and
> > will not mark the transaction as done.
> >
> > Check the event registers (ER and EER) and if the channel is inactive then
> > return wioth DMA_COMPLETE to let the client know that the transfer is
> > completed.
>
> Please do not pick this up yet, I got report that it might cause side
> effect which I need to debug to understand.
OK dropped for queue
--
~Vinod
^ permalink raw reply
* Re: [PATCH 1/3][V2] include: fpga: adi-axi-common.h: add common regs & defs header
From: Vinod Koul @ 2019-05-27 6:37 UTC (permalink / raw)
To: Alexandru Ardelean; +Cc: dmaengine
In-Reply-To: <20190521141425.26176-1-alexandru.ardelean@analog.com>
On 21-05-19, 17:14, Alexandru Ardelean wrote:
> The AXI HDL cores provided for Analog Devices reference designs all share
> some common base registers (e.g. version register at address 0x00).
>
> To reduce duplication for this, a common header is added to define these
> registers as well as bitfields & macros to work with these registers.
>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---
> include/linux/fpga/adi-axi-common.h | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
> create mode 100644 include/linux/fpga/adi-axi-common.h
>
> diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h
> new file mode 100644
> index 000000000000..7966c89561b1
> --- /dev/null
> +++ b/include/linux/fpga/adi-axi-common.h
> @@ -0,0 +1,19 @@
> +// SPDX-License-Identifier: GPL-2.0
For headers this is not the style to be used.
See Documentation/process/license-rules.rst
C source: // SPDX-License-Identifier: <SPDX License Expression>
C header: /* SPDX-License-Identifier: <SPDX License Expression> */
> +/*
> + * Analog Devices AXI common registers & definitions
> + *
> + * Copyright 2019 Analog Devices Inc.
> + *
> + * https://wiki.analog.com/resources/fpga/docs/axi_ip
> + * https://wiki.analog.com/resources/fpga/docs/hdl/regmap
> + */
> +
> +#ifndef ADI_AXI_COMMON_H_
> +#define ADI_AXI_COMMON_H_
> +
> +#define ADI_AXI_REG_VERSION 0x0000
> +
> +#define ADI_AXI_PCORE_VER(major, minor, patch) \
> + (((major) << 16) | ((minor) << 8) | (patch))
> +
> +#endif /* ADI_AXI_COMMON_H_ */
> --
> 2.17.1
--
~Vinod
^ permalink raw reply
* Re: [PATCH v1 4/6] dmaengine: fsl-edma: add i.mx7ulp edma2 version support
From: Vinod Koul @ 2019-05-27 6:34 UTC (permalink / raw)
To: Robin Gong
Cc: robh@kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de,
festevam@gmail.com, mark.rutland@arm.com,
dan.j.williams@intel.com, dl-linux-imx,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
devicetree@vger.kernel.org, kernel@pengutronix.de
In-Reply-To: <1557512248-8440-5-git-send-email-yibin.gong@nxp.com>
On 10-05-19, 10:14, Robin Gong wrote:
> Add edma2 for i.mx7ulp by version v3, since v2 has already
> been used by mcf-edma.
> The big changes based on v1 are belows:
> 1. only one dmamux.
> 2. another clock dma_clk except dmamux clk.
> 3. 16 independent interrupts instead of only one interrupt for
> all channels.
>
> Signed-off-by: Robin Gong <yibin.gong@nxp.com>
> ---
> drivers/dma/fsl-edma-common.c | 18 ++++++++++-
> drivers/dma/fsl-edma-common.h | 3 ++
> drivers/dma/fsl-edma.c | 69 ++++++++++++++++++++++++++++++++++++++++++-
> 3 files changed, 88 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
> index bb24251..64e822e 100644
> --- a/drivers/dma/fsl-edma-common.c
> +++ b/drivers/dma/fsl-edma-common.c
> @@ -90,6 +90,19 @@ static void mux_configure8(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
> iowrite8(val8, addr + off);
> }
>
> +void mux_configure32(struct fsl_edma_chan *fsl_chan, void __iomem *addr,
> + u32 off, u32 slot, bool enable)
> +{
> + u32 val;
> +
> + if (enable)
> + val = EDMAMUX_CHCFG_ENBL << 24 | slot;
> + else
> + val = EDMAMUX_CHCFG_DIS;
> +
> + iowrite32(val, addr + off * 4);
> +}
> +
> void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
> unsigned int slot, bool enable)
> {
> @@ -102,7 +115,10 @@ void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
> muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
> slot = EDMAMUX_CHCFG_SOURCE(slot);
>
> - mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
> + if (fsl_chan->edma->version == v3)
> + mux_configure32(fsl_chan, muxaddr, ch_off, slot, enable);
> + else
> + mux_configure8(fsl_chan, muxaddr, ch_off, slot, enable);
> }
> EXPORT_SYMBOL_GPL(fsl_edma_chan_mux);
>
> diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
> index 21a9cfd..2b0cc8e 100644
> --- a/drivers/dma/fsl-edma-common.h
> +++ b/drivers/dma/fsl-edma-common.h
> @@ -124,6 +124,7 @@ struct fsl_edma_chan {
> dma_addr_t dma_dev_addr;
> u32 dma_dev_size;
> enum dma_data_direction dma_dir;
> + char chan_name[16];
> };
>
> struct fsl_edma_desc {
> @@ -138,6 +139,7 @@ struct fsl_edma_desc {
> enum edma_version {
> v1, /* 32ch, Vybrid, mpc57x, etc */
> v2, /* 64ch Coldfire */
> + v3, /* 32ch, i.mx7ulp */
> };
>
> struct fsl_edma_engine {
> @@ -145,6 +147,7 @@ struct fsl_edma_engine {
> void __iomem *membase;
> void __iomem *muxbase[DMAMUX_NR];
> struct clk *muxclk[DMAMUX_NR];
> + struct clk *dmaclk;
> u32 dmamux_nr;
> struct mutex fsl_edma_mutex;
> u32 n_chans;
> diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
> index 7b65ef4..1568070 100644
> --- a/drivers/dma/fsl-edma.c
> +++ b/drivers/dma/fsl-edma.c
> @@ -165,6 +165,51 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
> return 0;
> }
>
> +static int
> +fsl_edma2_irq_init(struct platform_device *pdev,
> + struct fsl_edma_engine *fsl_edma)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + int i, ret, irq;
> + int count = 0;
> +
> + count = of_irq_count(np);
> + dev_info(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count);
> + if (count <= 2) {
> + dev_err(&pdev->dev, "Interrupts in DTS not correct.\n");
> + return -EINVAL;
> + }
> + /*
> + * 16 channel independent interrupts + 1 error interrupt on i.mx7ulp.
> + * 2 channel share one interrupt, for example, ch0/ch16, ch1/ch17...
> + * For now, just simply request irq without IRQF_SHARED flag, since 16
> + * channels are enough on i.mx7ulp whose M4 domain own some peripherals.
> + */
> + for (i = 0; i < count; i++) {
> + irq = platform_get_irq(pdev, i);
> + if (irq < 0)
> + return -ENXIO;
> +
> + sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i);
> +
> + /* The last IRQ is for eDMA err */
> + if (i == count - 1)
> + ret = devm_request_irq(&pdev->dev, irq,
> + fsl_edma_err_handler,
> + 0, "eDMA2-ERR", fsl_edma);
> + else
> +
> + ret = devm_request_irq(&pdev->dev, irq,
> + fsl_edma_tx_handler, 0,
> + fsl_edma->chans[i].chan_name,
> + fsl_edma);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> static void fsl_edma_irq_exit(
> struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
> {
> @@ -218,6 +263,23 @@ static int fsl_edma_probe(struct platform_device *pdev)
> fsl_edma_setup_regs(fsl_edma);
> regs = &fsl_edma->regs;
>
> + if (of_device_is_compatible(np, "fsl,imx7ulp-edma")) {
> + fsl_edma->dmamux_nr = 1;
> + fsl_edma->version = v3;
well this is not really scalable, we will keep adding versions and
compatible and expanding this check. So it would make sense to create a
driver data table which can be set for compatible and we use those
values and avoid these runtime checks for compatible.
Btw the binding documentation should precede the code usage, so this
patch should come after that
> +
> + fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma");
> + if (IS_ERR(fsl_edma->dmaclk)) {
> + dev_err(&pdev->dev, "Missing DMA block clock.\n");
> + return PTR_ERR(fsl_edma->dmaclk);
> + }
> +
> + ret = clk_prepare_enable(fsl_edma->dmaclk);
> + if (ret) {
> + dev_err(&pdev->dev, "DMA clk block failed.\n");
> + return ret;
> + }
> + }
> +
> for (i = 0; i < fsl_edma->dmamux_nr; i++) {
> char clkname[32];
>
> @@ -264,7 +326,11 @@ static int fsl_edma_probe(struct platform_device *pdev)
> }
>
> edma_writel(fsl_edma, ~0, regs->intl);
> - ret = fsl_edma_irq_init(pdev, fsl_edma);
> +
> + if (fsl_edma->version == v3)
> + ret = fsl_edma2_irq_init(pdev, fsl_edma);
> + else
> + ret = fsl_edma_irq_init(pdev, fsl_edma);
> if (ret)
> return ret;
>
> @@ -385,6 +451,7 @@ static const struct dev_pm_ops fsl_edma_pm_ops = {
>
> static const struct of_device_id fsl_edma_dt_ids[] = {
> { .compatible = "fsl,vf610-edma", },
> + { .compatible = "fsl,imx7ulp-edma", },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
> --
> 2.7.4
>
--
~Vinod
^ permalink raw reply
* Re: [PATCH v2 0/8] Add matching device node validation in DMA engine core
From: Vinod Koul @ 2019-05-27 5:54 UTC (permalink / raw)
To: Baolin Wang
Cc: dan.j.williams, thierry.reding, jonathanh, linux-tegra, shawnguo,
s.hauer, kernel, festevam, linux-imx, wsa+renesas, jroedel,
vincent.guittot, dmaengine, linux-kernel, linux-arm-kernel
In-Reply-To: <cover.1558351667.git.baolin.wang@linaro.org>
On 20-05-19, 19:32, Baolin Wang wrote:
> Hi,
>
> This patch set adds a device node validation in DMA engine core, that will
> help some drivers to remove the duplicate device node validation in each
> driver.
Applied all, thanks
--
~Vinod
^ permalink raw reply
* Re: [PATCH v2 5/7] dmaengine: sun6i: Add support for H6 DMA
From: Clément Péron @ 2019-05-26 19:12 UTC (permalink / raw)
To: Maxime Ripard
Cc: Vinod Koul, Rob Herring, Mark Rutland, Chen-Yu Tsai, Dan Williams,
dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec
In-Reply-To: <20190526183425.nbhrk5pa264p7tdy@flea>
Hi Maxime,
On Sun, 26 May 2019 at 20:34, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Sat, May 25, 2019 at 06:38:17PM +0200, Clément Péron wrote:
> > From: Jernej Skrabec <jernej.skrabec@siol.net>
> >
> > H6 DMA has more than 32 supported DRQs, which means that configuration
> > register is slightly rearranged. It also needs additional clock to be
> > enabled.
> >
> > Add support for it.
> >
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > Signed-off-by: Clément Péron <peron.clem@gmail.com>
> > ---
> > drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
> > 1 file changed, 42 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> > index f5cb5e89bf7b..8d44ddae926a 100644
> > --- a/drivers/dma/sun6i-dma.c
> > +++ b/drivers/dma/sun6i-dma.c
> > @@ -69,14 +69,19 @@
> >
> > #define DMA_CHAN_CUR_CFG 0x0c
> > #define DMA_CHAN_MAX_DRQ_A31 0x1f
> > +#define DMA_CHAN_MAX_DRQ_H6 0x3f
> > #define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
> > +#define DMA_CHAN_CFG_SRC_DRQ_H6(x) ((x) & DMA_CHAN_MAX_DRQ_H6)
> > #define DMA_CHAN_CFG_SRC_MODE_A31(x) (((x) & 0x1) << 5)
> > +#define DMA_CHAN_CFG_SRC_MODE_H6(x) (((x) & 0x1) << 8)
> > #define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
> > #define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
> > #define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
> >
> > #define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
> > +#define DMA_CHAN_CFG_DST_DRQ_H6(x) (DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
> > #define DMA_CHAN_CFG_DST_MODE_A31(x) (DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
> > +#define DMA_CHAN_CFG_DST_MODE_H6(x) (DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
> > #define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
> > #define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
> > #define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
> > @@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
> > DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
> > }
> >
> > +static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
> > +{
> > + *p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
> > + DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
> > +}
> > +
> > static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> > {
> > *p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
> > DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
> > }
> >
> > +static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> > +{
> > + *p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
> > + DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
> > +}
> > +
> > static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
> > {
> > struct sun6i_desc *txd = pchan->desc;
> > @@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
> > BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> > };
> >
> > +/*
> > + * The H6 binding uses the number of dma channels from the
> > + * device tree node.
> > + */
> > +static struct sun6i_dma_config sun50i_h6_dma_cfg = {
> > + .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
> > + .set_burst_length = sun6i_set_burst_length_h3,
> > + .set_drq = sun6i_set_drq_h6,
> > + .set_mode = sun6i_set_mode_h6,
> > + .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> > + .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> > + .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> > + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> > + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> > + .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> > + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> > + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> > + .has_mbus_clk = true,
> > +};
> > +
> > /*
> > * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
> > * and a total of 24 usable source and destination endpoints.
> > @@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] = {
> > { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
> > { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
> > { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
> > + { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
> > { /* sentinel */ }
> > };
> > MODULE_DEVICE_TABLE(of, sun6i_dma_match);
> > @@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
> > ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
> > if (ret && !sdc->max_request) {
> > dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
> > - DMA_CHAN_MAX_DRQ_A31);
> > - sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
> > + DMA_CHAN_MAX_DRQ_H6);
> > + sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
>
> This is changing the binding though, since we're changing the
> default. This should be reflected in the binding, and we should keep
> the same default in the device tree binding.
Agree, H6 device-tree will have the "dma-request" property.
As this modification is not mandatory, we can drop it to avoid
bindings modification.
What do you think?
Thanks for your review,
Clément
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
^ permalink raw reply
* Re: [PATCH v2 5/7] dmaengine: sun6i: Add support for H6 DMA
From: Maxime Ripard @ 2019-05-26 18:34 UTC (permalink / raw)
To: Clément Péron
Cc: Vinod Koul, Rob Herring, Mark Rutland, Chen-Yu Tsai, Dan Williams,
dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec
In-Reply-To: <20190525163819.21055-6-peron.clem@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5003 bytes --]
On Sat, May 25, 2019 at 06:38:17PM +0200, Clément Péron wrote:
> From: Jernej Skrabec <jernej.skrabec@siol.net>
>
> H6 DMA has more than 32 supported DRQs, which means that configuration
> register is slightly rearranged. It also needs additional clock to be
> enabled.
>
> Add support for it.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> Signed-off-by: Clément Péron <peron.clem@gmail.com>
> ---
> drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 42 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index f5cb5e89bf7b..8d44ddae926a 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -69,14 +69,19 @@
>
> #define DMA_CHAN_CUR_CFG 0x0c
> #define DMA_CHAN_MAX_DRQ_A31 0x1f
> +#define DMA_CHAN_MAX_DRQ_H6 0x3f
> #define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
> +#define DMA_CHAN_CFG_SRC_DRQ_H6(x) ((x) & DMA_CHAN_MAX_DRQ_H6)
> #define DMA_CHAN_CFG_SRC_MODE_A31(x) (((x) & 0x1) << 5)
> +#define DMA_CHAN_CFG_SRC_MODE_H6(x) (((x) & 0x1) << 8)
> #define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
> #define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
> #define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
>
> #define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
> +#define DMA_CHAN_CFG_DST_DRQ_H6(x) (DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
> #define DMA_CHAN_CFG_DST_MODE_A31(x) (DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
> +#define DMA_CHAN_CFG_DST_MODE_H6(x) (DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
> #define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
> #define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
> #define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
> @@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
> DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
> }
>
> +static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
> +{
> + *p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
> + DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
> +}
> +
> static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> {
> *p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
> DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
> }
>
> +static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
> +{
> + *p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
> + DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
> +}
> +
> static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
> {
> struct sun6i_desc *txd = pchan->desc;
> @@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
> BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> };
>
> +/*
> + * The H6 binding uses the number of dma channels from the
> + * device tree node.
> + */
> +static struct sun6i_dma_config sun50i_h6_dma_cfg = {
> + .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
> + .set_burst_length = sun6i_set_burst_length_h3,
> + .set_drq = sun6i_set_drq_h6,
> + .set_mode = sun6i_set_mode_h6,
> + .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> + .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> + .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> + .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> + .has_mbus_clk = true,
> +};
> +
> /*
> * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
> * and a total of 24 usable source and destination endpoints.
> @@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] = {
> { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
> { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
> { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
> + { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, sun6i_dma_match);
> @@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
> ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
> if (ret && !sdc->max_request) {
> dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
> - DMA_CHAN_MAX_DRQ_A31);
> - sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
> + DMA_CHAN_MAX_DRQ_H6);
> + sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
This is changing the binding though, since we're changing the
default. This should be reflected in the binding, and we should keep
the same default in the device tree binding.
Maxime
--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH] dmaengine: use to_platform_device()
From: Weitao Hou @ 2019-05-26 7:13 UTC (permalink / raw)
To: vkoul, dan.j.williams, mcoquelin.stm32, alexandre.torgue
Cc: dmaengine, linux-stm32, linux-arm-kernel, linux-kernel,
Weitao Hou
Use to_platform_device() instead of open-coding it.
Signed-off-by: Weitao Hou <houweitaoo@gmail.com>
---
drivers/dma/stm32-dmamux.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c
index a67119199c45..63af24d4c834 100644
--- a/drivers/dma/stm32-dmamux.c
+++ b/drivers/dma/stm32-dmamux.c
@@ -306,8 +306,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev)
#ifdef CONFIG_PM
static int stm32_dmamux_runtime_suspend(struct device *dev)
{
- struct platform_device *pdev =
- container_of(dev, struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(dev);
struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev);
clk_disable_unprepare(stm32_dmamux->clk);
@@ -317,8 +316,7 @@ static int stm32_dmamux_runtime_suspend(struct device *dev)
static int stm32_dmamux_runtime_resume(struct device *dev)
{
- struct platform_device *pdev =
- container_of(dev, struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(dev);
struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev);
int ret;
--
2.18.0
^ permalink raw reply related
* [PATCH v2 1/7] dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec, Rob Herring, Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
From: Jernej Skrabec <jernej.skrabec@siol.net>
DMA in H6 is similar to other DMA controller, except it is first which
supports more than 32 request sources and has 16 channels. It also needs
additional clock to be enabled.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
Documentation/devicetree/bindings/dma/sun6i-dma.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 7fccc20d8331..cae31f4e77ba 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -28,12 +28,17 @@ Example:
};
------------------------------------------------------------------------------
-For A64 DMA controller:
+For A64 and H6 DMA controller:
Required properties:
-- compatible: "allwinner,sun50i-a64-dma"
+- compatible: Must be one of
+ "allwinner,sun50i-a64-dma"
+ "allwinner,sun50i-h6-dma"
- dma-channels: Number of DMA channels supported by the controller.
Refer to Documentation/devicetree/bindings/dma/dma.txt
+- clocks: In addition to parent AHB clock, it should also contain mbus
+ clock (H6 only)
+- clock-names: Should contain "bus" and "mbus" (H6 only)
- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
Optional properties:
--
2.20.1
^ permalink raw reply related
* [PATCH v2 2/7] dmaengine: sun6i: Add a quirk for additional mbus clock
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec, Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
From: Jernej Skrabec <jernej.skrabec@siol.net>
H6 DMA controller needs additional mbus clock to be enabled.
Add a quirk for it and handle it accordingly.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
drivers/dma/sun6i-dma.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 0cd13f17fc11..7d9606997251 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -129,6 +129,7 @@ struct sun6i_dma_config {
u32 dst_burst_lengths;
u32 src_addr_widths;
u32 dst_addr_widths;
+ bool has_mbus_clk;
};
/*
@@ -182,6 +183,7 @@ struct sun6i_dma_dev {
struct dma_device slave;
void __iomem *base;
struct clk *clk;
+ struct clk *clk_mbus;
int irq;
spinlock_t lock;
struct reset_control *rstc;
@@ -1208,6 +1210,14 @@ static int sun6i_dma_probe(struct platform_device *pdev)
return PTR_ERR(sdc->clk);
}
+ if (sdc->cfg->has_mbus_clk) {
+ sdc->clk_mbus = devm_clk_get(&pdev->dev, "mbus");
+ if (IS_ERR(sdc->clk_mbus)) {
+ dev_err(&pdev->dev, "No mbus clock specified\n");
+ return PTR_ERR(sdc->clk_mbus);
+ }
+ }
+
sdc->rstc = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(sdc->rstc)) {
dev_err(&pdev->dev, "No reset controller specified\n");
@@ -1312,11 +1322,19 @@ static int sun6i_dma_probe(struct platform_device *pdev)
goto err_reset_assert;
}
+ if (sdc->cfg->has_mbus_clk) {
+ ret = clk_prepare_enable(sdc->clk_mbus);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't enable mbus clock\n");
+ goto err_clk_disable;
+ }
+ }
+
ret = devm_request_irq(&pdev->dev, sdc->irq, sun6i_dma_interrupt, 0,
dev_name(&pdev->dev), sdc);
if (ret) {
dev_err(&pdev->dev, "Cannot request IRQ\n");
- goto err_clk_disable;
+ goto err_mbus_clk_disable;
}
ret = dma_async_device_register(&sdc->slave);
@@ -1341,6 +1359,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
dma_async_device_unregister(&sdc->slave);
err_irq_disable:
sun6i_kill_tasklet(sdc);
+err_mbus_clk_disable:
+ clk_disable_unprepare(sdc->clk_mbus);
err_clk_disable:
clk_disable_unprepare(sdc->clk);
err_reset_assert:
@@ -1359,6 +1379,7 @@ static int sun6i_dma_remove(struct platform_device *pdev)
sun6i_kill_tasklet(sdc);
+ clk_disable_unprepare(sdc->clk_mbus);
clk_disable_unprepare(sdc->clk);
reset_control_assert(sdc->rstc);
--
2.20.1
^ permalink raw reply related
* [PATCH v2 3/7] dmaengine: sun6i: Add a quirk for setting DRQ fields
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec, Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
From: Jernej Skrabec <jernej.skrabec@siol.net>
H6 DMA has more than 32 possible DRQs. That means that current maximum
of 31 DRQs is not enough anymore.
Add a quirk which will set source and destination DRQ number.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
drivers/dma/sun6i-dma.c | 48 ++++++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 20 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 7d9606997251..f725b93fd21a 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,15 +68,15 @@
#define DMA_CHAN_LLI_ADDR 0x08
#define DMA_CHAN_CUR_CFG 0x0c
-#define DMA_CHAN_MAX_DRQ 0x1f
-#define DMA_CHAN_CFG_SRC_DRQ(x) ((x) & DMA_CHAN_MAX_DRQ)
+#define DMA_CHAN_MAX_DRQ_A31 0x1f
+#define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
#define DMA_CHAN_CFG_SRC_IO_MODE BIT(5)
#define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5)
#define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
#define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
-#define DMA_CHAN_CFG_DST_DRQ(x) (DMA_CHAN_CFG_SRC_DRQ(x) << 16)
+#define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
#define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16)
#define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
#define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
@@ -125,6 +125,7 @@ struct sun6i_dma_config {
*/
void (*clock_autogate_enable)(struct sun6i_dma_dev *);
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+ void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
u32 src_burst_lengths;
u32 dst_burst_lengths;
u32 src_addr_widths;
@@ -311,6 +312,12 @@ static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
}
+static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_DRQ_A31(src_drq) |
+ DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -634,14 +641,13 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
burst = convert_burst(8);
width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
- v_lli->cfg = DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_LINEAR_MODE |
+ v_lli->cfg = DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
DMA_CHAN_CFG_SRC_WIDTH(width) |
DMA_CHAN_CFG_DST_WIDTH(width);
sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
+ sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, DRQ_SDRAM);
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
@@ -695,9 +701,8 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
v_lli->dst = sconfig->dst_addr;
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -710,9 +715,8 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
v_lli->dst = sg_dma_address(sg);
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE |
- DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_IO_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -780,17 +784,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
v_lli->dst = sconfig->dst_addr;
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_DST_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
} else {
v_lli->src = sconfig->src_addr;
v_lli->dst = buf_addr + period_len * i;
v_lli->cfg = lli_cfg |
DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE |
- DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
- DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+ DMA_CHAN_CFG_SRC_IO_MODE;
+ sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
}
prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
@@ -1055,6 +1057,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_requests = 30,
.nr_max_vchans = 53,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1076,6 +1079,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_vchans = 37,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1092,6 +1096,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_vchans = 39,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1115,6 +1120,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans = 34,
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1134,6 +1140,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
static struct sun6i_dma_config sun50i_a64_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1157,6 +1164,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.nr_max_vchans = 24,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
+ .set_drq = sun6i_set_drq_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1272,8 +1280,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
if (ret && !sdc->max_request) {
dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
- DMA_CHAN_MAX_DRQ);
- sdc->max_request = DMA_CHAN_MAX_DRQ;
+ DMA_CHAN_MAX_DRQ_A31);
+ sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
}
/*
--
2.20.1
^ permalink raw reply related
* [PATCH v2 4/7] dmaengine: sun6i: Add a quirk for setting mode fields
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec, Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
From: Jernej Skrabec <jernej.skrabec@siol.net>
H6 DMA has mode fields in different position than any other currently
supported DMA controller.
Add a quirk for that.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
drivers/dma/sun6i-dma.c | 46 ++++++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index f725b93fd21a..f5cb5e89bf7b 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -70,15 +70,13 @@
#define DMA_CHAN_CUR_CFG 0x0c
#define DMA_CHAN_MAX_DRQ_A31 0x1f
#define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
-#define DMA_CHAN_CFG_SRC_IO_MODE BIT(5)
-#define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5)
+#define DMA_CHAN_CFG_SRC_MODE_A31(x) (((x) & 0x1) << 5)
#define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
#define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
#define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
-#define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16)
-#define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
+#define DMA_CHAN_CFG_DST_MODE_A31(x) (DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
#define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
@@ -98,6 +96,8 @@
#define LLI_LAST_ITEM 0xfffff800
#define NORMAL_WAIT 8
#define DRQ_SDRAM 1
+#define LINEAR_MODE 0
+#define IO_MODE 1
/* forward declaration */
struct sun6i_dma_dev;
@@ -126,6 +126,7 @@ struct sun6i_dma_config {
void (*clock_autogate_enable)(struct sun6i_dma_dev *);
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
void (*set_drq)(u32 *p_cfg, s8 src_drq, s8 dst_drq);
+ void (*set_mode)(u32 *p_cfg, s8 src_mode, s8 dst_mode);
u32 src_burst_lengths;
u32 dst_burst_lengths;
u32 src_addr_widths;
@@ -318,6 +319,12 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
}
+static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
+ DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -641,13 +648,12 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
burst = convert_burst(8);
width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
- v_lli->cfg = DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_WIDTH(width) |
+ v_lli->cfg = DMA_CHAN_CFG_SRC_WIDTH(width) |
DMA_CHAN_CFG_DST_WIDTH(width);
sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, DRQ_SDRAM);
+ sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, LINEAR_MODE);
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
@@ -699,10 +705,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
if (dir == DMA_MEM_TO_DEV) {
v_lli->src = sg_dma_address(sg);
v_lli->dst = sconfig->dst_addr;
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
+ sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -713,10 +718,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
} else {
v_lli->src = sconfig->src_addr;
v_lli->dst = sg_dma_address(sg);
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
+ sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE);
dev_dbg(chan2dev(chan),
"%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n",
@@ -782,17 +786,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
if (dir == DMA_MEM_TO_DEV) {
v_lli->src = buf_addr + period_len * i;
v_lli->dst = sconfig->dst_addr;
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_IO_MODE |
- DMA_CHAN_CFG_SRC_LINEAR_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port);
+ sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE);
} else {
v_lli->src = sconfig->src_addr;
v_lli->dst = buf_addr + period_len * i;
- v_lli->cfg = lli_cfg |
- DMA_CHAN_CFG_DST_LINEAR_MODE |
- DMA_CHAN_CFG_SRC_IO_MODE;
+ v_lli->cfg = lli_cfg;
sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM);
+ sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE);
}
prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
@@ -1058,6 +1060,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_vchans = 53,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1080,6 +1083,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1097,6 +1101,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1121,6 +1126,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1141,6 +1147,7 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
@@ -1165,6 +1172,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
.set_burst_length = sun6i_set_burst_length_a31,
.set_drq = sun6i_set_drq_a31,
+ .set_mode = sun6i_set_mode_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
--
2.20.1
^ permalink raw reply related
* [PATCH v2 6/7] arm64: dts: allwinner: h6: Add DMA node
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec, Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
From: Jernej Skrabec <jernej.skrabec@siol.net>
H6 has DMA controller which supports 16 channels.
Add a node for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 16c5c3d0fd81..f4ea596c82ce 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -208,6 +208,18 @@
reg = <0x03006000 0x400>;
};
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun50i-h6-dma";
+ reg = <0x03002000 0x1000>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ dma-channels = <16>;
+ dma-requests = <46>;
+ resets = <&ccu RST_BUS_DMA>;
+ #dma-cells = <1>;
+ };
+
pio: pinctrl@300b000 {
compatible = "allwinner,sun50i-h6-pinctrl";
reg = <0x0300b000 0x400>;
--
2.20.1
^ permalink raw reply related
* [PATCH v2 5/7] dmaengine: sun6i: Add support for H6 DMA
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Jernej Skrabec, Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
From: Jernej Skrabec <jernej.skrabec@siol.net>
H6 DMA has more than 32 supported DRQs, which means that configuration
register is slightly rearranged. It also needs additional clock to be
enabled.
Add support for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
drivers/dma/sun6i-dma.c | 44 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index f5cb5e89bf7b..8d44ddae926a 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -69,14 +69,19 @@
#define DMA_CHAN_CUR_CFG 0x0c
#define DMA_CHAN_MAX_DRQ_A31 0x1f
+#define DMA_CHAN_MAX_DRQ_H6 0x3f
#define DMA_CHAN_CFG_SRC_DRQ_A31(x) ((x) & DMA_CHAN_MAX_DRQ_A31)
+#define DMA_CHAN_CFG_SRC_DRQ_H6(x) ((x) & DMA_CHAN_MAX_DRQ_H6)
#define DMA_CHAN_CFG_SRC_MODE_A31(x) (((x) & 0x1) << 5)
+#define DMA_CHAN_CFG_SRC_MODE_H6(x) (((x) & 0x1) << 8)
#define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7)
#define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6)
#define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9)
#define DMA_CHAN_CFG_DST_DRQ_A31(x) (DMA_CHAN_CFG_SRC_DRQ_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_DRQ_H6(x) (DMA_CHAN_CFG_SRC_DRQ_H6(x) << 16)
#define DMA_CHAN_CFG_DST_MODE_A31(x) (DMA_CHAN_CFG_SRC_MODE_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_MODE_H6(x) (DMA_CHAN_CFG_SRC_MODE_H6(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
#define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
#define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
@@ -319,12 +324,24 @@ static void sun6i_set_drq_a31(u32 *p_cfg, s8 src_drq, s8 dst_drq)
DMA_CHAN_CFG_DST_DRQ_A31(dst_drq);
}
+static void sun6i_set_drq_h6(u32 *p_cfg, s8 src_drq, s8 dst_drq)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_DRQ_H6(src_drq) |
+ DMA_CHAN_CFG_DST_DRQ_H6(dst_drq);
+}
+
static void sun6i_set_mode_a31(u32 *p_cfg, s8 src_mode, s8 dst_mode)
{
*p_cfg |= DMA_CHAN_CFG_SRC_MODE_A31(src_mode) |
DMA_CHAN_CFG_DST_MODE_A31(dst_mode);
}
+static void sun6i_set_mode_h6(u32 *p_cfg, s8 src_mode, s8 dst_mode)
+{
+ *p_cfg |= DMA_CHAN_CFG_SRC_MODE_H6(src_mode) |
+ DMA_CHAN_CFG_DST_MODE_H6(dst_mode);
+}
+
static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
{
struct sun6i_desc *txd = pchan->desc;
@@ -1160,6 +1177,28 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
};
+/*
+ * The H6 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_h6_dma_cfg = {
+ .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+ .set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_h6,
+ .set_mode = sun6i_set_mode_h6,
+ .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .has_mbus_clk = true,
+};
+
/*
* The V3s have only 8 physical channels, a maximum DRQ port id of 23,
* and a total of 24 usable source and destination endpoints.
@@ -1190,6 +1229,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
+ { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun6i_dma_match);
@@ -1288,8 +1328,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
if (ret && !sdc->max_request) {
dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
- DMA_CHAN_MAX_DRQ_A31);
- sdc->max_request = DMA_CHAN_MAX_DRQ_A31;
+ DMA_CHAN_MAX_DRQ_H6);
+ sdc->max_request = DMA_CHAN_MAX_DRQ_H6;
}
/*
--
2.20.1
^ permalink raw reply related
* [PATCH v2 7/7] arm64: defconfig: enable Allwinner DMA drivers
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Clément Péron
In-Reply-To: <20190525163819.21055-1-peron.clem@gmail.com>
Allwinner sun6i DMA drivers is used on A64 and H6 boards.
Enable it as a module.
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 4d583514258c..b535f0f412cc 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -614,6 +614,7 @@ CONFIG_RTC_DRV_IMX_SC=m
CONFIG_RTC_DRV_XGENE=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=m
+CONFIG_DMA_SUN6I=m
CONFIG_K3_DMA=y
CONFIG_MV_XOR=y
CONFIG_MV_XOR_V2=y
--
2.20.1
^ permalink raw reply related
* [PATCH v2 0/7] Allwinner H6 DMA support
From: Clément Péron @ 2019-05-25 16:38 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland, Maxime Ripard,
Chen-Yu Tsai, Dan Williams
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel,
Clément Péron
Hi,
This series has been first proposed by Jernej Skrabec[1].
As this series is mandatory for SPDIF/I2S support and because he is
busy on Cedrus stuff. I asked him to make the minor change requested
and repost it.
Authorship remains to him.
I have tested this series with SPDIF driver and added a patch to enable
DMA_SUN6I_CONFIG for arm64.
Original Post:
"
DMA engine engine on H6 almost the same as on older SoCs. The biggest
difference is that it has slightly rearranged bits in registers and
it needs additional clock, probably due to iommu.
These patches were tested with I2S connected to HDMI. I2S needs
additional patches which will be sent later.
Please take a look.
Best regards,
Jernej
"
Thanks,
Clément
Changes since v1:
- Enable DMA_SUN6I in arm64 defconfig
- Change mbus_clk to has_mbus_clk
- Collect Rob H. reviewed-by
Clément Péron (1):
arm64: defconfig: enable Allwinner DMA drivers
Jernej Skrabec (6):
dt-bindings: arm64: allwinner: h6: Add binding for DMA controller
dmaengine: sun6i: Add a quirk for additional mbus clock
dmaengine: sun6i: Add a quirk for setting DRQ fields
dmaengine: sun6i: Add a quirk for setting mode fields
dmaengine: sun6i: Add support for H6 DMA
arm64: dts: allwinner: h6: Add DMA node
.../devicetree/bindings/dma/sun6i-dma.txt | 9 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 12 ++
arch/arm64/configs/defconfig | 1 +
drivers/dma/sun6i-dma.c | 147 +++++++++++++-----
4 files changed, 132 insertions(+), 37 deletions(-)
--
2.20.1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox