* [PATCH 2/5] dmaengine: axi-dmac: move clock enable earlier
2020-08-19 7:16 [PATCH 1/5] dmaengine: axi-dmac: move version read in probe Alexandru Ardelean
@ 2020-08-19 7:16 ` Alexandru Ardelean
2020-08-25 11:24 ` Vinod Koul
2020-08-19 7:16 ` [PATCH 3/5] dmaengine: axi-dmac: wrap entire dt parse in a function Alexandru Ardelean
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Alexandru Ardelean @ 2020-08-19 7:16 UTC (permalink / raw)
To: dmaengine, linux-kernel
Cc: vkoul, lars, dan.j.williams, ardeleanalex, Alexandru Ardelean
The clock may also be required to read registers from the IP core (if it is
provided and the driver needs to control it).
So, move it earlier in the probe.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
drivers/dma/dma-axi-dmac.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 088c79137398..07665c60c21b 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -850,6 +850,10 @@ static int axi_dmac_probe(struct platform_device *pdev)
if (IS_ERR(dmac->clk))
return PTR_ERR(dmac->clk);
+ ret = clk_prepare_enable(dmac->clk);
+ if (ret < 0)
+ return ret;
+
INIT_LIST_HEAD(&dmac->chan.active_descs);
of_channels = of_get_child_by_name(pdev->dev.of_node, "adi,channels");
@@ -892,10 +896,6 @@ static int axi_dmac_probe(struct platform_device *pdev)
dmac->chan.vchan.desc_free = axi_dmac_desc_free;
vchan_init(&dmac->chan.vchan, dma_dev);
- ret = clk_prepare_enable(dmac->clk);
- if (ret < 0)
- return ret;
-
version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
ret = axi_dmac_detect_caps(dmac, version);
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/5] dmaengine: axi-dmac: move clock enable earlier
2020-08-19 7:16 ` [PATCH 2/5] dmaengine: axi-dmac: move clock enable earlier Alexandru Ardelean
@ 2020-08-25 11:24 ` Vinod Koul
2020-08-25 12:34 ` Alexandru Ardelean
0 siblings, 1 reply; 8+ messages in thread
From: Vinod Koul @ 2020-08-25 11:24 UTC (permalink / raw)
To: Alexandru Ardelean
Cc: dmaengine, linux-kernel, lars, dan.j.williams, ardeleanalex
On 19-08-20, 10:16, Alexandru Ardelean wrote:
> The clock may also be required to read registers from the IP core (if it is
> provided and the driver needs to control it).
> So, move it earlier in the probe.
>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---
> drivers/dma/dma-axi-dmac.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
> index 088c79137398..07665c60c21b 100644
> --- a/drivers/dma/dma-axi-dmac.c
> +++ b/drivers/dma/dma-axi-dmac.c
> @@ -850,6 +850,10 @@ static int axi_dmac_probe(struct platform_device *pdev)
> if (IS_ERR(dmac->clk))
> return PTR_ERR(dmac->clk);
>
> + ret = clk_prepare_enable(dmac->clk);
> + if (ret < 0)
> + return ret;
> +
> INIT_LIST_HEAD(&dmac->chan.active_descs);
Change is fine, but then you need to jump to err_clk_disable in few
place below this and not return error
>
> of_channels = of_get_child_by_name(pdev->dev.of_node, "adi,channels");
> @@ -892,10 +896,6 @@ static int axi_dmac_probe(struct platform_device *pdev)
> dmac->chan.vchan.desc_free = axi_dmac_desc_free;
> vchan_init(&dmac->chan.vchan, dma_dev);
>
> - ret = clk_prepare_enable(dmac->clk);
> - if (ret < 0)
> - return ret;
> -
> version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
>
> ret = axi_dmac_detect_caps(dmac, version);
> --
> 2.17.1
--
~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/5] dmaengine: axi-dmac: move clock enable earlier
2020-08-25 11:24 ` Vinod Koul
@ 2020-08-25 12:34 ` Alexandru Ardelean
0 siblings, 0 replies; 8+ messages in thread
From: Alexandru Ardelean @ 2020-08-25 12:34 UTC (permalink / raw)
To: Vinod Koul
Cc: Alexandru Ardelean, dmaengine, LKML, Lars-Peter Clausen, dan.j.williams
On Tue, Aug 25, 2020 at 2:24 PM Vinod Koul <vkoul@kernel.org> wrote:
>
> On 19-08-20, 10:16, Alexandru Ardelean wrote:
> > The clock may also be required to read registers from the IP core (if it is
> > provided and the driver needs to control it).
> > So, move it earlier in the probe.
> >
> > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> > ---
> > drivers/dma/dma-axi-dmac.c | 8 ++++----
> > 1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
> > index 088c79137398..07665c60c21b 100644
> > --- a/drivers/dma/dma-axi-dmac.c
> > +++ b/drivers/dma/dma-axi-dmac.c
> > @@ -850,6 +850,10 @@ static int axi_dmac_probe(struct platform_device *pdev)
> > if (IS_ERR(dmac->clk))
> > return PTR_ERR(dmac->clk);
> >
> > + ret = clk_prepare_enable(dmac->clk);
> > + if (ret < 0)
> > + return ret;
> > +
> > INIT_LIST_HEAD(&dmac->chan.active_descs);
>
> Change is fine, but then you need to jump to err_clk_disable in few
> place below this and not return error
oops;
thanks for catching this;
will send a v2
>
> >
> > of_channels = of_get_child_by_name(pdev->dev.of_node, "adi,channels");
> > @@ -892,10 +896,6 @@ static int axi_dmac_probe(struct platform_device *pdev)
> > dmac->chan.vchan.desc_free = axi_dmac_desc_free;
> > vchan_init(&dmac->chan.vchan, dma_dev);
> >
> > - ret = clk_prepare_enable(dmac->clk);
> > - if (ret < 0)
> > - return ret;
> > -
> > version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
> >
> > ret = axi_dmac_detect_caps(dmac, version);
> > --
> > 2.17.1
>
> --
> ~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/5] dmaengine: axi-dmac: wrap entire dt parse in a function
2020-08-19 7:16 [PATCH 1/5] dmaengine: axi-dmac: move version read in probe Alexandru Ardelean
2020-08-19 7:16 ` [PATCH 2/5] dmaengine: axi-dmac: move clock enable earlier Alexandru Ardelean
@ 2020-08-19 7:16 ` Alexandru Ardelean
2020-08-25 11:25 ` Vinod Koul
2020-08-19 7:16 ` [PATCH 4/5] dmaengine: axi-dmac: wrap channel parameter adjust into function Alexandru Ardelean
2020-08-19 7:16 ` [PATCH 5/5] dmaengine: axi-dmac: add support for reading bus attributes from registers Alexandru Ardelean
3 siblings, 1 reply; 8+ messages in thread
From: Alexandru Ardelean @ 2020-08-19 7:16 UTC (permalink / raw)
To: dmaengine, linux-kernel
Cc: vkoul, lars, dan.j.williams, ardeleanalex, Alexandru Ardelean
All these attributes will be read from registers in newer core versions, so
just wrap the logic into a function.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
drivers/dma/dma-axi-dmac.c | 39 ++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 07665c60c21b..473c4a159c89 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -774,6 +774,28 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan,
return 0;
}
+static int axi_dmac_parse_dt(struct device *dev, struct axi_dmac *dmac)
+{
+ struct device_node *of_channels, *of_chan;
+ int ret;
+
+ of_channels = of_get_child_by_name(dev->of_node, "adi,channels");
+ if (of_channels == NULL)
+ return -ENODEV;
+
+ for_each_child_of_node(of_channels, of_chan) {
+ ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan);
+ if (ret) {
+ of_node_put(of_chan);
+ of_node_put(of_channels);
+ return -EINVAL;
+ }
+ }
+ of_node_put(of_channels);
+
+ return 0;
+}
+
static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
{
struct axi_dmac_chan *chan = &dmac->chan;
@@ -823,7 +845,6 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
static int axi_dmac_probe(struct platform_device *pdev)
{
- struct device_node *of_channels, *of_chan;
struct dma_device *dma_dev;
struct axi_dmac *dmac;
struct resource *res;
@@ -856,19 +877,9 @@ static int axi_dmac_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&dmac->chan.active_descs);
- of_channels = of_get_child_by_name(pdev->dev.of_node, "adi,channels");
- if (of_channels == NULL)
- return -ENODEV;
-
- for_each_child_of_node(of_channels, of_chan) {
- ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan);
- if (ret) {
- of_node_put(of_chan);
- of_node_put(of_channels);
- return -EINVAL;
- }
- }
- of_node_put(of_channels);
+ ret = axi_dmac_parse_dt(&pdev->dev, dmac);
+ if (ret < 0)
+ return ret;
pdev->dev.dma_parms = &dmac->dma_parms;
dma_set_max_seg_size(&pdev->dev, UINT_MAX);
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 3/5] dmaengine: axi-dmac: wrap entire dt parse in a function
2020-08-19 7:16 ` [PATCH 3/5] dmaengine: axi-dmac: wrap entire dt parse in a function Alexandru Ardelean
@ 2020-08-25 11:25 ` Vinod Koul
0 siblings, 0 replies; 8+ messages in thread
From: Vinod Koul @ 2020-08-25 11:25 UTC (permalink / raw)
To: Alexandru Ardelean
Cc: dmaengine, linux-kernel, lars, dan.j.williams, ardeleanalex
On 19-08-20, 10:16, Alexandru Ardelean wrote:
> All these attributes will be read from registers in newer core versions, so
> just wrap the logic into a function.
>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---
> drivers/dma/dma-axi-dmac.c | 39 ++++++++++++++++++++++++--------------
> 1 file changed, 25 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
> index 07665c60c21b..473c4a159c89 100644
> --- a/drivers/dma/dma-axi-dmac.c
> +++ b/drivers/dma/dma-axi-dmac.c
> @@ -774,6 +774,28 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan,
> return 0;
> }
>
> +static int axi_dmac_parse_dt(struct device *dev, struct axi_dmac *dmac)
> +{
> + struct device_node *of_channels, *of_chan;
> + int ret;
> +
> + of_channels = of_get_child_by_name(dev->of_node, "adi,channels");
> + if (of_channels == NULL)
> + return -ENODEV;
> +
> + for_each_child_of_node(of_channels, of_chan) {
> + ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan);
> + if (ret) {
> + of_node_put(of_chan);
> + of_node_put(of_channels);
> + return -EINVAL;
> + }
> + }
> + of_node_put(of_channels);
> +
> + return 0;
> +}
> +
> static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
> {
> struct axi_dmac_chan *chan = &dmac->chan;
> @@ -823,7 +845,6 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
>
> static int axi_dmac_probe(struct platform_device *pdev)
> {
> - struct device_node *of_channels, *of_chan;
> struct dma_device *dma_dev;
> struct axi_dmac *dmac;
> struct resource *res;
> @@ -856,19 +877,9 @@ static int axi_dmac_probe(struct platform_device *pdev)
>
> INIT_LIST_HEAD(&dmac->chan.active_descs);
>
> - of_channels = of_get_child_by_name(pdev->dev.of_node, "adi,channels");
> - if (of_channels == NULL)
> - return -ENODEV;
> -
> - for_each_child_of_node(of_channels, of_chan) {
> - ret = axi_dmac_parse_chan_dt(of_chan, &dmac->chan);
> - if (ret) {
> - of_node_put(of_chan);
> - of_node_put(of_channels);
> - return -EINVAL;
> - }
> - }
> - of_node_put(of_channels);
> + ret = axi_dmac_parse_dt(&pdev->dev, dmac);
> + if (ret < 0)
this need to jump to err_clk_disable
> + return ret;
>
> pdev->dev.dma_parms = &dmac->dma_parms;
> dma_set_max_seg_size(&pdev->dev, UINT_MAX);
> --
> 2.17.1
--
~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/5] dmaengine: axi-dmac: wrap channel parameter adjust into function
2020-08-19 7:16 [PATCH 1/5] dmaengine: axi-dmac: move version read in probe Alexandru Ardelean
2020-08-19 7:16 ` [PATCH 2/5] dmaengine: axi-dmac: move clock enable earlier Alexandru Ardelean
2020-08-19 7:16 ` [PATCH 3/5] dmaengine: axi-dmac: wrap entire dt parse in a function Alexandru Ardelean
@ 2020-08-19 7:16 ` Alexandru Ardelean
2020-08-19 7:16 ` [PATCH 5/5] dmaengine: axi-dmac: add support for reading bus attributes from registers Alexandru Ardelean
3 siblings, 0 replies; 8+ messages in thread
From: Alexandru Ardelean @ 2020-08-19 7:16 UTC (permalink / raw)
To: dmaengine, linux-kernel
Cc: vkoul, lars, dan.j.williams, ardeleanalex, Alexandru Ardelean
The channel parameters (which are read from the device-tree) are adjusted
for the DMAEngine framework in the axi_dmac_parse_chan_dt() function, after
they are read from the device-tree.
When we want to read these from registers, we will need to use the same
logic, so this change splits the logic into a separate function.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
drivers/dma/dma-axi-dmac.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 473c4a159c89..95aea2b423ac 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -717,6 +717,20 @@ static const struct regmap_config axi_dmac_regmap_config = {
.writeable_reg = axi_dmac_regmap_rdwr,
};
+static void axi_dmac_adjust_chan_params(struct axi_dmac_chan *chan)
+{
+ 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;
+ else if (!axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
+ chan->direction = DMA_MEM_TO_DEV;
+ else if (axi_dmac_dest_is_mem(chan) && !axi_dmac_src_is_mem(chan))
+ chan->direction = DMA_DEV_TO_MEM;
+ else
+ chan->direction = DMA_DEV_TO_DEV;
+}
+
/*
* The configuration stored in the devicetree matches the configuration
* parameters of the peripheral instance and allows the driver to know which
@@ -760,16 +774,7 @@ static int axi_dmac_parse_chan_dt(struct device_node *of_chan,
return ret;
chan->dest_width = val / 8;
- 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;
- else if (!axi_dmac_dest_is_mem(chan) && axi_dmac_src_is_mem(chan))
- chan->direction = DMA_MEM_TO_DEV;
- else if (axi_dmac_dest_is_mem(chan) && !axi_dmac_src_is_mem(chan))
- chan->direction = DMA_DEV_TO_MEM;
- else
- chan->direction = DMA_DEV_TO_DEV;
+ axi_dmac_adjust_chan_params(chan);
return 0;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] dmaengine: axi-dmac: add support for reading bus attributes from registers
2020-08-19 7:16 [PATCH 1/5] dmaengine: axi-dmac: move version read in probe Alexandru Ardelean
` (2 preceding siblings ...)
2020-08-19 7:16 ` [PATCH 4/5] dmaengine: axi-dmac: wrap channel parameter adjust into function Alexandru Ardelean
@ 2020-08-19 7:16 ` Alexandru Ardelean
3 siblings, 0 replies; 8+ messages in thread
From: Alexandru Ardelean @ 2020-08-19 7:16 UTC (permalink / raw)
To: dmaengine, linux-kernel
Cc: vkoul, lars, dan.j.williams, ardeleanalex, Alexandru Ardelean
Starting with core version 4.3.a the DMA bus attributes can (and should) be
read from the INTERFACE_DESCRIPTION (0x10) register.
For older core versions, this will still need to be provided from the
device-tree.
The bus-type values are identical to the ones stored in the device-trees,
so we just need to read them. Bus-width values are stored in log2 values,
so we just need to use them as shift values to make them equivalent to the
current format.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
drivers/dma/dma-axi-dmac.c | 66 ++++++++++++++++++++++++++++++++++++--
1 file changed, 63 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 95aea2b423ac..417735b6e97b 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -6,6 +6,7 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
@@ -45,6 +46,16 @@
* there is no address than can or needs to be configured for the device side.
*/
+#define AXI_DMAC_REG_INTERFACE_DESC 0x10
+#define AXI_DMAC_DMA_SRC_TYPE_MSK GENMASK(13, 12)
+#define AXI_DMAC_DMA_SRC_TYPE_GET(x) FIELD_GET(AXI_DMAC_DMA_SRC_TYPE_MSK, x)
+#define AXI_DMAC_DMA_SRC_WIDTH_MSK GENMASK(11, 8)
+#define AXI_DMAC_DMA_SRC_WIDTH_GET(x) FIELD_GET(AXI_DMAC_DMA_SRC_WIDTH_MSK, x)
+#define AXI_DMAC_DMA_DST_TYPE_MSK GENMASK(5, 4)
+#define AXI_DMAC_DMA_DST_TYPE_GET(x) FIELD_GET(AXI_DMAC_DMA_DST_TYPE_MSK, x)
+#define AXI_DMAC_DMA_DST_WIDTH_MSK GENMASK(3, 0)
+#define AXI_DMAC_DMA_DST_WIDTH_GET(x) FIELD_GET(AXI_DMAC_DMA_DST_WIDTH_MSK, x)
+
#define AXI_DMAC_REG_IRQ_MASK 0x80
#define AXI_DMAC_REG_IRQ_PENDING 0x84
#define AXI_DMAC_REG_IRQ_SOURCE 0x88
@@ -801,6 +812,51 @@ static int axi_dmac_parse_dt(struct device *dev, struct axi_dmac *dmac)
return 0;
}
+static int axi_dmac_read_chan_config(struct device *dev, struct axi_dmac *dmac)
+{
+ struct axi_dmac_chan *chan = &dmac->chan;
+ unsigned int val, desc;
+
+ desc = axi_dmac_read(dmac, AXI_DMAC_REG_INTERFACE_DESC);
+ if (desc == 0) {
+ dev_err(dev, "DMA interface register reads zero\n");
+ return -EFAULT;
+ }
+
+ val = AXI_DMAC_DMA_SRC_TYPE_GET(desc);
+ if (val > AXI_DMAC_BUS_TYPE_FIFO) {
+ dev_err(dev, "Invalid source bus type read: %d\n", val);
+ return -EINVAL;
+ }
+ chan->src_type = val;
+
+ val = AXI_DMAC_DMA_DST_TYPE_GET(desc);
+ if (val > AXI_DMAC_BUS_TYPE_FIFO) {
+ dev_err(dev, "Invalid destination bus type read: %d\n", val);
+ return -EINVAL;
+ }
+ chan->dest_type = val;
+
+ val = AXI_DMAC_DMA_SRC_WIDTH_GET(desc);
+ if (val == 0) {
+ dev_err(dev, "Source bus width is zero\n");
+ return -EINVAL;
+ }
+ /* widths are stored in log2 */
+ chan->src_width = 1 << val;
+
+ val = AXI_DMAC_DMA_DST_WIDTH_GET(desc);
+ if (val == 0) {
+ dev_err(dev, "Destination bus width is zero\n");
+ return -EINVAL;
+ }
+ chan->dest_width = 1 << val;
+
+ axi_dmac_adjust_chan_params(chan);
+
+ return 0;
+}
+
static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
{
struct axi_dmac_chan *chan = &dmac->chan;
@@ -882,7 +938,13 @@ static int axi_dmac_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&dmac->chan.active_descs);
- ret = axi_dmac_parse_dt(&pdev->dev, dmac);
+ version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
+
+ if (version >= ADI_AXI_PCORE_VER(4, 3, 'a'))
+ ret = axi_dmac_read_chan_config(&pdev->dev, dmac);
+ else
+ ret = axi_dmac_parse_dt(&pdev->dev, dmac);
+
if (ret < 0)
return ret;
@@ -912,8 +974,6 @@ static int axi_dmac_probe(struct platform_device *pdev)
dmac->chan.vchan.desc_free = axi_dmac_desc_free;
vchan_init(&dmac->chan.vchan, dma_dev);
- version = axi_dmac_read(dmac, ADI_AXI_REG_VERSION);
-
ret = axi_dmac_detect_caps(dmac, version);
if (ret)
goto err_clk_disable;
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread