* [2/7] dmaengine: fsldma: Adding macro FSL_DMA_IN/OUT implement for ARM platform
From: Peng Ma @ 2018-10-26 9:52 UTC (permalink / raw)
To: vkoul
Cc: robh+dt, mark.rutland, shawnguo, leoyang.li, dan.j.williams, zw,
dmaengine, devicetree, linux-kernel, linux-arm-kernel,
linuxppc-dev, Peng Ma, Wen He
This patch add the macro FSL_DMA_IN/OUT implement for ARM platform.
Signed-off-by: Wen He <wen.he_1@nxp.com>
Signed-off-by: Peng Ma <peng.ma@nxp.com>
---
change in v10:
- fixed compile warning on powerpc
drivers/dma/fsldma.h | 61 ++++++++++++++++++++++++++++++++++---------------
1 files changed, 42 insertions(+), 19 deletions(-)
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 982845b..88db939 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -196,39 +196,62 @@ struct fsldma_chan {
#define to_fsl_desc(lh) container_of(lh, struct fsl_desc_sw, node)
#define tx_to_fsl_desc(tx) container_of(tx, struct fsl_desc_sw, async_tx)
+#ifdef CONFIG_PPC
+#define fsl_ioread32(p) in_le32(p)
+#define fsl_ioread32be(p) in_be32(p)
+#define fsl_iowrite32(v, p) out_le32(p, v)
+#define fsl_iowrite32be(v, p) out_be32(p, v)
+
#ifndef __powerpc64__
-static u64 in_be64(const u64 __iomem *addr)
+static u64 fsl_ioread64(const u64 __iomem *addr)
{
- return ((u64)in_be32((u32 __iomem *)addr) << 32) |
- (in_be32((u32 __iomem *)addr + 1));
+ u32 fsl_addr = lower_32_bits(addr);
+ u64 fsl_addr_hi = (u64)in_le32((u32 *)(fsl_addr + 1)) << 32;
+
+ return fsl_addr_hi | in_le32((u32 *)fsl_addr);
}
-static void out_be64(u64 __iomem *addr, u64 val)
+static void fsl_iowrite64(u64 val, u64 __iomem *addr)
{
- out_be32((u32 __iomem *)addr, val >> 32);
- out_be32((u32 __iomem *)addr + 1, (u32)val);
+ out_le32((u32 __iomem *)addr + 1, val >> 32);
+ out_le32((u32 __iomem *)addr, (u32)val);
}
-/* There is no asm instructions for 64 bits reverse loads and stores */
-static u64 in_le64(const u64 __iomem *addr)
+static u64 fsl_ioread64be(const u64 __iomem *addr)
{
- return ((u64)in_le32((u32 __iomem *)addr + 1) << 32) |
- (in_le32((u32 __iomem *)addr));
+ u32 fsl_addr = lower_32_bits(addr);
+ u64 fsl_addr_hi = (u64)in_be32((u32 *)fsl_addr) << 32;
+
+ return fsl_addr_hi | in_be32((u32 *)(fsl_addr + 1));
}
-static void out_le64(u64 __iomem *addr, u64 val)
+static void fsl_iowrite64be(u64 val, u64 __iomem *addr)
{
- out_le32((u32 __iomem *)addr + 1, val >> 32);
- out_le32((u32 __iomem *)addr, (u32)val);
+ out_be32((u32 __iomem *)addr, val >> 32);
+ out_be32((u32 __iomem *)addr + 1, (u32)val);
}
#endif
+#endif
-#define FSL_DMA_IN(fsl_chan, addr, width) \
- (((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ? \
- in_be##width(addr) : in_le##width(addr))
-#define FSL_DMA_OUT(fsl_chan, addr, val, width) \
- (((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ? \
- out_be##width(addr, val) : out_le##width(addr, val))
+#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
+#define fsl_ioread32(p) ioread32(p)
+#define fsl_ioread32be(p) ioread32be(p)
+#define fsl_iowrite32(v, p) iowrite32(v, p)
+#define fsl_iowrite32be(v, p) iowrite32be(v, p)
+#define fsl_ioread64(p) ioread64(p)
+#define fsl_ioread64be(p) ioread64be(p)
+#define fsl_iowrite64(v, p) iowrite64(v, p)
+#define fsl_iowrite64be(v, p) iowrite64be(v, p)
+#endif
+
+#define FSL_DMA_IN(fsl_dma, addr, width) \
+ (((fsl_dma)->feature & FSL_DMA_BIG_ENDIAN) ? \
+ fsl_ioread##width##be(addr) : fsl_ioread##width(addr))
+
+#define FSL_DMA_OUT(fsl_dma, addr, val, width) \
+ (((fsl_dma)->feature & FSL_DMA_BIG_ENDIAN) ? \
+ fsl_iowrite##width##be(val, addr) : fsl_iowrite \
+ ##width(val, addr))
#define DMA_TO_CPU(fsl_chan, d, width) \
(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ? \
^ permalink raw reply related
* [1/7] dmaengine: fsldma: Replace DMA_IN/OUT by FSL_DMA_IN/OUT
From: Peng Ma @ 2018-10-26 9:52 UTC (permalink / raw)
To: vkoul
Cc: robh+dt, mark.rutland, shawnguo, leoyang.li, dan.j.williams, zw,
dmaengine, devicetree, linux-kernel, linux-arm-kernel,
linuxppc-dev, Wen He, Peng Ma
From: Wen He <wen.he_1@nxp.com>
This patch implement a standard macro call functions is
used to NXP dma drivers.
Signed-off-by: Wen He <wen.he_1@nxp.com>
Signed-off-by: Peng Ma <peng.ma@nxp.com>
---
change in v10:
- no
drivers/dma/fsldma.c | 16 ++++++++--------
drivers/dma/fsldma.h | 4 ++--
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 1117b51..39871e0 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -53,42 +53,42 @@
static void set_sr(struct fsldma_chan *chan, u32 val)
{
- DMA_OUT(chan, &chan->regs->sr, val, 32);
+ FSL_DMA_OUT(chan, &chan->regs->sr, val, 32);
}
static u32 get_sr(struct fsldma_chan *chan)
{
- return DMA_IN(chan, &chan->regs->sr, 32);
+ return FSL_DMA_IN(chan, &chan->regs->sr, 32);
}
static void set_mr(struct fsldma_chan *chan, u32 val)
{
- DMA_OUT(chan, &chan->regs->mr, val, 32);
+ FSL_DMA_OUT(chan, &chan->regs->mr, val, 32);
}
static u32 get_mr(struct fsldma_chan *chan)
{
- return DMA_IN(chan, &chan->regs->mr, 32);
+ return FSL_DMA_IN(chan, &chan->regs->mr, 32);
}
static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
{
- DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+ FSL_DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
}
static dma_addr_t get_cdar(struct fsldma_chan *chan)
{
- return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+ return FSL_DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
}
static void set_bcr(struct fsldma_chan *chan, u32 val)
{
- DMA_OUT(chan, &chan->regs->bcr, val, 32);
+ FSL_DMA_OUT(chan, &chan->regs->bcr, val, 32);
}
static u32 get_bcr(struct fsldma_chan *chan)
{
- return DMA_IN(chan, &chan->regs->bcr, 32);
+ return FSL_DMA_IN(chan, &chan->regs->bcr, 32);
}
/*
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 4787d48..982845b 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -223,10 +223,10 @@ static void out_le64(u64 __iomem *addr, u64 val)
}
#endif
-#define DMA_IN(fsl_chan, addr, width) \
+#define FSL_DMA_IN(fsl_chan, addr, width) \
(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ? \
in_be##width(addr) : in_le##width(addr))
-#define DMA_OUT(fsl_chan, addr, val, width) \
+#define FSL_DMA_OUT(fsl_chan, addr, val, width) \
(((fsl_chan)->feature & FSL_DMA_BIG_ENDIAN) ? \
out_be##width(addr, val) : out_le##width(addr, val))
^ permalink raw reply related
* [1/2] dt-bindings: dmaengine: usb-dmac: Add binding for r8a77470
From: Fabrizio Castro @ 2018-10-26 9:46 UTC (permalink / raw)
To: Biju Das, Vinod Koul, Rob Herring, Mark Rutland
Cc: dmaengine@vger.kernel.org, devicetree@vger.kernel.org,
Simon Horman, Geert Uytterhoeven, Chris Paterson,
linux-renesas-soc@vger.kernel.org
> Subject: [PATCH 1/2] dt-bindings: dmaengine: usb-dmac: Add binding for r8a77470
>
> This patch adds usb high-speed dmac binding for r8a77470 (RZ/G1C) SoC.
>
> Signed-off-by: Biju Das <biju.das@bp.renesas.com>
Reviewed-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
> ---
> This patch tested against linux-next.
> ---
> Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> index 1743017..a1e7b814 100644
> --- a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> +++ b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> @@ -6,6 +6,7 @@ Required Properties:
> - "renesas,r8a7743-usb-dmac" (RZ/G1M)
> - "renesas,r8a7744-usb-dmac" (RZ/G1N)
> - "renesas,r8a7745-usb-dmac" (RZ/G1E)
> + - "renesas,r8a77470-usb-dmac" (RZ/G1C)
> - "renesas,r8a7790-usb-dmac" (R-Car H2)
> - "renesas,r8a7791-usb-dmac" (R-Car M2-W)
> - "renesas,r8a7793-usb-dmac" (R-Car M2-N)
> --
> 2.7.4
Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered No. 04586709.
^ permalink raw reply
* [[PATCH] 8/9] DMA-UART-Driver-for-AST2500
From: sudheer.v @ 2018-10-26 7:07 UTC (permalink / raw)
To: Vinod
Cc: Benjamin Herrenschmidt, Rob Herring, Mark Rutland,
Greg Kroah-Hartman, Joel Stanley, Andrew Jeffery, Russell King,
Dan Williams, Jiri Slaby, Thomas Gleixner, Marc Zyngier,
Christian Borntraeger, Michael Moese, Hendrik Brueckner,
Kate Stewart, Philippe Ombredanne, dmaengine, devicetree,
linux-kernel, linux-serial, linux-arm-kernel, linux-aspeed,
Sudheer V, ShivahShankar Shakarnarayan rao
On Sat, Oct 20, 2018 at 09:56:24PM +0530, Vinod wrote:
> On 19-10-18, 12:41, sudheer.v wrote:
> > On Fri, Oct 19, 2018 at 10:32:24AM +1100, Benjamin Herrenschmidt wrote:
> > > On Thu, 2018-10-18 at 15:25 +0530, Vinod wrote:
> > > >
> > > > > It's not a dmaengine driver. It's a serial UART driver that happens to
> > > > > use a dedicated DMA engine.
> > > >
> > > > Then I see no reason for it to use dmaengine APIs. The framework allows
> > > > people to share a controller for many clients, but if you have dedicated
> > > > one then you may use it directly
> > >
> > > Well... the engine is shared by a few UARTs, they have dedicated rings
> > > but there's a common set of regs for interrupt handling etc.
> > >
> > > That said, I still think it could be contained within a UART driver,
> > > there's little benefit in adding the framework overhead, esp since
> > > these are really weak cores, any overhead will be felt.
> > >
> > > Ben.
> > >
> > > > > It's unclear whether it should be split into two drivers, or just have
> > > > > the serial driver directly use the dma engine since that engine is
> > > > > dedicated in HW to only work on those UARTs and nothing else...
> > > > >
> > > > > Cheers,
> > > > > Ben.
> >
> > Initially we wanted to have a single driver,
> > however we had an informal discussion with one of the maintainer
> > and based on the feedback, followed the Linux DMA and UART architecture.
> >
> > If this seperate DMA-engine driver adds more overhead than benifit,
> > we will merge them into a single UART driver and resubmitt the patches.
> > Vinod,
> > can this dma-controller driver sit under dma subsystem?.
> > or better to move it under UART framework.
>
>
> My advise would be to see what you can do with the DMA IP block. If this
> can/would be used in different places then it would make sense to do a
> dmaengine driver and solve the problem for everyone.
>
> If this is always going to be hidden behind serial then maybe it makes
> sense to be inside serial driver and not use dmaengine APIs
>
> If you decide to prefer the former case, please move it to dmaengine and
> resubmit :)
>
> HTH
> --
> ~Vinod
Hi All,
As the DMA engine is dedicated only to UART,we have decided
to rewrite the driver so that no code will come under
drivers/dma.
I will resubmitt the patches after merging dma controller
code and uart driver code.
Regards
-sudheer
^ permalink raw reply
* dmaengine: xilinx_dma: Remove __aligned attribute on zynqmp_dma_desc_ll
From: Nick Desaulniers @ 2018-10-25 18:18 UTC (permalink / raw)
To: Nathan Chancellor
Cc: vkoul, dan.j.williams, michal.simek, dmaengine, Linux ARM, LKML
On Thu, Oct 25, 2018 at 11:14 AM Nathan Chancellor
<natechancellor@gmail.com> wrote:
>
> On Thu, Oct 25, 2018 at 11:11:22AM -0700, Nick Desaulniers wrote:
> > On Thu, Oct 25, 2018 at 11:06 AM Nathan Chancellor
> > <natechancellor@gmail.com> wrote:
> > >
> > > Clang warns:
> > >
> > > drivers/dma/xilinx/zynqmp_dma.c:166:4: warning: attribute 'aligned' is
> > > ignored, place it after "struct" to apply attribute to type declaration
> > > [-Wignored-attributes]
> > > }; __aligned(64)
> > > ^
> > > ./include/linux/compiler_types.h:200:38: note: expanded from macro
> > > '__aligned'
> > > #define __aligned(x) __attribute__((aligned(x)))
> > > ^
> > > 1 warning generated.
> > >
> > > As Nick pointed out in the previous version of this patch, the author
> > > likely intended for this struct to be 8-byte (64-bit) aligned, not
> > > 64-byte, which is the default. Remove the hanging __aligned attribute.
> >
> > Here was the v1 discussion, for reference.
> > https://lkml.org/lkml/2018/9/12/4
> >
> > Thanks for sending the update Nathan. One thing I recommend doing is
> > including the version in the [PATCH] subject line, ie. [PATCH v2].
> > `git format-patch` can do this automatically for you, ex.
> > $ git format-patch -v2 HEAD~
> >
> > >
> > > Fixes: b0cc417c1637 ("dmaengine: Add Xilinx zynqmp dma engine driver support")
> > > Reported-by: Nick Desaulniers <ndesaulniers@google.com>
> > > Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
> > > Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> > > ---
> >
> > Then below this line, you can include the notes about v1 -> v2
> > changes. (interdiff notes to the reviewers that get discarded from the
> > commit message). I think I've seen you use the versioning before, so
> > sorry if I'm restating something you already know.
> >
>
> No, that's fine, I completely forgot all the versioning for this patch
> as I was rushing, sorry about that!
No worries. There's a lot to juggle when sending a patch and I miss
these all the time (did I run checkpatch, did I cc the folks added to
v1 that get_maintainer did not suggest, did I ...) and the version
info of the patch gets discarded anyways once committed.
>
> > Thanks for the patch.
> > Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> >
>
> Thanks for the review!
> Nathan
>
> > > drivers/dma/xilinx/zynqmp_dma.c | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
> > > index c74a88b65039..73de6a6179fc 100644
> > > --- a/drivers/dma/xilinx/zynqmp_dma.c
> > > +++ b/drivers/dma/xilinx/zynqmp_dma.c
> > > @@ -163,7 +163,7 @@ struct zynqmp_dma_desc_ll {
> > > u32 ctrl;
> > > u64 nxtdscraddr;
> > > u64 rsvd;
> > > -}; __aligned(64)
> > > +};
> > >
> > > /**
> > > * struct zynqmp_dma_desc_sw - Per Transaction structure
> > > --
> > > 2.19.1
> > >
> >
> >
> > --
> > Thanks,
> > ~Nick Desaulniers
^ permalink raw reply
* dmaengine: xilinx_dma: Remove __aligned attribute on zynqmp_dma_desc_ll
From: Nathan Chancellor @ 2018-10-25 18:14 UTC (permalink / raw)
To: Nick Desaulniers
Cc: vkoul, dan.j.williams, michal.simek, dmaengine, Linux ARM, LKML
On Thu, Oct 25, 2018 at 11:11:22AM -0700, Nick Desaulniers wrote:
> On Thu, Oct 25, 2018 at 11:06 AM Nathan Chancellor
> <natechancellor@gmail.com> wrote:
> >
> > Clang warns:
> >
> > drivers/dma/xilinx/zynqmp_dma.c:166:4: warning: attribute 'aligned' is
> > ignored, place it after "struct" to apply attribute to type declaration
> > [-Wignored-attributes]
> > }; __aligned(64)
> > ^
> > ./include/linux/compiler_types.h:200:38: note: expanded from macro
> > '__aligned'
> > #define __aligned(x) __attribute__((aligned(x)))
> > ^
> > 1 warning generated.
> >
> > As Nick pointed out in the previous version of this patch, the author
> > likely intended for this struct to be 8-byte (64-bit) aligned, not
> > 64-byte, which is the default. Remove the hanging __aligned attribute.
>
> Here was the v1 discussion, for reference.
> https://lkml.org/lkml/2018/9/12/4
>
> Thanks for sending the update Nathan. One thing I recommend doing is
> including the version in the [PATCH] subject line, ie. [PATCH v2].
> `git format-patch` can do this automatically for you, ex.
> $ git format-patch -v2 HEAD~
>
> >
> > Fixes: b0cc417c1637 ("dmaengine: Add Xilinx zynqmp dma engine driver support")
> > Reported-by: Nick Desaulniers <ndesaulniers@google.com>
> > Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
> > Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> > ---
>
> Then below this line, you can include the notes about v1 -> v2
> changes. (interdiff notes to the reviewers that get discarded from the
> commit message). I think I've seen you use the versioning before, so
> sorry if I'm restating something you already know.
>
No, that's fine, I completely forgot all the versioning for this patch
as I was rushing, sorry about that!
> Thanks for the patch.
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
>
Thanks for the review!
Nathan
> > drivers/dma/xilinx/zynqmp_dma.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
> > index c74a88b65039..73de6a6179fc 100644
> > --- a/drivers/dma/xilinx/zynqmp_dma.c
> > +++ b/drivers/dma/xilinx/zynqmp_dma.c
> > @@ -163,7 +163,7 @@ struct zynqmp_dma_desc_ll {
> > u32 ctrl;
> > u64 nxtdscraddr;
> > u64 rsvd;
> > -}; __aligned(64)
> > +};
> >
> > /**
> > * struct zynqmp_dma_desc_sw - Per Transaction structure
> > --
> > 2.19.1
> >
>
>
> --
> Thanks,
> ~Nick Desaulniers
^ permalink raw reply
* dmaengine: xilinx_dma: Remove __aligned attribute on zynqmp_dma_desc_ll
From: Nick Desaulniers @ 2018-10-25 18:11 UTC (permalink / raw)
To: Nathan Chancellor
Cc: vkoul, dan.j.williams, michal.simek, dmaengine, Linux ARM, LKML
On Thu, Oct 25, 2018 at 11:06 AM Nathan Chancellor
<natechancellor@gmail.com> wrote:
>
> Clang warns:
>
> drivers/dma/xilinx/zynqmp_dma.c:166:4: warning: attribute 'aligned' is
> ignored, place it after "struct" to apply attribute to type declaration
> [-Wignored-attributes]
> }; __aligned(64)
> ^
> ./include/linux/compiler_types.h:200:38: note: expanded from macro
> '__aligned'
> #define __aligned(x) __attribute__((aligned(x)))
> ^
> 1 warning generated.
>
> As Nick pointed out in the previous version of this patch, the author
> likely intended for this struct to be 8-byte (64-bit) aligned, not
> 64-byte, which is the default. Remove the hanging __aligned attribute.
Here was the v1 discussion, for reference.
https://lkml.org/lkml/2018/9/12/4
Thanks for sending the update Nathan. One thing I recommend doing is
including the version in the [PATCH] subject line, ie. [PATCH v2].
`git format-patch` can do this automatically for you, ex.
$ git format-patch -v2 HEAD~
>
> Fixes: b0cc417c1637 ("dmaengine: Add Xilinx zynqmp dma engine driver support")
> Reported-by: Nick Desaulniers <ndesaulniers@google.com>
> Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
> Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
> ---
Then below this line, you can include the notes about v1 -> v2
changes. (interdiff notes to the reviewers that get discarded from the
commit message). I think I've seen you use the versioning before, so
sorry if I'm restating something you already know.
Thanks for the patch.
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> drivers/dma/xilinx/zynqmp_dma.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
> index c74a88b65039..73de6a6179fc 100644
> --- a/drivers/dma/xilinx/zynqmp_dma.c
> +++ b/drivers/dma/xilinx/zynqmp_dma.c
> @@ -163,7 +163,7 @@ struct zynqmp_dma_desc_ll {
> u32 ctrl;
> u64 nxtdscraddr;
> u64 rsvd;
> -}; __aligned(64)
> +};
>
> /**
> * struct zynqmp_dma_desc_sw - Per Transaction structure
> --
> 2.19.1
>
^ permalink raw reply
* dmaengine: xilinx_dma: Remove __aligned attribute on zynqmp_dma_desc_ll
From: Nathan Chancellor @ 2018-10-25 18:05 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Michal Simek, dmaengine, linux-arm-kernel,
linux-kernel, Nick Desaulniers, Nathan Chancellor
Clang warns:
drivers/dma/xilinx/zynqmp_dma.c:166:4: warning: attribute 'aligned' is
ignored, place it after "struct" to apply attribute to type declaration
[-Wignored-attributes]
}; __aligned(64)
^
./include/linux/compiler_types.h:200:38: note: expanded from macro
'__aligned'
#define __aligned(x) __attribute__((aligned(x)))
^
1 warning generated.
As Nick pointed out in the previous version of this patch, the author
likely intended for this struct to be 8-byte (64-bit) aligned, not
64-byte, which is the default. Remove the hanging __aligned attribute.
Fixes: b0cc417c1637 ("dmaengine: Add Xilinx zynqmp dma engine driver support")
Reported-by: Nick Desaulniers <ndesaulniers@google.com>
Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
---
drivers/dma/xilinx/zynqmp_dma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index c74a88b65039..73de6a6179fc 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -163,7 +163,7 @@ struct zynqmp_dma_desc_ll {
u32 ctrl;
u64 nxtdscraddr;
u64 rsvd;
-}; __aligned(64)
+};
/**
* struct zynqmp_dma_desc_sw - Per Transaction structure
^ permalink raw reply related
* dmaengine: imx-sdma: Use a single line for dma_alloc_coherent()
From: Fabio Estevam @ 2018-10-25 17:52 UTC (permalink / raw)
To: vkoul; +Cc: dmaengine, Fabio Estevam
Make the call to dma_alloc_coherent() to fit into a single line, which
helps readability.
Signed-off-by: Fabio Estevam <festevam@gmail.com>
---
drivers/dma/imx-sdma.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index b4ec2d2..a2b488d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -671,9 +671,7 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
int ret;
unsigned long flags;
- buf_virt = dma_alloc_coherent(NULL,
- size,
- &buf_phys, GFP_KERNEL);
+ buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL);
if (!buf_virt) {
return -ENOMEM;
}
^ permalink raw reply related
* [1/2] dt-bindings: dmaengine: usb-dmac: Add binding for r8a77470
From: Biju Das @ 2018-10-25 16:22 UTC (permalink / raw)
To: Vinod
Cc: Rob Herring, Mark Rutland, dmaengine@vger.kernel.org,
devicetree@vger.kernel.org, Simon Horman, Geert Uytterhoeven,
Chris Paterson, Fabrizio Castro,
linux-renesas-soc@vger.kernel.org
Hi Vinod,
Thanks for the feedback.
> Subject: Re: [PATCH 1/2] dt-bindings: dmaengine: usb-dmac: Add binding for
> r8a77470
>
> On 25-10-18, 15:53, Biju Das wrote:
> > This patch adds usb high-speed dmac binding for r8a77470 (RZ/G1C) SoC.
>
> Where is the patch 2/2 ...?
I missed adding you in the second patch. Just now I have added you in CC.
Regards,
Biju
Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered No. 04586709.
^ permalink raw reply
* [1/2] dt-bindings: dmaengine: usb-dmac: Add binding for r8a77470
From: Vinod Koul @ 2018-10-25 15:57 UTC (permalink / raw)
To: Biju Das
Cc: Rob Herring, Mark Rutland, dmaengine, devicetree, Simon Horman,
Geert Uytterhoeven, Chris Paterson, Fabrizio Castro,
linux-renesas-soc
On 25-10-18, 15:53, Biju Das wrote:
> This patch adds usb high-speed dmac binding for r8a77470 (RZ/G1C) SoC.
Where is the patch 2/2 ...?
> Signed-off-by: Biju Das <biju.das@bp.renesas.com>
> ---
> This patch tested against linux-next.
> ---
> Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> index 1743017..a1e7b814 100644
> --- a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> +++ b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
> @@ -6,6 +6,7 @@ Required Properties:
> - "renesas,r8a7743-usb-dmac" (RZ/G1M)
> - "renesas,r8a7744-usb-dmac" (RZ/G1N)
> - "renesas,r8a7745-usb-dmac" (RZ/G1E)
> + - "renesas,r8a77470-usb-dmac" (RZ/G1C)
> - "renesas,r8a7790-usb-dmac" (R-Car H2)
> - "renesas,r8a7791-usb-dmac" (R-Car M2-W)
> - "renesas,r8a7793-usb-dmac" (R-Car M2-N)
> --
> 2.7.4
^ permalink raw reply
* [1/2] dt-bindings: dmaengine: usb-dmac: Add binding for r8a77470
From: Biju Das @ 2018-10-25 14:53 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Mark Rutland
Cc: Biju Das, dmaengine, devicetree, Simon Horman, Geert Uytterhoeven,
Chris Paterson, Fabrizio Castro, linux-renesas-soc
This patch adds usb high-speed dmac binding for r8a77470 (RZ/G1C) SoC.
Signed-off-by: Biju Das <biju.das@bp.renesas.com>
---
This patch tested against linux-next.
---
Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
index 1743017..a1e7b814 100644
--- a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
+++ b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
@@ -6,6 +6,7 @@ Required Properties:
- "renesas,r8a7743-usb-dmac" (RZ/G1M)
- "renesas,r8a7744-usb-dmac" (RZ/G1N)
- "renesas,r8a7745-usb-dmac" (RZ/G1E)
+ - "renesas,r8a77470-usb-dmac" (RZ/G1C)
- "renesas,r8a7790-usb-dmac" (R-Car H2)
- "renesas,r8a7791-usb-dmac" (R-Car M2-W)
- "renesas,r8a7793-usb-dmac" (R-Car M2-N)
^ permalink raw reply related
* [1/3] clk: bcm2835: make license text and module license match
From: Eric Anholt @ 2018-10-23 18:31 UTC (permalink / raw)
To: Stefan Wahren, Florian Meier, Chris Boot, Martin Sperl
Cc: Michael Turquette, Stephen Boyd, Mark Brown, Vinod Koul,
linux-clk, dmaengine, linux-spi, linux-arm-kernel
Stefan Wahren <stefan.wahren@i2se.com> writes:
> The license text is specifying GPL v2 or later but the MODULE_LICENSE
> is set to GPL v2 which means GNU Public License v2 only. So choose the
> license text as the correct one.
>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
For the series:
Reviewed-by: Eric Anholt <eric@anholt.net>
^ permalink raw reply
* [3/3] spi: bcm2835: make license text and module license match
From: Stefan Wahren @ 2018-10-23 11:06 UTC (permalink / raw)
To: Florian Meier, Chris Boot, Martin Sperl, Eric Anholt
Cc: Michael Turquette, Stephen Boyd, Mark Brown, Vinod Koul,
linux-clk, dmaengine, linux-spi, linux-arm-kernel, Stefan Wahren
The license text is specifying GPL v2 or later but the MODULE_LICENSE
is set to GPL v2 which means GNU Public License v2 only. So choose the
license text as the correct one.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
drivers/spi/spi-bcm2835.c | 2 +-
drivers/spi/spi-bcm2835aux.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index f35cc10..b0b87ff 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -843,4 +843,4 @@ module_platform_driver(bcm2835_spi_driver);
MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835");
MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
index 3094d81..671e374 100644
--- a/drivers/spi/spi-bcm2835aux.c
+++ b/drivers/spi/spi-bcm2835aux.c
@@ -542,4 +542,4 @@ module_platform_driver(bcm2835aux_spi_driver);
MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux");
MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
^ permalink raw reply related
* [2/3] dma: bcm2835: make license text and module license match
From: Stefan Wahren @ 2018-10-23 11:06 UTC (permalink / raw)
To: Florian Meier, Chris Boot, Martin Sperl, Eric Anholt
Cc: Michael Turquette, Stephen Boyd, Mark Brown, Vinod Koul,
linux-clk, dmaengine, linux-spi, linux-arm-kernel, Stefan Wahren
The license text is specifying GPL v2 or later but the MODULE_LICENSE
is set to GPL v2 which means GNU Public License v2 only. So choose the
license text as the correct one.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
drivers/dma/bcm2835-dma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 847f84a..112b071 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -1064,4 +1064,4 @@ module_platform_driver(bcm2835_dma_driver);
MODULE_ALIAS("platform:bcm2835-dma");
MODULE_DESCRIPTION("BCM2835 DMA engine driver");
MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
^ permalink raw reply related
* [1/3] clk: bcm2835: make license text and module license match
From: Stefan Wahren @ 2018-10-23 11:06 UTC (permalink / raw)
To: Florian Meier, Chris Boot, Martin Sperl, Eric Anholt
Cc: Michael Turquette, Stephen Boyd, Mark Brown, Vinod Koul,
linux-clk, dmaengine, linux-spi, linux-arm-kernel, Stefan Wahren
The license text is specifying GPL v2 or later but the MODULE_LICENSE
is set to GPL v2 which means GNU Public License v2 only. So choose the
license text as the correct one.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
drivers/clk/bcm/clk-bcm2835-aux.c | 2 +-
drivers/clk/bcm/clk-bcm2835.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c
index f225ad2..e01d557 100644
--- a/drivers/clk/bcm/clk-bcm2835-aux.c
+++ b/drivers/clk/bcm/clk-bcm2835-aux.c
@@ -79,4 +79,4 @@ builtin_platform_driver(bcm2835_aux_clk_driver);
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 7bef066..6b6d836 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2206,4 +2206,4 @@ builtin_platform_driver(bcm2835_clk_driver);
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
MODULE_DESCRIPTION("BCM2835 clock driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
^ permalink raw reply related
* [v9,2/7] dmaengine: fsldma: Adding macro FSL_DMA_IN/OUT implement for ARM platform
From: kbuild test robot @ 2018-10-22 17:14 UTC (permalink / raw)
To: Peng Ma
Cc: kbuild-all, vkoul, robh+dt, mark.rutland, shawnguo, leoyang.li,
dan.j.williams, zw, dmaengine, devicetree, linux-kernel,
linux-arm-kernel, linuxppc-dev, Wen He
Hi Peng,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linux-sof-driver/master]
[also build test WARNING on v4.19 next-20181019]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Peng-Ma/dmaengine-fsldma-Replace-DMA_IN-OUT-by-FSL_DMA_IN-OUT/20181017-232444
base: https://github.com/thesofproject/linux master
config: powerpc-xes_mpc85xx_defconfig (attached as .config)
compiler: powerpc-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=powerpc
All warnings (new ones prefixed by >>):
In file included from drivers/dma/fsldma.c:41:0:
drivers/dma/fsldma.h: In function 'fsl_ioread64':
>> drivers/dma/fsldma.h:210:17: warning: passing argument 1 of 'in_le32' makes pointer from integer without a cast [-Wint-conversion]
return in_le32(fsl_addr) | in_le32(fsl_addr + 1) << 32;
^~~~~~~~
In file included from include/linux/io.h:25:0,
from include/linux/irq.h:20,
from arch/powerpc/include/asm/hardirq.h:6,
from include/linux/hardirq.h:9,
from include/linux/interrupt.h:11,
from include/linux/pci.h:32,
from drivers/dma/fsldma.c:29:
arch/powerpc/include/asm/io.h:172:15: note: expected 'const volatile u32 * {aka const volatile unsigned int *}' but argument is of type 'u32 {aka unsigned int}'
DEF_MMIO_IN_X(in_le32, 32, lwbrx);
^
arch/powerpc/include/asm/io.h:131:23: note: in definition of macro 'DEF_MMIO_IN_X'
static inline u##size name(const volatile u##size __iomem *addr) \
^~~~
In file included from drivers/dma/fsldma.c:41:0:
drivers/dma/fsldma.h:210:37: warning: passing argument 1 of 'in_le32' makes pointer from integer without a cast [-Wint-conversion]
return in_le32(fsl_addr) | in_le32(fsl_addr + 1) << 32;
^~~~~~~~
In file included from include/linux/io.h:25:0,
from include/linux/irq.h:20,
from arch/powerpc/include/asm/hardirq.h:6,
from include/linux/hardirq.h:9,
from include/linux/interrupt.h:11,
from include/linux/pci.h:32,
from drivers/dma/fsldma.c:29:
arch/powerpc/include/asm/io.h:172:15: note: expected 'const volatile u32 * {aka const volatile unsigned int *}' but argument is of type 'u32 {aka unsigned int}'
DEF_MMIO_IN_X(in_le32, 32, lwbrx);
^
arch/powerpc/include/asm/io.h:131:23: note: in definition of macro 'DEF_MMIO_IN_X'
static inline u##size name(const volatile u##size __iomem *addr) \
^~~~
In file included from drivers/dma/fsldma.c:41:0:
>> drivers/dma/fsldma.h:210:51: warning: left shift count >= width of type [-Wshift-count-overflow]
return in_le32(fsl_addr) | in_le32(fsl_addr + 1) << 32;
^~
drivers/dma/fsldma.h: In function 'fsl_ioread64be':
>> drivers/dma/fsldma.h:223:17: warning: passing argument 1 of 'in_be32' makes pointer from integer without a cast [-Wint-conversion]
return in_be32(fsl_addr + 1) | in_be32(fsl_addr) << 32;
^~~~~~~~
In file included from include/linux/io.h:25:0,
from include/linux/irq.h:20,
from arch/powerpc/include/asm/hardirq.h:6,
from include/linux/hardirq.h:9,
from include/linux/interrupt.h:11,
from include/linux/pci.h:32,
from drivers/dma/fsldma.c:29:
arch/powerpc/include/asm/io.h:170:15: note: expected 'const volatile u32 * {aka const volatile unsigned int *}' but argument is of type 'u32 {aka unsigned int}'
DEF_MMIO_IN_D(in_be32, 32, lwz);
^
arch/powerpc/include/asm/io.h:149:23: note: in definition of macro 'DEF_MMIO_IN_D'
static inline u##size name(const volatile u##size __iomem *addr) \
^~~~
In file included from drivers/dma/fsldma.c:41:0:
drivers/dma/fsldma.h:223:41: warning: passing argument 1 of 'in_be32' makes pointer from integer without a cast [-Wint-conversion]
return in_be32(fsl_addr + 1) | in_be32(fsl_addr) << 32;
^~~~~~~~
In file included from include/linux/io.h:25:0,
from include/linux/irq.h:20,
from arch/powerpc/include/asm/hardirq.h:6,
from include/linux/hardirq.h:9,
from include/linux/interrupt.h:11,
from include/linux/pci.h:32,
from drivers/dma/fsldma.c:29:
arch/powerpc/include/asm/io.h:170:15: note: expected 'const volatile u32 * {aka const volatile unsigned int *}' but argument is of type 'u32 {aka unsigned int}'
DEF_MMIO_IN_D(in_be32, 32, lwz);
^
arch/powerpc/include/asm/io.h:149:23: note: in definition of macro 'DEF_MMIO_IN_D'
static inline u##size name(const volatile u##size __iomem *addr) \
^~~~
In file included from drivers/dma/fsldma.c:41:0:
drivers/dma/fsldma.h:223:51: warning: left shift count >= width of type [-Wshift-count-overflow]
return in_be32(fsl_addr + 1) | in_be32(fsl_addr) << 32;
^~
vim +/in_le32 +210 drivers/dma/fsldma.h
204
205 #ifndef __powerpc64__
206 static u64 fsl_ioread64(const u64 __iomem *addr)
207 {
208 u32 fsl_addr = lower_32_bits(addr);
209
> 210 return in_le32(fsl_addr) | in_le32(fsl_addr + 1) << 32;
211 }
212
213 static void fsl_iowrite64(u64 val, u64 __iomem *addr)
214 {
215 out_le32((u32 __iomem *)addr + 1, val >> 32);
216 out_le32((u32 __iomem *)addr, (u32)val);
217 }
218
219 static u64 fsl_ioread64be(const u64 __iomem *addr)
220 {
221 u32 fsl_addr = lower_32_bits(addr);
222
> 223 return in_be32(fsl_addr + 1) | in_be32(fsl_addr) << 32;
224 }
225
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* [[PATCH] 8/9] DMA-UART-Driver-for-AST2500
From: Vinod Koul @ 2018-10-20 16:26 UTC (permalink / raw)
To: sudheer.v
Cc: Benjamin Herrenschmidt, Rob Herring, Mark Rutland,
Greg Kroah-Hartman, Joel Stanley, Andrew Jeffery, Russell King,
Dan Williams, Jiri Slaby, Thomas Gleixner, Marc Zyngier,
Christian Borntraeger, Michael Moese, Hendrik Brueckner,
Kate Stewart, Philippe Ombredanne, dmaengine, devicetree,
linux-kernel, linux-serial, linux-arm-kernel, linux-aspeed,
Sudheer V, ShivahShankar Shakarnarayan rao
On 19-10-18, 12:41, sudheer.v wrote:
> On Fri, Oct 19, 2018 at 10:32:24AM +1100, Benjamin Herrenschmidt wrote:
> > On Thu, 2018-10-18 at 15:25 +0530, Vinod wrote:
> > >
> > > > It's not a dmaengine driver. It's a serial UART driver that happens to
> > > > use a dedicated DMA engine.
> > >
> > > Then I see no reason for it to use dmaengine APIs. The framework allows
> > > people to share a controller for many clients, but if you have dedicated
> > > one then you may use it directly
> >
> > Well... the engine is shared by a few UARTs, they have dedicated rings
> > but there's a common set of regs for interrupt handling etc.
> >
> > That said, I still think it could be contained within a UART driver,
> > there's little benefit in adding the framework overhead, esp since
> > these are really weak cores, any overhead will be felt.
> >
> > Ben.
> >
> > > > It's unclear whether it should be split into two drivers, or just have
> > > > the serial driver directly use the dma engine since that engine is
> > > > dedicated in HW to only work on those UARTs and nothing else...
> > > >
> > > > Cheers,
> > > > Ben.
>
> Initially we wanted to have a single driver,
> however we had an informal discussion with one of the maintainer
> and based on the feedback, followed the Linux DMA and UART architecture.
>
> If this seperate DMA-engine driver adds more overhead than benifit,
> we will merge them into a single UART driver and resubmitt the patches.
> Vinod,
> can this dma-controller driver sit under dma subsystem?.
> or better to move it under UART framework.
My advise would be to see what you can do with the DMA IP block. If this
can/would be used in different places then it would make sense to do a
dmaengine driver and solve the problem for everyone.
If this is always going to be hidden behind serial then maybe it makes
sense to be inside serial driver and not use dmaengine APIs
If you decide to prefer the former case, please move it to dmaengine and
resubmit :)
HTH
^ permalink raw reply
* [v2,4/4] dmaengine: xilinx_dma: Fix 64-bit simple CDMA transfer
From: Appana Durga Kedareswara Rao @ 2018-10-19 10:38 UTC (permalink / raw)
To: Radhey Shyam Pandey, vkoul@kernel.org, dan.j.williams@intel.com,
Michal Simek
Cc: dmaengine@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
> -----Original Message-----
> From: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
> Sent: Saturday, September 29, 2018 10:48 PM
> To: vkoul@kernel.org; dan.j.williams@intel.com; Michal Simek
> <michals@xilinx.com>; Appana Durga Kedareswara Rao
> <appanad@xilinx.com>; Radhey Shyam Pandey <radheys@xilinx.com>
> Cc: dmaengine@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org
> Subject: [PATCH v2 4/4] dmaengine: xilinx_dma: Fix 64-bit simple CDMA
> transfer
>
> In AXI CDMA simple mode also pass MSB bits of source and destination
> address to xilinx_write function. This fixes simple CDMA operation mode using
> 64-bit addressing.
>
> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Appana Durga Kedareswara Rao <appana.durga.rao@xilinx.com>
Regards,
Kedar.
> ---
> Changes for v2:
> Use helper macro for preparing dma_addr_t.
> ---
> drivers/dma/xilinx/xilinx_dma.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index c27ab64..d04ef85 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -1247,8 +1247,10 @@ static void xilinx_cdma_start_transfer(struct
> xilinx_dma_chan *chan)
>
> hw = &segment->hw;
>
> - xilinx_write(chan, XILINX_CDMA_REG_SRCADDR, hw-
> >src_addr);
> - xilinx_write(chan, XILINX_CDMA_REG_DSTADDR, hw-
> >dest_addr);
> + xilinx_write(chan, XILINX_CDMA_REG_SRCADDR,
> + xilinx_prep_dma_addr_t(hw->src_addr));
> + xilinx_write(chan, XILINX_CDMA_REG_DSTADDR,
> + xilinx_prep_dma_addr_t(hw->dest_addr));
>
> /* Start the transfer */
> dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
> --
> 1.7.1
^ permalink raw reply
* [v2,3/4] dmaengine: xilinx_dma: Introduce helper macro for preparing dma address
From: Appana Durga Kedareswara Rao @ 2018-10-19 10:37 UTC (permalink / raw)
To: Radhey Shyam Pandey, vkoul@kernel.org, dan.j.williams@intel.com,
Michal Simek
Cc: dmaengine@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Hi,
Thanks for the patch...
>
> This patch introduces the xilinx_prep_dma_addr_t macro which prepares
> dma_addr_t from hardware buffer descriptor LSB and MSB fields. It will be
> used in simple dma 64-bit programming sequence.
>
> Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Reviewed-by: Appana Durga Kedareswara Rao <appana.durga.rao@xilinx.com>
Regards,
Kedar.
> ---
> Changes for v2:
> New patch- Preparatory change for 4/4 fix.
> ---
> drivers/dma/xilinx/xilinx_dma.c | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index a37871e..c27ab64 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -190,6 +190,8 @@
> /* AXI CDMA Specific Masks */
> #define XILINX_CDMA_CR_SGMODE BIT(3)
>
> +#define xilinx_prep_dma_addr_t(addr) \
> + ((dma_addr_t)((u64)addr##_##msb << 32 | (addr)))
> /**
> * struct xilinx_vdma_desc_hw - Hardware Descriptor
> * @next_desc: Next Descriptor Pointer @0x00
> --
> 1.7.1
^ permalink raw reply
* [v3,4/7] dmaengine: stm32-dma: Add DMA/MDMA chaining support
From: Pierre Yves MORDRET @ 2018-10-19 9:21 UTC (permalink / raw)
To: Vinod
Cc: Rob Herring, Mark Rutland, Alexandre Torgue, Maxime Coquelin,
Dan Williams, devicetree, dmaengine, linux-arm-kernel,
linux-kernel
On 10/16/18 4:44 PM, Vinod wrote:
> On 16-10-18, 11:19, Pierre Yves MORDRET wrote:
>>
>>
>> On 10/15/18 7:14 PM, Vinod wrote:
>>> On 10-10-18, 09:02, Pierre Yves MORDRET wrote:
>>>>
>>>>
>>>> On 10/10/2018 06:03 AM, Vinod wrote:
>>>>> On 09-10-18, 10:40, Pierre Yves MORDRET wrote:
>>>>>>
>>>>>>
>>>>>> On 10/07/2018 06:00 PM, Vinod wrote:
>>>>>>> On 28-09-18, 15:01, Pierre-Yves MORDRET wrote:
>>>>>>>> This patch adds support of DMA/MDMA chaining support.
>>>>>>>> It introduces an intermediate transfer between peripherals and STM32 DMA.
>>>>>>>> This intermediate transfer is triggered by SW for single M2D transfer and
>>>>>>>> by STM32 DMA IP for all other modes (sg, cyclic) and direction (D2M).
>>>>>>>>
>>>>>>>> A generic SRAM allocator is used for this intermediate buffer
>>>>>>>> Each DMA channel will be able to define its SRAM needs to achieve chaining
>>>>>>>> feature : (2 ^ order) * PAGE_SIZE.
>>>>>>>> For cyclic, SRAM buffer is derived from period length (rounded on
>>>>>>>> PAGE_SIZE).
>>>>>>>
>>>>>>> So IIUC, you chain two dma txns together and transfer data via an SRAM?
>>>>>>
>>>>>> Correct. one DMA is DMAv2 (stm32-dma) and the other is MDMA(stm32-mdma).
>>>>>> Intermediate transfer is between device and memory.
>>>>>> This intermediate transfer is using SDRAM.
>>>>>
>>>>> Ah so you use dma calls to setup mdma xtfers? I dont think that is a
>>>>> good idea. How do you know you should use mdma for subsequent transfer?
>>>>>
>>>>
>>>> When user bindings told to setup chaining intermediate MDMA transfers are always
>>>> triggers.
>>>> For instance if a user requests a Dev2Mem transfer with chaining. From client
>>>> pov this is still a prep_slave_sg. Internally DMAv2 is setup in cyclic mode (in
>>>> double buffer mode indeed => 2 buffer of PAGE_SIZE/2) and destination is SDRAM.
>>>> DMAv2 will flip/flop on those 2 buffers.
>>>> At the same time DMAv2 driver prepares a MDMA SG that will fetch data from those
>>>> 2 buffers in SDRAM and fills final destination memory.
>>>
>>> I am not able to follow is why does it need to be internal, why should
>>> the client not set the two transfers and trigger them?
>>>
>>
>> Client may use or not chaining: defined within DT. API and dynamic are same at
>
> That should be upto client... As a dmaengine driver you should enable
> data transfer from src to dstn.
>
>> driver client level. Moreover driver exposes only DMAv2 and not both DMAv2 and
>> MDMA. This is totally hidden for client. If client sets both this would imply
>
> Why should a controller be hidden from user, I dont see why that would
> be a good thing
>
>> changing all drivers that may want use chaining. Even more to deal with DMAv2
>> and MDMA at its level.
>> Since DMAv2 deals with MDMA, all drivers are same as before. no changes required.
>
> It is not about changes, it is about the SW model you want to have.
>
> The intermediate SRAM transfers should not be made within DMAengine
> driver, client can chose to have two transfers and couple or not, it is
> upto them to choose. Sorry I do not like this abstraction and would like
> to see a cleaner approach
>
What we have done it to hide all the complexity related to DMA engine:
synchronization, residue and many other topics solved by this approach. If this
is up to client to perform intermediate transfer, each client drivers using
chaining will need to duplicate the required sw.
This approach is present as a feature from driver pov.
Regards
^ permalink raw reply
* [[PATCH] 8/9] DMA-UART-Driver-for-AST2500
From: sudheer.v @ 2018-10-19 7:11 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Vinod, Rob Herring, Mark Rutland, Greg Kroah-Hartman,
Joel Stanley, Andrew Jeffery, Russell King, Dan Williams,
Jiri Slaby, Thomas Gleixner, Marc Zyngier, Christian Borntraeger,
Michael Moese, Hendrik Brueckner, Kate Stewart,
Philippe Ombredanne, dmaengine, devicetree, linux-kernel,
linux-serial, linux-arm-kernel, linux-aspeed, Sudheer V,
ShivahShankar Shakarnarayan rao
On Fri, Oct 19, 2018 at 10:32:24AM +1100, Benjamin Herrenschmidt wrote:
> On Thu, 2018-10-18 at 15:25 +0530, Vinod wrote:
> >
> > > It's not a dmaengine driver. It's a serial UART driver that happens to
> > > use a dedicated DMA engine.
> >
> > Then I see no reason for it to use dmaengine APIs. The framework allows
> > people to share a controller for many clients, but if you have dedicated
> > one then you may use it directly
>
> Well... the engine is shared by a few UARTs, they have dedicated rings
> but there's a common set of regs for interrupt handling etc.
>
> That said, I still think it could be contained within a UART driver,
> there's little benefit in adding the framework overhead, esp since
> these are really weak cores, any overhead will be felt.
>
> Ben.
>
> > > It's unclear whether it should be split into two drivers, or just have
> > > the serial driver directly use the dma engine since that engine is
> > > dedicated in HW to only work on those UARTs and nothing else...
> > >
> > > Cheers,
> > > Ben.
Initially we wanted to have a single driver,
however we had an informal discussion with one of the maintainer
and based on the feedback, followed the Linux DMA and UART architecture.
If this seperate DMA-engine driver adds more overhead than benifit,
we will merge them into a single UART driver and resubmitt the patches.
Vinod,
can this dma-controller driver sit under dma subsystem?.
or better to move it under UART framework.
Thank you.
-- Sudheer
^ permalink raw reply
* [[PATCH] 8/9] DMA-UART-Driver-for-AST2500
From: Benjamin Herrenschmidt @ 2018-10-18 23:32 UTC (permalink / raw)
To: Vinod
Cc: sudheer.v, Rob Herring, Mark Rutland, Greg Kroah-Hartman,
Joel Stanley, Andrew Jeffery, Russell King, Dan Williams,
Jiri Slaby, Thomas Gleixner, Marc Zyngier, Christian Borntraeger,
Michael Moese, Hendrik Brueckner, Kate Stewart,
Philippe Ombredanne, dmaengine, devicetree, linux-kernel,
linux-serial, linux-arm-kernel, linux-aspeed, Sudheer V,
ShivahShankar Shakarnarayan rao
On Thu, 2018-10-18 at 15:25 +0530, Vinod wrote:
>
> > It's not a dmaengine driver. It's a serial UART driver that happens to
> > use a dedicated DMA engine.
>
> Then I see no reason for it to use dmaengine APIs. The framework allows
> people to share a controller for many clients, but if you have dedicated
> one then you may use it directly
Well... the engine is shared by a few UARTs, they have dedicated rings
but there's a common set of regs for interrupt handling etc.
That said, I still think it could be contained within a UART driver,
there's little benefit in adding the framework overhead, esp since
these are really weak cores, any overhead will be felt.
Ben.
> > It's unclear whether it should be split into two drivers, or just have
> > the serial driver directly use the dma engine since that engine is
> > dedicated in HW to only work on those UARTs and nothing else...
> >
> > Cheers,
> > Ben.
> >
> >
> > > While doing resubmission please take some time to understand subsystem
> > > tags to use. (hint git log <subsystem> will tell you)
> > >
> > > Also series has [[PATCH] 8/9] whereas it should be [PATCH 8/9] please
> > > let git generate that for you (hint git format-patch start..end does a
> > > good job)
> > >
> > > > @@ -0,0 +1,1594 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * drivers/tty/serial/8250/8250_aspeed_uart_dma.c
> > > > + * 1. 2018/07/01 Shivah Shankar created
> > > > + * 2. 2018/08/25 sudheer.veliseti<open.sudheer@gmail.com> modified
> > >
> > > we dont use this log in kernel. I do not see s-o-b by Shivah, that
> > > should be added. I think he should be author and you need to list
> > > changes you did..
> > >
>
>
^ permalink raw reply
* [[PATCH] 8/9] DMA-UART-Driver-for-AST2500
From: Vinod Koul @ 2018-10-18 9:55 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: sudheer.v, Rob Herring, Mark Rutland, Greg Kroah-Hartman,
Joel Stanley, Andrew Jeffery, Russell King, Dan Williams,
Jiri Slaby, Thomas Gleixner, Marc Zyngier, Christian Borntraeger,
Michael Moese, Hendrik Brueckner, Kate Stewart,
Philippe Ombredanne, dmaengine, devicetree, linux-kernel,
linux-serial, linux-arm-kernel, linux-aspeed, Sudheer V,
ShivahShankar Shakarnarayan rao
On 17-10-18, 19:56, Benjamin Herrenschmidt wrote:
> On Wed, 2018-10-17 at 11:35 +0530, Vinod wrote:
> > On 17-10-18, 09:41, sudheer.v wrote:
> >
> > Please add the change log describing the driver and its features
> >
> > > Signed-off-by: sudheer.v <open.sudheer@gmail.com>
> > > ---
> > > drivers/tty/serial/8250/8250_aspeed_uart_dma.c | 1594 ++++++++++++++++++++++++
> > > 1 file changed, 1594 insertions(+)
> > > create mode 100644 drivers/tty/serial/8250/8250_aspeed_uart_dma.c
> > >
> > > diff --git a/drivers/tty/serial/8250/8250_aspeed_uart_dma.c b/drivers/tty/serial/8250/8250_aspeed_uart_dma.c
> > > new file mode 100644
> > > index 0000000..e1019a8
> > > --- /dev/null
> > > +++ b/drivers/tty/serial/8250/8250_aspeed_uart_dma.c
> >
> > why is this in serial. It is dmaengine driver so belongs to drivers/dma/
> > like other controllers. Please move it out and resubmit.
>
> It's not a dmaengine driver. It's a serial UART driver that happens to
> use a dedicated DMA engine.
Then I see no reason for it to use dmaengine APIs. The framework allows
people to share a controller for many clients, but if you have dedicated
one then you may use it directly
> It's unclear whether it should be split into two drivers, or just have
> the serial driver directly use the dma engine since that engine is
> dedicated in HW to only work on those UARTs and nothing else...
>
> Cheers,
> Ben.
>
>
> > While doing resubmission please take some time to understand subsystem
> > tags to use. (hint git log <subsystem> will tell you)
> >
> > Also series has [[PATCH] 8/9] whereas it should be [PATCH 8/9] please
> > let git generate that for you (hint git format-patch start..end does a
> > good job)
> >
> > > @@ -0,0 +1,1594 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * drivers/tty/serial/8250/8250_aspeed_uart_dma.c
> > > + * 1. 2018/07/01 Shivah Shankar created
> > > + * 2. 2018/08/25 sudheer.veliseti<open.sudheer@gmail.com> modified
> >
> > we dont use this log in kernel. I do not see s-o-b by Shivah, that
> > should be added. I think he should be author and you need to list
> > changes you did..
> >
^ permalink raw reply
* [2/2] dmaengine: mediatek: Add MediaTek Command-Queue DMA controller for MT6765 SoC
From: shun-chih.yu @ 2018-10-18 7:49 UTC (permalink / raw)
To: Sean Wang, Vinod Koul, Rob Herring, Matthias Brugger,
Dan Williams
Cc: dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
linux-kernel, srv_wsdupstream, Shun-Chih Yu
From: Shun-Chih Yu <shun-chih.yu@mediatek.com>
MediaTek Command-Queue DMA controller (CQDMA) on MT6765 SoC is dedicated
to memory-to-memory transfer through queue based descriptor management.
There are only 3 physical channels inside CQDMA, while the driver is
extended to support 32 virtual channels for multiple dma users to issue
dma requests onto the CQDMA simultaneously.
Signed-off-by: Shun-Chih Yu <shun-chih.yu@mediatek.com>
---
drivers/dma/mediatek/Kconfig | 13 +
drivers/dma/mediatek/Makefile | 1 +
drivers/dma/mediatek/mtk-cqdma.c | 951 ++++++++++++++++++++++++++++++++++++++
3 files changed, 965 insertions(+)
create mode 100644 drivers/dma/mediatek/mtk-cqdma.c
diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig
index 27bac0b..680fc05 100644
--- a/drivers/dma/mediatek/Kconfig
+++ b/drivers/dma/mediatek/Kconfig
@@ -11,3 +11,16 @@ config MTK_HSDMA
This controller provides the channels which is dedicated to
memory-to-memory transfer to offload from CPU through ring-
based descriptor management.
+
+config MTK_CQDMA
+ tristate "MediaTek Command-Queue DMA controller support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ select ASYNC_TX_ENABLE_CHANNEL_SWITCH
+ help
+ Enable support for Command-Queue DMA controller on MediaTek
+ SoCs.
+
+ This controller provides the channels which is dedicated to
+ memory-to-memory transfer to offload from CPU.
diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile
index 6e778f8..41bb381 100644
--- a/drivers/dma/mediatek/Makefile
+++ b/drivers/dma/mediatek/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o
+obj-$(CONFIG_MTK_CQDMA) += mtk-cqdma.o
diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c
new file mode 100644
index 0000000..131f397
--- /dev/null
+++ b/drivers/dma/mediatek/mtk-cqdma.c
@@ -0,0 +1,951 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-2019 MediaTek Inc.
+
+/*
+ * Driver for MediaTek Command-Queue DMA Controller
+ *
+ * Author: Shun-Chih Yu <shun-chih.yu@mediatek.com>
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/refcount.h>
+#include <linux/slab.h>
+
+#include "../virt-dma.h"
+
+#define MTK_CQDMA_USEC_POLL 10
+#define MTK_CQDMA_TIMEOUT_POLL 1000
+#define MTK_CQDMA_DMA_BUSWIDTHS BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)
+#define MTK_CQDMA_ALIGN_SIZE 1
+
+/* The default number of virtual channel */
+#define MTK_CQDMA_NR_VCHANS 32
+
+/* The default number of physical channel */
+#define MTK_CQDMA_NR_PCHANS 3
+
+/* Registers for underlying dma manipulation */
+#define MTK_CQDMA_INT_FLAG 0x0
+#define MTK_CQDMA_INT_EN 0x4
+#define MTK_CQDMA_EN 0x8
+#define MTK_CQDMA_RESET 0xc
+#define MTK_CQDMA_FLUSH 0x14
+#define MTK_CQDMA_SRC 0x1c
+#define MTK_CQDMA_DST 0x20
+#define MTK_CQDMA_LEN1 0x24
+#define MTK_CQDMA_LEN2 0x28
+#define MTK_CQDMA_SRC2 0x60
+#define MTK_CQDMA_DST2 0x64
+
+/* Registers setting */
+#define MTK_CQDMA_EN_BIT BIT(0)
+#define MTK_CQDMA_INT_FLAG_BIT BIT(0)
+#define MTK_CQDMA_INT_EN_BIT BIT(0)
+#define MTK_CQDMA_FLUSH_BIT BIT(0)
+
+#define MTK_CQDMA_WARM_RST_BIT BIT(0)
+#define MTK_CQDMA_HARD_RST_BIT BIT(1)
+
+#define MTK_CQDMA_MAX_LEN GENMASK(27, 0)
+#define MTK_CQDMA_ADDR_LIMIT GENMASK(31, 0)
+#define MTK_CQDMA_ADDR2_SHFIT (32)
+
+/**
+ * struct mtk_cqdma_vdesc - The struct holding info describing virtual
+ * descriptor (CVD)
+ * @vd: An instance for struct virt_dma_desc
+ * @len: The total data size device wants to move
+ * @residue: The remaining data size device will move
+ * @dest: The destination address device wants to move to
+ * @src: The source address device wants to move from
+ * @ch: The pointer to the corresponding dma channel
+ * @node: The lise_head struct to build link-list for VDs
+ * @parent: The pointer to the parent CVD
+ */
+struct mtk_cqdma_vdesc {
+ struct virt_dma_desc vd;
+ size_t len;
+ size_t residue;
+ dma_addr_t dest;
+ dma_addr_t src;
+ struct dma_chan *ch;
+
+ struct list_head node;
+ struct mtk_cqdma_vdesc *parent;
+};
+
+/**
+ * struct mtk_cqdma_pchan - The struct holding info describing physical
+ * channel (PC)
+ * @queue: Queue for the PDs issued to this PC
+ * @base: The mapped register I/O base of this PC
+ * @irq: The IRQ that this PC are using
+ * @refcnt: Track how many VCs are using this PC
+ * @tasklet: Tasklet for this PC
+ * @lock: Lock protect agaisting multiple VCs access PC
+ */
+struct mtk_cqdma_pchan {
+ struct list_head queue;
+ void __iomem *base;
+ u32 irq;
+
+ refcount_t refcnt;
+
+ struct tasklet_struct tasklet;
+
+ /* lock to protect PC */
+ spinlock_t lock;
+};
+
+/**
+ * struct mtk_cqdma_vchan - The struct holding info describing virtual
+ * channel (VC)
+ * @vc: An instance for struct virt_dma_chan
+ * @pc: The pointer to the underlying PC
+ * @issue_completion: The wait for all issued descriptors completited
+ * @issue_synchronize: Bool indicating channel synchronization starts
+ */
+struct mtk_cqdma_vchan {
+ struct virt_dma_chan vc;
+ struct mtk_cqdma_pchan *pc;
+ struct completion issue_completion;
+ bool issue_synchronize;
+};
+
+/**
+ * struct mtk_cqdma_device - The struct holding info describing CQDMA
+ * device
+ * @ddev: An instance for struct dma_device
+ * @clk: The clock that device internal is using
+ * @dma_requests: The number of VCs the device supports to
+ * @dma_channels: The number of PCs the device supports to
+ * @vc: The pointer to all available VCs
+ * @pc: The pointer to all the underlying PCs
+ */
+struct mtk_cqdma_device {
+ struct dma_device ddev;
+ struct clk *clk;
+
+ u32 dma_requests;
+ u32 dma_channels;
+ struct mtk_cqdma_vchan *vc;
+ struct mtk_cqdma_pchan **pc;
+};
+
+static struct mtk_cqdma_device *to_cqdma_dev(struct dma_chan *chan)
+{
+ return container_of(chan->device, struct mtk_cqdma_device, ddev);
+}
+
+static struct mtk_cqdma_vchan *to_cqdma_vchan(struct dma_chan *chan)
+{
+ return container_of(chan, struct mtk_cqdma_vchan, vc.chan);
+}
+
+static struct mtk_cqdma_vdesc *to_cqdma_vdesc(struct virt_dma_desc *vd)
+{
+ return container_of(vd, struct mtk_cqdma_vdesc, vd);
+}
+
+static struct device *cqdma2dev(struct mtk_cqdma_device *cqdma)
+{
+ return cqdma->ddev.dev;
+}
+
+static u32 mtk_dma_read(struct mtk_cqdma_pchan *pc, u32 reg)
+{
+ return readl(pc->base + reg);
+}
+
+static void mtk_dma_write(struct mtk_cqdma_pchan *pc, u32 reg, u32 val)
+{
+ writel_relaxed(val, pc->base + reg);
+}
+
+static void mtk_dma_rmw(struct mtk_cqdma_pchan *pc, u32 reg,
+ u32 mask, u32 set)
+{
+ u32 val;
+
+ val = mtk_dma_read(pc, reg);
+ val &= ~mask;
+ val |= set;
+ mtk_dma_write(pc, reg, val);
+}
+
+static void mtk_dma_set(struct mtk_cqdma_pchan *pc, u32 reg, u32 val)
+{
+ mtk_dma_rmw(pc, reg, 0, val);
+}
+
+static void mtk_dma_clr(struct mtk_cqdma_pchan *pc, u32 reg, u32 val)
+{
+ mtk_dma_rmw(pc, reg, val, 0);
+}
+
+static void mtk_cqdma_vdesc_free(struct virt_dma_desc *vd)
+{
+ kfree(to_cqdma_vdesc(vd));
+}
+
+static int mtk_cqdma_poll_engine_done(struct mtk_cqdma_pchan *pc, bool atomic)
+{
+ u32 status = 0;
+
+ if (!atomic)
+ return readl_poll_timeout(pc->base + MTK_CQDMA_EN,
+ status,
+ !(status & MTK_CQDMA_EN_BIT),
+ MTK_CQDMA_USEC_POLL,
+ MTK_CQDMA_TIMEOUT_POLL);
+
+ return readl_poll_timeout_atomic(pc->base + MTK_CQDMA_EN,
+ status,
+ !(status & MTK_CQDMA_EN_BIT),
+ MTK_CQDMA_USEC_POLL,
+ MTK_CQDMA_TIMEOUT_POLL);
+}
+
+static int mtk_cqdma_hard_reset(struct mtk_cqdma_pchan *pc)
+{
+ mtk_dma_set(pc, MTK_CQDMA_RESET, MTK_CQDMA_HARD_RST_BIT);
+ mtk_dma_clr(pc, MTK_CQDMA_RESET, MTK_CQDMA_HARD_RST_BIT);
+
+ return mtk_cqdma_poll_engine_done(pc, false);
+}
+
+static void mtk_cqdma_start(struct mtk_cqdma_pchan *pc,
+ struct mtk_cqdma_vdesc *cvd)
+{
+ /* wait for the previous transaction done */
+ if (mtk_cqdma_poll_engine_done(pc, true) < 0)
+ dev_err(cqdma2dev(to_cqdma_dev(cvd->ch)), "cqdma wait transaction timeout\n");
+
+ /* warm reset the dma engine for the new transaction */
+ mtk_dma_set(pc, MTK_CQDMA_RESET, MTK_CQDMA_WARM_RST_BIT);
+ if (mtk_cqdma_poll_engine_done(pc, true) < 0)
+ dev_err(cqdma2dev(to_cqdma_dev(cvd->ch)), "cqdma warm reset timeout\n");
+
+ /* setup the source */
+ mtk_dma_set(pc, MTK_CQDMA_SRC, cvd->src & MTK_CQDMA_ADDR_LIMIT);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ mtk_dma_set(pc, MTK_CQDMA_SRC2, cvd->src >> MTK_CQDMA_ADDR2_SHFIT);
+#else
+ mtk_dma_set(pc, MTK_CQDMA_SRC2, 0);
+#endif
+
+ /* setup the destination */
+ mtk_dma_set(pc, MTK_CQDMA_DST, cvd->dest & MTK_CQDMA_ADDR_LIMIT);
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+ mtk_dma_set(pc, MTK_CQDMA_DST2, cvd->dest >> MTK_CQDMA_ADDR2_SHFIT);
+#else
+ mtk_dma_set(pc, MTK_CQDMA_SRC2, 0);
+#endif
+
+ /* setup the length */
+ mtk_dma_set(pc, MTK_CQDMA_LEN1, cvd->len);
+
+ /* start dma engine */
+ mtk_dma_set(pc, MTK_CQDMA_EN, MTK_CQDMA_EN_BIT);
+}
+
+static void mtk_cqdma_issue_vchan_pending(struct mtk_cqdma_vchan *cvc)
+{
+ struct virt_dma_desc *vd, *vd2;
+ struct mtk_cqdma_pchan *pc = cvc->pc;
+ struct mtk_cqdma_vdesc *cvd;
+ bool trigger_engine = false;
+
+ lockdep_assert_held(&cvc->vc.lock);
+ lockdep_assert_held(&pc->lock);
+
+ list_for_each_entry_safe(vd, vd2, &cvc->vc.desc_issued, node) {
+ /* need to trigger dma engine if PC's queue is empty */
+ if (list_empty(&pc->queue))
+ trigger_engine = true;
+
+ cvd = to_cqdma_vdesc(vd);
+
+ /* add VD into PC's queue */
+ list_add_tail(&cvd->node, &pc->queue);
+
+ /* start the dma engine */
+ if (trigger_engine)
+ mtk_cqdma_start(pc, cvd);
+
+ /* remove VD from list desc_issued */
+ list_del(&vd->node);
+ }
+}
+
+/*
+ * return true if this VC is active,
+ * meaning that there are VDs under processing by the PC
+ */
+static bool mtk_cqdma_is_vchan_active(struct mtk_cqdma_vchan *cvc)
+{
+ struct mtk_cqdma_vdesc *cvd;
+
+ list_for_each_entry(cvd, &cvc->pc->queue, node)
+ if (cvc == to_cqdma_vchan(cvd->ch))
+ return true;
+
+ return false;
+}
+
+/*
+ * return the pointer of the CVD that is just consumed by the PC
+ */
+static struct mtk_cqdma_vdesc
+*mtk_cqdma_consume_work_queue(struct mtk_cqdma_pchan *pc)
+{
+ struct mtk_cqdma_vchan *cvc;
+ struct mtk_cqdma_vdesc *cvd, *ret = NULL;
+
+ /* consume a CVD from PC's queue */
+ cvd = list_first_entry_or_null(&pc->queue,
+ struct mtk_cqdma_vdesc, node);
+ if (unlikely(!cvd || !cvd->parent))
+ return NULL;
+
+ cvc = to_cqdma_vchan(cvd->ch);
+ ret = cvd;
+
+ /* update residue of the parent CVD */
+ cvd->parent->residue -= cvd->len;
+
+ /* delete CVD from PC's queue */
+ list_del(&cvd->node);
+
+ spin_lock(&cvc->vc.lock);
+
+ /* check whether all the child CVDs completed */
+ if (!cvd->parent->residue) {
+ /* add the parent VD into list desc_completed */
+ vchan_cookie_complete(&cvd->parent->vd);
+
+ /* setup completion if this VC is under synchronization */
+ if (cvc->issue_synchronize && !mtk_cqdma_is_vchan_active(cvc)) {
+ complete(&cvc->issue_completion);
+ cvc->issue_synchronize = false;
+ }
+ }
+
+ spin_unlock(&cvc->vc.lock);
+
+ /* start transaction for next CVD in the queue */
+ cvd = list_first_entry_or_null(&pc->queue,
+ struct mtk_cqdma_vdesc, node);
+ if (cvd)
+ mtk_cqdma_start(pc, cvd);
+
+ return ret;
+}
+
+static void mtk_cqdma_tasklet_cb(unsigned long data)
+{
+ struct mtk_cqdma_pchan *pc = (struct mtk_cqdma_pchan *)data;
+ struct mtk_cqdma_vdesc *cvd = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pc->lock, flags);
+ /* consume the queue */
+ cvd = mtk_cqdma_consume_work_queue(pc);
+ spin_unlock_irqrestore(&pc->lock, flags);
+
+ /* submit the next CVD */
+ if (cvd) {
+ dma_run_dependencies(&cvd->vd.tx);
+
+ /*
+ * free child CVD after completion.
+ * the parent CVD would be freeed with desc_free by user.
+ */
+ if (cvd->parent != cvd)
+ kfree(cvd);
+ }
+
+ /* re-enable interrupt before leaving tasklet */
+ enable_irq(pc->irq);
+}
+
+static irqreturn_t mtk_cqdma_irq(int irq, void *devid)
+{
+ struct mtk_cqdma_device *cqdma = devid;
+ irqreturn_t ret = IRQ_NONE;
+ bool schedule_tasklet = false;
+ u32 i;
+
+ /* clear interrupt flags for each PC */
+ for (i = 0; i < cqdma->dma_channels; ++i, schedule_tasklet = false) {
+ spin_lock(&cqdma->pc[i]->lock);
+ if (mtk_dma_read(cqdma->pc[i],
+ MTK_CQDMA_INT_FLAG) & MTK_CQDMA_INT_FLAG_BIT) {
+ /* clear interrupt */
+ mtk_dma_clr(cqdma->pc[i], MTK_CQDMA_INT_FLAG,
+ MTK_CQDMA_INT_FLAG_BIT);
+
+ schedule_tasklet = true;
+ ret = IRQ_HANDLED;
+ }
+ spin_unlock(&cqdma->pc[i]->lock);
+
+ if (schedule_tasklet) {
+ /* disable interrupt */
+ disable_irq_nosync(cqdma->pc[i]->irq);
+
+ /* schedule the tasklet to handle the transactions */
+ tasklet_schedule(&cqdma->pc[i]->tasklet);
+ }
+ }
+
+ return ret;
+}
+
+static struct virt_dma_desc *mtk_cqdma_find_active_desc(struct dma_chan *c,
+ dma_cookie_t cookie)
+{
+ struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c);
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cvc->pc->lock, flags);
+ list_for_each_entry(vd, &cvc->pc->queue, node)
+ if (vd->tx.cookie == cookie) {
+ spin_unlock_irqrestore(&cvc->pc->lock, flags);
+ return vd;
+ }
+ spin_unlock_irqrestore(&cvc->pc->lock, flags);
+
+ list_for_each_entry(vd, &cvc->vc.desc_issued, node)
+ if (vd->tx.cookie == cookie)
+ return vd;
+
+ return NULL;
+}
+
+static enum dma_status mtk_cqdma_tx_status(struct dma_chan *c,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c);
+ struct mtk_cqdma_vdesc *cvd;
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
+ size_t bytes = 0;
+
+ ret = dma_cookie_status(c, cookie, txstate);
+ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&cvc->vc.lock, flags);
+ vd = mtk_cqdma_find_active_desc(c, cookie);
+ spin_unlock_irqrestore(&cvc->vc.lock, flags);
+
+ if (vd) {
+ cvd = to_cqdma_vdesc(vd);
+ bytes = cvd->residue;
+ }
+
+ dma_set_residue(txstate, bytes);
+
+ return ret;
+}
+
+static void mtk_cqdma_issue_pending(struct dma_chan *c)
+{
+ struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c);
+ unsigned long pc_flags;
+ unsigned long vc_flags;
+
+ /* acquire PC's lock before VS's lock for lock dependency in tasklet */
+ spin_lock_irqsave(&cvc->pc->lock, pc_flags);
+ spin_lock_irqsave(&cvc->vc.lock, vc_flags);
+
+ if (vchan_issue_pending(&cvc->vc))
+ mtk_cqdma_issue_vchan_pending(cvc);
+
+ spin_unlock_irqrestore(&cvc->vc.lock, vc_flags);
+ spin_unlock_irqrestore(&cvc->pc->lock, pc_flags);
+}
+
+static struct dma_async_tx_descriptor *
+mtk_cqdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest,
+ dma_addr_t src, size_t len, unsigned long flags)
+{
+ struct mtk_cqdma_vdesc **cvd;
+ struct dma_async_tx_descriptor *tx = NULL, *prev_tx = NULL;
+ size_t i, tlen, nr_vd;
+
+ /*
+ * In the case that trsanction length is larger than the
+ * DMA engine supports, a single memcpy transaction needs
+ * to be separated into several DMA transactions.
+ * Each DMA transaction would be described by a CVD,
+ * and the first one is referred as the parent CVD,
+ * while the others are child CVDs.
+ * The parent CVD's tx descriptor is the only tx descriptor
+ * returned to the DMA user, and it should not be completed
+ * until all the child CVDs completed.
+ */
+ nr_vd = DIV_ROUND_UP(len, MTK_CQDMA_MAX_LEN);
+ cvd = kcalloc(nr_vd, sizeof(*cvd), GFP_NOWAIT);
+ if (!cvd)
+ return NULL;
+
+ for (i = 0; i < nr_vd; ++i) {
+ cvd[i] = kzalloc(sizeof(*cvd[i]), GFP_NOWAIT);
+ if (!cvd[i]) {
+ for (; i > 0; --i)
+ kfree(cvd[i - 1]);
+ return NULL;
+ }
+
+ /* setup dma channel */
+ cvd[i]->ch = c;
+
+ /* setup sourece, destination, and length */
+ tlen = (len > MTK_CQDMA_MAX_LEN) ? MTK_CQDMA_MAX_LEN : len;
+ cvd[i]->len = tlen;
+ cvd[i]->src = src;
+ cvd[i]->dest = dest;
+
+ /* setup tx descriptor */
+ tx = vchan_tx_prep(to_virt_chan(c), &cvd[i]->vd, flags);
+ tx->next = NULL;
+
+ if (!i) {
+ cvd[0]->residue = len;
+ } else {
+ prev_tx->next = tx;
+ cvd[i]->residue = tlen;
+ }
+
+ cvd[i]->parent = cvd[0];
+
+ /* update the src, dest, len, prev_tx for the next CVD */
+ src += tlen;
+ dest += tlen;
+ len -= tlen;
+ prev_tx = tx;
+ }
+
+ return &cvd[0]->vd.tx;
+}
+
+static void mtk_cqdma_free_inactive_desc(struct dma_chan *c)
+{
+ struct virt_dma_chan *vc = to_virt_chan(c);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ /*
+ * set desc_allocated, desc_submitted,
+ * and desc_issued as the candicates to be freed
+ */
+ spin_lock_irqsave(&vc->lock, flags);
+ list_splice_tail_init(&vc->desc_allocated, &head);
+ list_splice_tail_init(&vc->desc_submitted, &head);
+ list_splice_tail_init(&vc->desc_issued, &head);
+ spin_unlock_irqrestore(&vc->lock, flags);
+
+ /* free descriptor lists */
+ vchan_dma_desc_free_list(vc, &head);
+}
+
+static void mtk_cqdma_free_active_desc(struct dma_chan *c)
+{
+ struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c);
+ bool sync_needed = false;
+ unsigned long pc_flags;
+ unsigned long vc_flags;
+
+ /* acquire PC's lock first due to lock dependency in dma ISR */
+ spin_lock_irqsave(&cvc->pc->lock, pc_flags);
+ spin_lock_irqsave(&cvc->vc.lock, vc_flags);
+
+ /* synchronization is required if this VC is active */
+ if (mtk_cqdma_is_vchan_active(cvc)) {
+ cvc->issue_synchronize = true;
+ sync_needed = true;
+ }
+
+ spin_unlock_irqrestore(&cvc->vc.lock, vc_flags);
+ spin_unlock_irqrestore(&cvc->pc->lock, pc_flags);
+
+ /* waiting for the completion of this VC */
+ if (sync_needed)
+ wait_for_completion(&cvc->issue_completion);
+
+ /* free all descriptors in list desc_completed */
+ vchan_synchronize(&cvc->vc);
+
+ WARN_ONCE(!list_empty(&cvc->vc.desc_completed),
+ "Desc pending still in list desc_completed\n");
+}
+
+static int mtk_cqdma_terminate_all(struct dma_chan *c)
+{
+ /* free descriptors not processed yet by hardware */
+ mtk_cqdma_free_inactive_desc(c);
+
+ /* free descriptors being processed by hardware */
+ mtk_cqdma_free_active_desc(c);
+
+ return 0;
+}
+
+static int mtk_cqdma_alloc_chan_resources(struct dma_chan *c)
+{
+ struct mtk_cqdma_device *cqdma = to_cqdma_dev(c);
+ struct mtk_cqdma_vchan *vc = to_cqdma_vchan(c);
+ struct mtk_cqdma_pchan *pc = NULL;
+ u32 i, min_refcnt = U32_MAX, refcnt;
+ unsigned long flags;
+
+ /* allocate PC with the minimun refcount */
+ for (i = 0; i < cqdma->dma_channels; ++i) {
+ refcnt = refcount_read(&cqdma->pc[i]->refcnt);
+ if (refcnt < min_refcnt) {
+ pc = cqdma->pc[i];
+ min_refcnt = refcnt;
+ }
+ }
+
+ if (!pc)
+ return -ENOSPC;
+
+ spin_lock_irqsave(&pc->lock, flags);
+
+ if (!refcount_read(&pc->refcnt)) {
+ /* allocate PC when the refcount is zero */
+ mtk_cqdma_hard_reset(pc);
+
+ /* enable interrupt for this PC */
+ mtk_dma_set(pc, MTK_CQDMA_INT_EN, MTK_CQDMA_INT_EN_BIT);
+
+ /*
+ * refcount_inc would complain increment on 0; use-after-free.
+ * Thus, we need to explicitly set it as 1 initially.
+ */
+ refcount_set(&pc->refcnt, 1);
+ } else {
+ refcount_inc(&pc->refcnt);
+ }
+
+ spin_unlock_irqrestore(&pc->lock, flags);
+
+ vc->pc = pc;
+
+ return 0;
+}
+
+static void mtk_cqdma_free_chan_resources(struct dma_chan *c)
+{
+ struct mtk_cqdma_vchan *cvc = to_cqdma_vchan(c);
+ unsigned long flags;
+
+ /* free all descriptors in all lists on the VC */
+ mtk_cqdma_terminate_all(c);
+
+ spin_lock_irqsave(&cvc->pc->lock, flags);
+
+ /* PC is not freed until there is no VC mapped to it */
+ if (refcount_dec_and_test(&cvc->pc->refcnt)) {
+ /* start the flush operation and stop the engine */
+ mtk_dma_set(cvc->pc, MTK_CQDMA_FLUSH, MTK_CQDMA_FLUSH_BIT);
+
+ /* wait for the completion of flush operation */
+ if (mtk_cqdma_poll_engine_done(cvc->pc, false) < 0)
+ dev_err(cqdma2dev(to_cqdma_dev(c)), "cqdma flush timeout\n");
+
+ /* clear the flush bit and interrupt flag */
+ mtk_dma_clr(cvc->pc, MTK_CQDMA_FLUSH, MTK_CQDMA_FLUSH_BIT);
+ mtk_dma_clr(cvc->pc, MTK_CQDMA_INT_FLAG,
+ MTK_CQDMA_INT_FLAG_BIT);
+
+ /* disable interrupt for this PC */
+ mtk_dma_clr(cvc->pc, MTK_CQDMA_INT_EN, MTK_CQDMA_INT_EN_BIT);
+ }
+
+ spin_unlock_irqrestore(&cvc->pc->lock, flags);
+}
+
+static int mtk_cqdma_hw_init(struct mtk_cqdma_device *cqdma)
+{
+ unsigned long flags;
+ int err;
+ u32 i;
+
+ pm_runtime_enable(cqdma2dev(cqdma));
+ pm_runtime_get_sync(cqdma2dev(cqdma));
+
+ err = clk_prepare_enable(cqdma->clk);
+
+ if (err) {
+ pm_runtime_put_sync(cqdma2dev(cqdma));
+ pm_runtime_disable(cqdma2dev(cqdma));
+ return err;
+ }
+
+ /* reset all PCs */
+ for (i = 0; i < cqdma->dma_channels; ++i) {
+ spin_lock_irqsave(&cqdma->pc[i]->lock, flags);
+ if (mtk_cqdma_hard_reset(cqdma->pc[i]) < 0) {
+ dev_err(cqdma2dev(cqdma), "cqdma hard reset timeout\n");
+ spin_unlock_irqrestore(&cqdma->pc[i]->lock, flags);
+
+ clk_disable_unprepare(cqdma->clk);
+ pm_runtime_put_sync(cqdma2dev(cqdma));
+ pm_runtime_disable(cqdma2dev(cqdma));
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&cqdma->pc[i]->lock, flags);
+ }
+
+ return 0;
+}
+
+static void mtk_cqdma_hw_deinit(struct mtk_cqdma_device *cqdma)
+{
+ unsigned long flags;
+ u32 i;
+
+ /* reset all PCs */
+ for (i = 0; i < cqdma->dma_channels; ++i) {
+ spin_lock_irqsave(&cqdma->pc[i]->lock, flags);
+ if (mtk_cqdma_hard_reset(cqdma->pc[i]) < 0)
+ dev_err(cqdma2dev(cqdma), "cqdma hard reset timeout\n");
+ spin_unlock_irqrestore(&cqdma->pc[i]->lock, flags);
+ }
+
+ clk_disable_unprepare(cqdma->clk);
+
+ pm_runtime_put_sync(cqdma2dev(cqdma));
+ pm_runtime_disable(cqdma2dev(cqdma));
+}
+
+static const struct of_device_id mtk_cqdma_match[] = {
+ { .compatible = "mediatek,mt6765-cqdma" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_cqdma_match);
+
+static int mtk_cqdma_probe(struct platform_device *pdev)
+{
+ struct mtk_cqdma_device *cqdma;
+ struct mtk_cqdma_vchan *vc;
+ struct dma_device *dd;
+ struct resource *res;
+ int err;
+ u32 i;
+
+ cqdma = devm_kzalloc(&pdev->dev, sizeof(*cqdma), GFP_KERNEL);
+ if (!cqdma)
+ return -ENOMEM;
+
+ dd = &cqdma->ddev;
+
+ cqdma->clk = devm_clk_get(&pdev->dev, "cqdma");
+ if (IS_ERR(cqdma->clk)) {
+ dev_err(&pdev->dev, "No clock for %s\n",
+ dev_name(&pdev->dev));
+ return PTR_ERR(cqdma->clk);
+ }
+
+ dma_cap_set(DMA_MEMCPY, dd->cap_mask);
+
+ dd->copy_align = MTK_CQDMA_ALIGN_SIZE;
+ dd->device_alloc_chan_resources = mtk_cqdma_alloc_chan_resources;
+ dd->device_free_chan_resources = mtk_cqdma_free_chan_resources;
+ dd->device_tx_status = mtk_cqdma_tx_status;
+ dd->device_issue_pending = mtk_cqdma_issue_pending;
+ dd->device_prep_dma_memcpy = mtk_cqdma_prep_dma_memcpy;
+ dd->device_terminate_all = mtk_cqdma_terminate_all;
+ dd->src_addr_widths = MTK_CQDMA_DMA_BUSWIDTHS;
+ dd->dst_addr_widths = MTK_CQDMA_DMA_BUSWIDTHS;
+ dd->directions = BIT(DMA_MEM_TO_MEM);
+ dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+ dd->dev = &pdev->dev;
+ INIT_LIST_HEAD(&dd->channels);
+
+ if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
+ "dma-requests",
+ &cqdma->dma_requests)) {
+ dev_info(&pdev->dev,
+ "Using %u as missing dma-requests property\n",
+ MTK_CQDMA_NR_VCHANS);
+
+ cqdma->dma_requests = MTK_CQDMA_NR_VCHANS;
+ }
+
+ if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
+ "dma-channels",
+ &cqdma->dma_channels)) {
+ dev_info(&pdev->dev,
+ "Using %u as missing dma-channels property\n",
+ MTK_CQDMA_NR_PCHANS);
+
+ cqdma->dma_channels = MTK_CQDMA_NR_PCHANS;
+ }
+
+ cqdma->pc = devm_kcalloc(&pdev->dev, cqdma->dma_channels,
+ sizeof(*cqdma->pc), GFP_KERNEL);
+ if (!cqdma->pc)
+ return -ENOMEM;
+
+ /* initialization for PCs */
+ for (i = 0; i < cqdma->dma_channels; ++i) {
+ cqdma->pc[i] = devm_kcalloc(&pdev->dev, 1,
+ sizeof(**cqdma->pc), GFP_KERNEL);
+ if (!cqdma->pc[i])
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&cqdma->pc[i]->queue);
+ spin_lock_init(&cqdma->pc[i]->lock);
+ refcount_set(&cqdma->pc[i]->refcnt, 0);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res) {
+ dev_err(&pdev->dev, "No mem resource for %s\n",
+ dev_name(&pdev->dev));
+ return -EINVAL;
+ }
+
+ cqdma->pc[i]->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(cqdma->pc[i]->base))
+ return PTR_ERR(cqdma->pc[i]->base);
+
+ /* allocate IRQ resource */
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(&pdev->dev, "No irq resource for %s\n",
+ dev_name(&pdev->dev));
+ return -EINVAL;
+ }
+ cqdma->pc[i]->irq = res->start;
+
+ err = devm_request_irq(&pdev->dev, cqdma->pc[i]->irq,
+ mtk_cqdma_irq, 0, dev_name(&pdev->dev),
+ cqdma);
+ if (err) {
+ dev_err(&pdev->dev,
+ "request_irq failed with err %d\n", err);
+ return -EINVAL;
+ }
+ }
+
+ /* allocate resource for VCs */
+ cqdma->vc = devm_kcalloc(&pdev->dev, cqdma->dma_requests,
+ sizeof(*cqdma->vc), GFP_KERNEL);
+ if (!cqdma->vc)
+ return -ENOMEM;
+
+ for (i = 0; i < cqdma->dma_requests; i++) {
+ vc = &cqdma->vc[i];
+ vc->vc.desc_free = mtk_cqdma_vdesc_free;
+ vchan_init(&vc->vc, dd);
+ init_completion(&vc->issue_completion);
+ }
+
+ err = dma_async_device_register(dd);
+ if (err)
+ return err;
+
+ err = of_dma_controller_register(pdev->dev.of_node,
+ of_dma_xlate_by_chan_id, cqdma);
+ if (err) {
+ dev_err(&pdev->dev,
+ "MediaTek CQDMA OF registration failed %d\n", err);
+ goto err_unregister;
+ }
+
+ err = mtk_cqdma_hw_init(cqdma);
+ if (err) {
+ dev_err(&pdev->dev,
+ "MediaTek CQDMA HW initialization failed %d\n", err);
+ goto err_unregister;
+ }
+
+ platform_set_drvdata(pdev, cqdma);
+
+ /* initialize tasklet for each PC */
+ for (i = 0; i < cqdma->dma_channels; ++i)
+ tasklet_init(&cqdma->pc[i]->tasklet, mtk_cqdma_tasklet_cb,
+ (unsigned long)cqdma->pc[i]);
+
+ dev_info(&pdev->dev, "MediaTek CQDMA driver registered\n");
+
+ return 0;
+
+err_unregister:
+ dma_async_device_unregister(dd);
+
+ return err;
+}
+
+static int mtk_cqdma_remove(struct platform_device *pdev)
+{
+ struct mtk_cqdma_device *cqdma = platform_get_drvdata(pdev);
+ struct mtk_cqdma_vchan *vc;
+ unsigned long flags;
+ int i;
+
+ /* kill VC task */
+ for (i = 0; i < cqdma->dma_requests; i++) {
+ vc = &cqdma->vc[i];
+
+ list_del(&vc->vc.chan.device_node);
+ tasklet_kill(&vc->vc.task);
+ }
+
+ /* disable interrupt */
+ for (i = 0; i < cqdma->dma_channels; i++) {
+ spin_lock_irqsave(&cqdma->pc[i]->lock, flags);
+ mtk_dma_clr(cqdma->pc[i], MTK_CQDMA_INT_EN,
+ MTK_CQDMA_INT_EN_BIT);
+ spin_unlock_irqrestore(&cqdma->pc[i]->lock, flags);
+
+ /* Waits for any pending IRQ handlers to complete */
+ synchronize_irq(cqdma->pc[i]->irq);
+
+ tasklet_kill(&cqdma->pc[i]->tasklet);
+ }
+
+ /* disable hardware */
+ mtk_cqdma_hw_deinit(cqdma);
+
+ dma_async_device_unregister(&cqdma->ddev);
+ of_dma_controller_free(pdev->dev.of_node);
+
+ return 0;
+}
+
+static struct platform_driver mtk_cqdma_driver = {
+ .probe = mtk_cqdma_probe,
+ .remove = mtk_cqdma_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = mtk_cqdma_match,
+ },
+};
+module_platform_driver(mtk_cqdma_driver);
+
+MODULE_DESCRIPTION("MediaTek CQDMA Controller Driver");
+MODULE_AUTHOR("Shun-Chih Yu <shun-chih.yu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
^ permalink raw reply related
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