Correct Tegra20 FUSE driver DMA usage
v2 cover Correct Tegra20 FUSE driver DMA usage
Change log:
v2:
- Dropped DT patch as turned out it was incorrect and made things work by luck.
- Now FUSE driver requests DMA channel from the APB DMA driver utilizing DMA channel filter.
- This patchset now depends on the APB DMA driver patch that allows DMA client to issue a non-flow controlled transfers. I haven't included that patch to this patchset since DMA usage is broken anyway right now. It will work once this patchset and APBDMA patch get applied.
Dmitry Osipenko (2):
soc/tegra: fuse: Fix reading registers using DMA on Tegra20 soc/tegra: fuse: Explicitly request DMA channel from APB DMA driver
drivers/soc/tegra/fuse/fuse-tegra.c | 1 + drivers/soc/tegra/fuse/fuse-tegra20.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-)
Signature · 1 line
2.14.1
PATCH v2 1/2 soc/tegra: fuse: Fix reading registers using DMA on Tegra20
In reply to a message not in the archiveDMA config is incorrect, because of it DMA transfer is never issued and tegra20_fuse_read() always returns 0x0.
--- drivers/soc/tegra/fuse/fuse-tegra.c | 1 + drivers/soc/tegra/fuse/fuse-tegra20.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/soc/tegra/fuse/fuse-tegra.c +1 -0
@@ -132,6 +132,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)/* take over the memory region from the early initialization */ res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + fuse->phys = res->start; fuse->base =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (fuse->base))return PTR_ERR (fuse->base);
drivers/soc/tegra/fuse/fuse-tegra20.c +2 -1
@@ -59,7 +59,7 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)mutex_lock (&fuse->apbdma.lock); - fuse->apbdma.config.src_addr = fuse->apbdma.phys +FUSE_BEGIN + offset; + fuse->apbdma.config.src_addr = fuse->phys +FUSE_BEGIN + offset; err =dmaengine_slave_config (fuse->apbdma.chan, &fuse->apbdma.config);if (err)
@@ -119,6 +119,7 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse) fuse->apbdma.config.dst_addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES ; fuse->apbdma.config.src_maxburst =1 ; fuse->apbdma.config.dst_maxburst =1 ; + fuse->apbdma.config.direction =DMA_DEV_TO_MEM ;init_completion (&fuse->apbdma.wait);mutex_init (&fuse->apbdma.lock);
Signature · 1 line
2.14.1
PATCH v2 2/2 soc/tegra: fuse: Explicitly request DMA channel from APB DMA driver
In reply to a message not in the archiveCurrently fuse driver requests DMA channel from an arbitrary DMA device, it is not a problem since there is only one DMA provider for Tegra20 yet, but it will become troublesome once another provider will be added.
--- drivers/soc/tegra/fuse/fuse-tegra20.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/soc/tegra/fuse/fuse-tegra20.c +11 -1
@@ -37,6 +37,11 @@#define FUSE_UID_LOW 0x08#define FUSE_UID_HIGH 0x0c +static const struct of_device_id apbdma_of_match[] = { + { .compatible ="nvidia,tegra20-apbdma" }, + { }, +}; +static u32 tegra20_fuse_read_early (struct tegra_fuse *fuse,unsigned int offset) {return readl_relaxed (fuse->base +FUSE_BEGIN + offset);
@@ -96,6 +101,11 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)return value; } +static bool dma_filter (struct dma_chan *chan,void *filter_param) +{ +return of_match_device (apbdma_of_match, chan->device->dev) !=NULL ; +} +static int tegra20_fuse_probe (struct tegra_fuse *fuse) {dma_cap_mask_t mask;
@@ -103,7 +113,7 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse)dma_cap_zero (mask);dma_cap_set (DMA_SLAVE , mask); - fuse->apbdma.chan =dma_request_channel (mask,NULL ,NULL ); + fuse->apbdma.chan =__dma_request_channel (&mask, dma_filter,NULL );if (!fuse->apbdma.chan)return -EPROBE_DEFER ;
Signature · 1 line
2.14.1
Jon Hunter
Acked-byRe: [PATCH v2 1/2] soc/tegra: fuse: Fix reading registers using DMA on Tegra20
In reply to a message not in the archiveQuoted 35 lines · Dmitry Osipenko
DMA config is incorrect, because of it DMA transfer is never issued and
tegra20_fuse_read()always returns0x0.Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/soc/tegra/fuse/fuse-tegra.c | 1 + drivers/soc/tegra/fuse/fuse-tegra20.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)drivers/soc/tegra/fuse/fuse-tegra.c +1
-0@@ -132,6 +132,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)/* take over the memory region from the early initialization */ res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + fuse->phys = res->start; fuse->base =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (fuse->base))return PTR_ERR (fuse->base);drivers/soc/tegra/fuse/fuse-tegra20.c +1
-1@@ -59,7 +59,7 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)mutex_lock (&fuse->apbdma.lock); - fuse->apbdma.config.src_addr = fuse->apbdma.phys +FUSE_BEGIN + offset; + fuse->apbdma.config.src_addr = fuse->phys +FUSE_BEGIN + offset; err =dmaengine_slave_config (fuse->apbdma.chan, &fuse->apbdma.config);if (err)
drivers/soc/tegra/fuse/fuse-tegra20.c static int tegra20_fuse_probe(struct tegra_fuse *fuse) · line 125
Quoted 7 lines
drivers/soc/tegra/fuse/fuse-tegra20.c +1
-0@@ -119,6 +119,7 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse) fuse->apbdma.config.dst_addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES ; fuse->apbdma.config.src_maxburst =1 ; fuse->apbdma.config.dst_maxburst =1 ; + fuse->apbdma.config.direction =DMA_DEV_TO_MEM ;init_completion (&fuse->apbdma.wait);mutex_init (&fuse->apbdma.lock);
Cheers
Jon
Signature · 1 line
nvpublic
Re: [PATCH v2 2/2] soc/tegra: fuse: Explicitly request DMA channel from APB DMA driver
In reply to a message not in the archiveQuoted 26 lines · Dmitry Osipenko
Currently fuse driver requests DMA channel from an arbitrary DMA device, it is not a problem since there is only one DMA provider for Tegra20 yet, but it will become troublesome once another provider will be added.
Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/soc/tegra/fuse/fuse-tegra20.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)drivers/soc/tegra/fuse/fuse-tegra20.c +5
-0@@ -37,6 +37,11 @@#define FUSE_UID_LOW 0x08#define FUSE_UID_HIGH 0x0c +static const struct of_device_id apbdma_of_match[] = { + { .compatible ="nvidia,tegra20-apbdma" }, + { }, +}; +static u32 tegra20_fuse_read_early (struct tegra_fuse *fuse,unsigned int offset) {return readl_relaxed (fuse->base +FUSE_BEGIN + offset);
drivers/soc/tegra/fuse/fuse-tegra20.c static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) · line 106
Quoted 6 lines
drivers/soc/tegra/fuse/fuse-tegra20.c +3
-0@@ -96,6 +101,11 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)return value; } +static bool dma_filter (struct dma_chan *chan,void *filter_param) +{ +return of_match_device (apbdma_of_match, chan->device->dev) !=NULL ;
Is it simpler just to use of_device_is_compatible() here?
Cheers
Jon
Signature · 1 line
nvpublic
Re: [PATCH v2 2/2] soc/tegra: fuse: Explicitly request DMA channel from APB DMA driver
In reply to a message not in the archiveQuoted 32 lines · Jon Hunter
Quoted 29 lines · Dmitry Osipenko
Currently fuse driver requests DMA channel from an arbitrary DMA device, it is not a problem since there is only one DMA provider for Tegra20 yet, but it will become troublesome once another provider will be added.
Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/soc/tegra/fuse/fuse-tegra20.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)drivers/soc/tegra/fuse/fuse-tegra20.c +5
-0@@ -37,6 +37,11 @@#define FUSE_UID_LOW 0x08#define FUSE_UID_HIGH 0x0c +static const struct of_device_id apbdma_of_match[] = { + { .compatible ="nvidia,tegra20-apbdma" }, + { }, +}; +static u32 tegra20_fuse_read_early (struct tegra_fuse *fuse,unsigned int offset) {return readl_relaxed (fuse->base +FUSE_BEGIN + offset);@@ -96,6 +101,11 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)return value; }
Quoted 6 lines
drivers/soc/tegra/fuse/fuse-tegra20.c static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset) · line 106
Quoted 3 lines
drivers/soc/tegra/fuse/fuse-tegra20.c +3
-0+static bool dma_filter (struct dma_chan *chan,void *filter_param) +{ +return of_match_device (apbdma_of_match, chan->device->dev) !=NULL ;Is it simpler just to use
of_device_is_compatible()here?
Good point! I haven't noticed that function in the OF API.
Re: [PATCH v2 1/2] soc/tegra: fuse: Fix reading registers using DMA on Tegra20
In reply to a message not in the archiveQuoted 42 lines · Jon Hunter
Quoted 40 lines · Dmitry Osipenko
DMA config is incorrect, because of it DMA transfer is never issued and
tegra20_fuse_read()always returns0x0.Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/soc/tegra/fuse/fuse-tegra.c | 1 + drivers/soc/tegra/fuse/fuse-tegra20.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)drivers/soc/tegra/fuse/fuse-tegra.c +1
-0@@ -132,6 +132,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)/* take over the memory region from the early initialization */ res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + fuse->phys = res->start; fuse->base =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (fuse->base))return PTR_ERR (fuse->base);drivers/soc/tegra/fuse/fuse-tegra20.c +2
-1@@ -59,7 +59,7 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)mutex_lock (&fuse->apbdma.lock); - fuse->apbdma.config.src_addr = fuse->apbdma.phys +FUSE_BEGIN + offset; + fuse->apbdma.config.src_addr = fuse->phys +FUSE_BEGIN + offset; err =dmaengine_slave_config (fuse->apbdma.chan, &fuse->apbdma.config);if (err)@@ -119,6 +119,7 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse) fuse->apbdma.config.dst_addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES ; fuse->apbdma.config.src_maxburst =1 ; fuse->apbdma.config.dst_maxburst =1 ; + fuse->apbdma.config.direction =DMA_DEV_TO_MEM ;
Quoted 4 lines
drivers/soc/tegra/fuse/fuse-tegra20.c static int tegra20_fuse_probe(struct tegra_fuse *fuse) · line 125
Quoted 2 lines
drivers/soc/tegra/fuse/fuse-tegra20.c +0
-0init_completion (&fuse->apbdma.wait);mutex_init (&fuse->apbdma.lock);Acked-by Jon Hunter <[email protected]>
BTW, if you do rev this series, then maybe it is worth explicitly setting 'fuse->apbdma.config.device_fc = false'.
Cheers
Jon
Signature · 1 line
nvpublic
Re: [PATCH v2 1/2] soc/tegra: fuse: Fix reading registers using DMA on Tegra20
In reply to a message not in the archiveQuoted 44 lines · Jon Hunter
Quoted 42 lines · Jon Hunter
Quoted 40 lines · Dmitry Osipenko
DMA config is incorrect, because of it DMA transfer is never issued and
tegra20_fuse_read()always returns0x0.Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/soc/tegra/fuse/fuse-tegra.c | 1 + drivers/soc/tegra/fuse/fuse-tegra20.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)drivers/soc/tegra/fuse/fuse-tegra.c +1
-0@@ -132,6 +132,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)/* take over the memory region from the early initialization */ res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); + fuse->phys = res->start; fuse->base =devm_ioremap_resource (&pdev->dev, res);if (IS_ERR (fuse->base))return PTR_ERR (fuse->base);drivers/soc/tegra/fuse/fuse-tegra20.c +2
-1@@ -59,7 +59,7 @@ static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)mutex_lock (&fuse->apbdma.lock); - fuse->apbdma.config.src_addr = fuse->apbdma.phys +FUSE_BEGIN + offset; + fuse->apbdma.config.src_addr = fuse->phys +FUSE_BEGIN + offset; err =dmaengine_slave_config (fuse->apbdma.chan, &fuse->apbdma.config);if (err)@@ -119,6 +119,7 @@ static int tegra20_fuse_probe(struct tegra_fuse *fuse) fuse->apbdma.config.dst_addr_width =DMA_SLAVE_BUSWIDTH_4_BYTES ; fuse->apbdma.config.src_maxburst =1 ; fuse->apbdma.config.dst_maxburst =1 ; + fuse->apbdma.config.direction =DMA_DEV_TO_MEM ;
Quoted 8 lines
Quoted 4 lines
drivers/soc/tegra/fuse/fuse-tegra20.c static int tegra20_fuse_probe(struct tegra_fuse *fuse) · line 125
Quoted 2 lines
drivers/soc/tegra/fuse/fuse-tegra20.c +0
-0init_completion (&fuse->apbdma.wait);mutex_init (&fuse->apbdma.lock);Acked-by Jon Hunter <[email protected]>BTW, if you do rev this series, then maybe it is worth explicitly setting '
fuse->apbdma.config.device_fc= false'.
I'll make v3 for sure. Setting device_fc isn't strictly needed, but it is good to have for expressiveness. I'll add it to v3, thanks.