* [PATCH v2 00/16] various fixes and updates for ste_dma40
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri
Hi all,
this series contains many fixes and updates for the ste_dma40 driver.
The first patches of the series were originally sent weeks ago but did not
receive any feedback, so I'm also resending those, but I've rebased everything
on top of v3.8-rc2 to avoid a (trivial) file rename conflict.
Vinod, these should probably end up in the arm-soc tree so they can receive
some testing from drivers using it. Can I have your Acked-by for this?
Thanks,
Fabio
Fabio Baltieri (7):
dmaengine: ste_dma40: add a done queue for completed descriptors
dmaengine: ste_dma40: add missing kernel-doc entry
dmaengine: ste_dma40: minor cosmetic fixes
dmaengine: ste_dma40: minor code readability fixes
dmaengine: ste_dma40: add software lli support
dmaengine: set_dma40: ignore spurious interrupts
dmaengine: set_dma40: balance clock in probe fail code
Gerald Baeza (2):
dmaengine: ste_dma40: support fixed physical channel allocation
dmaengine: ste_dma40: physical channels number correction
Narayanan (1):
dmaengine: ste_dma40: reset priority bit for logical channels
Narayanan G (1):
dmaengine: ste_dma40: don't check for pm_runtime_suspended()
Per Forlin (3):
dmaengine: ste_dma40: use writel_relaxed for lcxa
dmaengine: ste_dma40: set dma max seg size
dmaengine: ste_dma40: limit burst size to 16
Rabin Vincent (1):
dmaengine: ste_dma40: don't allow high priority dest event lines
Tong Liu (1):
dmaengine: ste_dma40: support more than 128 event lines
drivers/dma/ste_dma40.c | 489 +++++++++++++++++++++-------
drivers/dma/ste_dma40_ll.c | 29 +-
drivers/dma/ste_dma40_ll.h | 130 +++++++-
include/linux/platform_data/dma-ste-dma40.h | 13 +
4 files changed, 518 insertions(+), 143 deletions(-)
--
1.7.12.1
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 00/16] various fixes and updates for ste_dma40
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
this series contains many fixes and updates for the ste_dma40 driver.
The first patches of the series were originally sent weeks ago but did not
receive any feedback, so I'm also resending those, but I've rebased everything
on top of v3.8-rc2 to avoid a (trivial) file rename conflict.
Vinod, these should probably end up in the arm-soc tree so they can receive
some testing from drivers using it. Can I have your Acked-by for this?
Thanks,
Fabio
Fabio Baltieri (7):
dmaengine: ste_dma40: add a done queue for completed descriptors
dmaengine: ste_dma40: add missing kernel-doc entry
dmaengine: ste_dma40: minor cosmetic fixes
dmaengine: ste_dma40: minor code readability fixes
dmaengine: ste_dma40: add software lli support
dmaengine: set_dma40: ignore spurious interrupts
dmaengine: set_dma40: balance clock in probe fail code
Gerald Baeza (2):
dmaengine: ste_dma40: support fixed physical channel allocation
dmaengine: ste_dma40: physical channels number correction
Narayanan (1):
dmaengine: ste_dma40: reset priority bit for logical channels
Narayanan G (1):
dmaengine: ste_dma40: don't check for pm_runtime_suspended()
Per Forlin (3):
dmaengine: ste_dma40: use writel_relaxed for lcxa
dmaengine: ste_dma40: set dma max seg size
dmaengine: ste_dma40: limit burst size to 16
Rabin Vincent (1):
dmaengine: ste_dma40: don't allow high priority dest event lines
Tong Liu (1):
dmaengine: ste_dma40: support more than 128 event lines
drivers/dma/ste_dma40.c | 489 +++++++++++++++++++++-------
drivers/dma/ste_dma40_ll.c | 29 +-
drivers/dma/ste_dma40_ll.h | 130 +++++++-
include/linux/platform_data/dma-ste-dma40.h | 13 +
4 files changed, 518 insertions(+), 143 deletions(-)
--
1.7.12.1
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 01/16] dmaengine: ste_dma40: reset priority bit for logical channels
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Narayanan, Fabio Baltieri
From: Narayanan <narayanan.gopalakrishnan@stericsson.com>
This patch sets the SSCFG/SDCFG bit[7] PRI only for physical channel
requests with high priority. For logical channels, this bit will be
zero.
Signed-off-by: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
Reviewed-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40_ll.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 851ad56..d64b72a 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -102,17 +102,18 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS;
dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS;
+ /* Set the priority bit to high for the physical channel */
+ if (cfg->high_priority) {
+ src |= 1 << D40_SREG_CFG_PRI_POS;
+ dst |= 1 << D40_SREG_CFG_PRI_POS;
+ }
+
} else {
/* Logical channel */
dst |= 1 << D40_SREG_CFG_LOG_GIM_POS;
src |= 1 << D40_SREG_CFG_LOG_GIM_POS;
}
- if (cfg->high_priority) {
- src |= 1 << D40_SREG_CFG_PRI_POS;
- dst |= 1 << D40_SREG_CFG_PRI_POS;
- }
-
if (cfg->src_info.big_endian)
src |= 1 << D40_SREG_CFG_LBE_POS;
if (cfg->dst_info.big_endian)
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 01/16] dmaengine: ste_dma40: reset priority bit for logical channels
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Narayanan <narayanan.gopalakrishnan@stericsson.com>
This patch sets the SSCFG/SDCFG bit[7] PRI only for physical channel
requests with high priority. For logical channels, this bit will be
zero.
Signed-off-by: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
Reviewed-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40_ll.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 851ad56..d64b72a 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -102,17 +102,18 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS;
dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS;
+ /* Set the priority bit to high for the physical channel */
+ if (cfg->high_priority) {
+ src |= 1 << D40_SREG_CFG_PRI_POS;
+ dst |= 1 << D40_SREG_CFG_PRI_POS;
+ }
+
} else {
/* Logical channel */
dst |= 1 << D40_SREG_CFG_LOG_GIM_POS;
src |= 1 << D40_SREG_CFG_LOG_GIM_POS;
}
- if (cfg->high_priority) {
- src |= 1 << D40_SREG_CFG_PRI_POS;
- dst |= 1 << D40_SREG_CFG_PRI_POS;
- }
-
if (cfg->src_info.big_endian)
src |= 1 << D40_SREG_CFG_LBE_POS;
if (cfg->dst_info.big_endian)
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 02/16] dmaengine: ste_dma40: use writel_relaxed for lcxa
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Per Forlin, Fabio Baltieri
From: Per Forlin <per.forlin@stericsson.com>
lcpa and lcla are written often and the cache_sync() overhead in writel
is costly, especially for wlan where every single network packet (in RX
mode) corresponds to a separate DMA transfer.
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Reviewed-by: Narayanan Gopalakrishnan <narayanan.gopalakrishnan@stericsson.com>
Reviewed-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40_ll.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index d64b72a..1cfe7ab 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -332,10 +332,10 @@ void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
{
d40_log_lli_link(lli_dst, lli_src, next, flags);
- writel(lli_src->lcsp02, &lcpa[0].lcsp0);
- writel(lli_src->lcsp13, &lcpa[0].lcsp1);
- writel(lli_dst->lcsp02, &lcpa[0].lcsp2);
- writel(lli_dst->lcsp13, &lcpa[0].lcsp3);
+ writel_relaxed(lli_src->lcsp02, &lcpa[0].lcsp0);
+ writel_relaxed(lli_src->lcsp13, &lcpa[0].lcsp1);
+ writel_relaxed(lli_dst->lcsp02, &lcpa[0].lcsp2);
+ writel_relaxed(lli_dst->lcsp13, &lcpa[0].lcsp3);
}
void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
@@ -345,10 +345,10 @@ void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
{
d40_log_lli_link(lli_dst, lli_src, next, flags);
- writel(lli_src->lcsp02, &lcla[0].lcsp02);
- writel(lli_src->lcsp13, &lcla[0].lcsp13);
- writel(lli_dst->lcsp02, &lcla[1].lcsp02);
- writel(lli_dst->lcsp13, &lcla[1].lcsp13);
+ writel_relaxed(lli_src->lcsp02, &lcla[0].lcsp02);
+ writel_relaxed(lli_src->lcsp13, &lcla[0].lcsp13);
+ writel_relaxed(lli_dst->lcsp02, &lcla[1].lcsp02);
+ writel_relaxed(lli_dst->lcsp13, &lcla[1].lcsp13);
}
static void d40_log_fill_lli(struct d40_log_lli *lli,
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 02/16] dmaengine: ste_dma40: use writel_relaxed for lcxa
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Per Forlin <per.forlin@stericsson.com>
lcpa and lcla are written often and the cache_sync() overhead in writel
is costly, especially for wlan where every single network packet (in RX
mode) corresponds to a separate DMA transfer.
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Reviewed-by: Narayanan Gopalakrishnan <narayanan.gopalakrishnan@stericsson.com>
Reviewed-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40_ll.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index d64b72a..1cfe7ab 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -332,10 +332,10 @@ void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
{
d40_log_lli_link(lli_dst, lli_src, next, flags);
- writel(lli_src->lcsp02, &lcpa[0].lcsp0);
- writel(lli_src->lcsp13, &lcpa[0].lcsp1);
- writel(lli_dst->lcsp02, &lcpa[0].lcsp2);
- writel(lli_dst->lcsp13, &lcpa[0].lcsp3);
+ writel_relaxed(lli_src->lcsp02, &lcpa[0].lcsp0);
+ writel_relaxed(lli_src->lcsp13, &lcpa[0].lcsp1);
+ writel_relaxed(lli_dst->lcsp02, &lcpa[0].lcsp2);
+ writel_relaxed(lli_dst->lcsp13, &lcpa[0].lcsp3);
}
void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
@@ -345,10 +345,10 @@ void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
{
d40_log_lli_link(lli_dst, lli_src, next, flags);
- writel(lli_src->lcsp02, &lcla[0].lcsp02);
- writel(lli_src->lcsp13, &lcla[0].lcsp13);
- writel(lli_dst->lcsp02, &lcla[1].lcsp02);
- writel(lli_dst->lcsp13, &lcla[1].lcsp13);
+ writel_relaxed(lli_src->lcsp02, &lcla[0].lcsp02);
+ writel_relaxed(lli_src->lcsp13, &lcla[0].lcsp13);
+ writel_relaxed(lli_dst->lcsp02, &lcla[1].lcsp02);
+ writel_relaxed(lli_dst->lcsp13, &lcla[1].lcsp13);
}
static void d40_log_fill_lli(struct d40_log_lli *lli,
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 03/16] dmaengine: ste_dma40: set dma max seg size
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Per Forlin, Fabio Baltieri
From: Per Forlin <per.forlin@stericsson.com>
Maximum DMA seg size is (0xffff x data_width). If max seg
size is not set it deafults to 64k. This results in failure
if transferring 64k in byte mode.
Large seg sizes may be supported by splitting large transfer.
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 23c5573..f5724d9 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -344,6 +344,7 @@ struct d40_base {
int irq;
int num_phy_chans;
int num_log_chans;
+ struct device_dma_parameters dma_parms;
struct dma_device dma_both;
struct dma_device dma_slave;
struct dma_device dma_memcpy;
@@ -3362,6 +3363,13 @@ static int __init d40_probe(struct platform_device *pdev)
if (err)
goto failure;
+ base->dev->dma_parms = &base->dma_parms;
+ err = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE);
+ if (err) {
+ d40_err(&pdev->dev, "Failed to set dma max seg size\n");
+ goto failure;
+ }
+
d40_hw_init(base);
dev_info(base->dev, "initialized\n");
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 03/16] dmaengine: ste_dma40: set dma max seg size
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Per Forlin <per.forlin@stericsson.com>
Maximum DMA seg size is (0xffff x data_width). If max seg
size is not set it deafults to 64k. This results in failure
if transferring 64k in byte mode.
Large seg sizes may be supported by splitting large transfer.
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 23c5573..f5724d9 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -344,6 +344,7 @@ struct d40_base {
int irq;
int num_phy_chans;
int num_log_chans;
+ struct device_dma_parameters dma_parms;
struct dma_device dma_both;
struct dma_device dma_slave;
struct dma_device dma_memcpy;
@@ -3362,6 +3363,13 @@ static int __init d40_probe(struct platform_device *pdev)
if (err)
goto failure;
+ base->dev->dma_parms = &base->dma_parms;
+ err = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE);
+ if (err) {
+ d40_err(&pdev->dev, "Failed to set dma max seg size\n");
+ goto failure;
+ }
+
d40_hw_init(base);
dev_info(base->dev, "initialized\n");
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 04/16] dmaengine: ste_dma40: limit burst size to 16
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Per Forlin, Fabio Baltieri
From: Per Forlin <per.forlin@stericsson.com>
The client is not aware of the maximum burst size in the dma driver. If
the size exceeds 16 set max to 16.
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index f5724d9..2d0c63d 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2578,6 +2578,14 @@ static int d40_set_runtime_config(struct dma_chan *chan,
return -EINVAL;
}
+ if (src_maxburst > 16) {
+ src_maxburst = 16;
+ dst_maxburst = src_maxburst * src_addr_width / dst_addr_width;
+ } else if (dst_maxburst > 16) {
+ dst_maxburst = 16;
+ src_maxburst = dst_maxburst * dst_addr_width / src_addr_width;
+ }
+
ret = dma40_config_to_halfchannel(d40c, &cfg->src_info,
src_addr_width,
src_maxburst);
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 04/16] dmaengine: ste_dma40: limit burst size to 16
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Per Forlin <per.forlin@stericsson.com>
The client is not aware of the maximum burst size in the dma driver. If
the size exceeds 16 set max to 16.
Signed-off-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index f5724d9..2d0c63d 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2578,6 +2578,14 @@ static int d40_set_runtime_config(struct dma_chan *chan,
return -EINVAL;
}
+ if (src_maxburst > 16) {
+ src_maxburst = 16;
+ dst_maxburst = src_maxburst * src_addr_width / dst_addr_width;
+ } else if (dst_maxburst > 16) {
+ dst_maxburst = 16;
+ src_maxburst = dst_maxburst * dst_addr_width / src_addr_width;
+ }
+
ret = dma40_config_to_halfchannel(d40c, &cfg->src_info,
src_addr_width,
src_maxburst);
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 05/16] dmaengine: ste_dma40: don't check for pm_runtime_suspended()
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Narayanan G, Fabio Baltieri
From: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
The check for runtime suspend is not needed during a regular suspend, as
the framework takes care of this. This fixes the issue of DMA driver
not letting the system to go to deepsleep in the first attempt.
Signed-off-by: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
Reviewed-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 2d0c63d..760576b 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2782,8 +2782,6 @@ static int dma40_pm_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct d40_base *base = platform_get_drvdata(pdev);
int ret = 0;
- if (!pm_runtime_suspended(dev))
- return -EBUSY;
if (base->lcpa_regulator)
ret = regulator_disable(base->lcpa_regulator);
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 05/16] dmaengine: ste_dma40: don't check for pm_runtime_suspended()
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
The check for runtime suspend is not needed during a regular suspend, as
the framework takes care of this. This fixes the issue of DMA driver
not letting the system to go to deepsleep in the first attempt.
Signed-off-by: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
Reviewed-by: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 2d0c63d..760576b 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2782,8 +2782,6 @@ static int dma40_pm_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct d40_base *base = platform_get_drvdata(pdev);
int ret = 0;
- if (!pm_runtime_suspended(dev))
- return -EBUSY;
if (base->lcpa_regulator)
ret = regulator_disable(base->lcpa_regulator);
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 06/16] dmaengine: ste_dma40: don't allow high priority dest event lines
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Rabin Vincent, Fabio Baltieri
From: Rabin Vincent <rabin.vincent@stericsson.com>
Hardware bug: when a logical channel is triggerred by a high priority
destination event line, an extra packet transaction is generated in case
of important data write response latency on previous logical channel A
and if the source transfer of current logical channel B is already
completed and if no other channel with a higher priority than B is
waiting for execution.
Software workaround: do not set the high priority level for the
destination event lines that trigger logical channels.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Reviewed-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 760576b..9f8964a 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2180,11 +2180,24 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
{
bool realtime = d40c->dma_cfg.realtime;
bool highprio = d40c->dma_cfg.high_priority;
- u32 prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1;
u32 event = D40_TYPE_TO_EVENT(dev_type);
u32 group = D40_TYPE_TO_GROUP(dev_type);
u32 bit = 1 << event;
+ u32 prioreg;
+
+ /*
+ * Due to a hardware bug, in some cases a logical channel triggered by
+ * a high priority destination event line can generate extra packet
+ * transactions.
+ *
+ * The workaround is to not set the high priority level for the
+ * destination event lines that trigger logical channels.
+ */
+ if (!src && chan_is_logical(d40c))
+ highprio = false;
+
+ prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
/* Destination event lines are stored in the upper halfword */
if (!src)
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 06/16] dmaengine: ste_dma40: don't allow high priority dest event lines
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Rabin Vincent <rabin.vincent@stericsson.com>
Hardware bug: when a logical channel is triggerred by a high priority
destination event line, an extra packet transaction is generated in case
of important data write response latency on previous logical channel A
and if the source transfer of current logical channel B is already
completed and if no other channel with a higher priority than B is
waiting for execution.
Software workaround: do not set the high priority level for the
destination event lines that trigger logical channels.
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Reviewed-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 760576b..9f8964a 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2180,11 +2180,24 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
{
bool realtime = d40c->dma_cfg.realtime;
bool highprio = d40c->dma_cfg.high_priority;
- u32 prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1;
u32 event = D40_TYPE_TO_EVENT(dev_type);
u32 group = D40_TYPE_TO_GROUP(dev_type);
u32 bit = 1 << event;
+ u32 prioreg;
+
+ /*
+ * Due to a hardware bug, in some cases a logical channel triggered by
+ * a high priority destination event line can generate extra packet
+ * transactions.
+ *
+ * The workaround is to not set the high priority level for the
+ * destination event lines that trigger logical channels.
+ */
+ if (!src && chan_is_logical(d40c))
+ highprio = false;
+
+ prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
/* Destination event lines are stored in the upper halfword */
if (!src)
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 07/16] dmaengine: ste_dma40: support fixed physical channel allocation
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Gerald Baeza, Fabio Baltieri
From: Gerald Baeza <gerald.baeza@stericsson.com>
This patch makes existing use_fixed_channel field (of stedma40_chan_cfg
structure) applicable to physical channels.
Signed-off-by: Gerald Baeza <gerald.baeza@stericsson.com>
Tested-by: Yannick Fertre <yannick.fertre@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 9f8964a..5feab7db9 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1711,10 +1711,12 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
int i;
int j;
int log_num;
+ int num_phy_chans;
bool is_src;
bool is_log = d40c->dma_cfg.mode == STEDMA40_MODE_LOGICAL;
phys = d40c->base->phy_res;
+ num_phy_chans = d40c->base->num_phy_chans;
if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
dev_type = d40c->dma_cfg.src_dev_type;
@@ -1735,12 +1737,19 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
if (!is_log) {
if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
/* Find physical half channel */
- for (i = 0; i < d40c->base->num_phy_chans; i++) {
-
+ if (d40c->dma_cfg.use_fixed_channel) {
+ i = d40c->dma_cfg.phy_channel;
if (d40_alloc_mask_set(&phys[i], is_src,
0, is_log,
first_phy_user))
goto found_phy;
+ } else {
+ for (i = 0; i < num_phy_chans; i++) {
+ if (d40_alloc_mask_set(&phys[i], is_src,
+ 0, is_log,
+ first_phy_user))
+ goto found_phy;
+ }
}
} else
for (j = 0; j < d40c->base->num_phy_chans; j += 8) {
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 07/16] dmaengine: ste_dma40: support fixed physical channel allocation
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Gerald Baeza <gerald.baeza@stericsson.com>
This patch makes existing use_fixed_channel field (of stedma40_chan_cfg
structure) applicable to physical channels.
Signed-off-by: Gerald Baeza <gerald.baeza@stericsson.com>
Tested-by: Yannick Fertre <yannick.fertre@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 9f8964a..5feab7db9 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1711,10 +1711,12 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
int i;
int j;
int log_num;
+ int num_phy_chans;
bool is_src;
bool is_log = d40c->dma_cfg.mode == STEDMA40_MODE_LOGICAL;
phys = d40c->base->phy_res;
+ num_phy_chans = d40c->base->num_phy_chans;
if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
dev_type = d40c->dma_cfg.src_dev_type;
@@ -1735,12 +1737,19 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user)
if (!is_log) {
if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
/* Find physical half channel */
- for (i = 0; i < d40c->base->num_phy_chans; i++) {
-
+ if (d40c->dma_cfg.use_fixed_channel) {
+ i = d40c->dma_cfg.phy_channel;
if (d40_alloc_mask_set(&phys[i], is_src,
0, is_log,
first_phy_user))
goto found_phy;
+ } else {
+ for (i = 0; i < num_phy_chans; i++) {
+ if (d40_alloc_mask_set(&phys[i], is_src,
+ 0, is_log,
+ first_phy_user))
+ goto found_phy;
+ }
}
} else
for (j = 0; j < d40c->base->num_phy_chans; j += 8) {
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 08/16] dmaengine: ste_dma40: physical channels number correction
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Gerald Baeza, Fabio Baltieri
From: Gerald Baeza <gerald.baeza@stericsson.com>
DMAC_ICFG[0:2]=SCHNB only allows to count 'multiple of 4' physical
channels so it was ok with platforms having 8 channels but cannot be
used for next versions (with 10 or 14 channels). This patch allows to
provide the number of physical channels for a DMA device via
platform_data, or still rely on SCHNB if platform_data announces 0
channel.
Signed-off-by: Gerald Baeza <gerald.baeza@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 15 ++++++++++-----
include/linux/platform_data/dma-ste-dma40.h | 4 ++++
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 5feab7db9..ca18117 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3004,14 +3004,21 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
* ? has revision 1
* DB8500v1 has revision 2
* DB8500v2 has revision 3
+ * AP9540v1 has revision 4
+ * DB8540v1 has revision 4
*/
rev = AMBA_REV_BITS(pid);
+ plat_data = pdev->dev.platform_data;
+
/* The number of physical channels on this HW */
- num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
+ if (plat_data->num_of_phy_chans)
+ num_phy_chans = plat_data->num_of_phy_chans;
+ else
+ num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
- dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n",
- rev, res->start);
+ dev_info(&pdev->dev, "hardware revision: %d @ 0x%x with %d physical channels\n",
+ rev, res->start, num_phy_chans);
if (rev < 2) {
d40_err(&pdev->dev, "hardware revision: %d is not supported",
@@ -3019,8 +3026,6 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
goto failure;
}
- plat_data = pdev->dev.platform_data;
-
/* Count the number of logical channels in use */
for (i = 0; i < plat_data->dev_len; i++)
if (plat_data->dev_rx[i] != 0)
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index 9ff93b0..833cb95 100644
--- a/include/linux/platform_data/dma-ste-dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -147,6 +147,9 @@ struct stedma40_chan_cfg {
* @memcpy_conf_log: default configuration of logical channel memcpy
* @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver.
+ * @num_of_phy_chans: The number of physical channels implemented in HW.
+ * 0 means reading the number of channels from DMA HW but this is only valid
+ * for 'multiple of 4' channels, like 8.
*/
struct stedma40_platform_data {
u32 dev_len;
@@ -158,6 +161,7 @@ struct stedma40_platform_data {
struct stedma40_chan_cfg *memcpy_conf_log;
int disabled_channels[STEDMA40_MAX_PHYS];
bool use_esram_lcla;
+ int num_of_phy_chans;
};
#ifdef CONFIG_STE_DMA40
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 08/16] dmaengine: ste_dma40: physical channels number correction
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Gerald Baeza <gerald.baeza@stericsson.com>
DMAC_ICFG[0:2]=SCHNB only allows to count 'multiple of 4' physical
channels so it was ok with platforms having 8 channels but cannot be
used for next versions (with 10 or 14 channels). This patch allows to
provide the number of physical channels for a DMA device via
platform_data, or still rely on SCHNB if platform_data announces 0
channel.
Signed-off-by: Gerald Baeza <gerald.baeza@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 15 ++++++++++-----
include/linux/platform_data/dma-ste-dma40.h | 4 ++++
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 5feab7db9..ca18117 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3004,14 +3004,21 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
* ? has revision 1
* DB8500v1 has revision 2
* DB8500v2 has revision 3
+ * AP9540v1 has revision 4
+ * DB8540v1 has revision 4
*/
rev = AMBA_REV_BITS(pid);
+ plat_data = pdev->dev.platform_data;
+
/* The number of physical channels on this HW */
- num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
+ if (plat_data->num_of_phy_chans)
+ num_phy_chans = plat_data->num_of_phy_chans;
+ else
+ num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4;
- dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n",
- rev, res->start);
+ dev_info(&pdev->dev, "hardware revision: %d @ 0x%x with %d physical channels\n",
+ rev, res->start, num_phy_chans);
if (rev < 2) {
d40_err(&pdev->dev, "hardware revision: %d is not supported",
@@ -3019,8 +3026,6 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
goto failure;
}
- plat_data = pdev->dev.platform_data;
-
/* Count the number of logical channels in use */
for (i = 0; i < plat_data->dev_len; i++)
if (plat_data->dev_rx[i] != 0)
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index 9ff93b0..833cb95 100644
--- a/include/linux/platform_data/dma-ste-dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -147,6 +147,9 @@ struct stedma40_chan_cfg {
* @memcpy_conf_log: default configuration of logical channel memcpy
* @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver.
+ * @num_of_phy_chans: The number of physical channels implemented in HW.
+ * 0 means reading the number of channels from DMA HW but this is only valid
+ * for 'multiple of 4' channels, like 8.
*/
struct stedma40_platform_data {
u32 dev_len;
@@ -158,6 +161,7 @@ struct stedma40_platform_data {
struct stedma40_chan_cfg *memcpy_conf_log;
int disabled_channels[STEDMA40_MAX_PHYS];
bool use_esram_lcla;
+ int num_of_phy_chans;
};
#ifdef CONFIG_STE_DMA40
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 09/16] dmaengine: ste_dma40: support more than 128 event lines
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Tong Liu, Fabio Baltieri
From: Tong Liu <tong.liu@stericsson.com>
U8540 DMA controller is different from u9540 we need define new
registers and use them to support handling more than 128 event lines.
Signed-off-by: Tong Liu <tong.liu@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 306 +++++++++++++++++++++++++++++++++------------
drivers/dma/ste_dma40_ll.h | 130 ++++++++++++++++++-
2 files changed, 355 insertions(+), 81 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ca18117..67e565b 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -53,6 +53,8 @@
#define D40_ALLOC_PHY (1 << 30)
#define D40_ALLOC_LOG_FREE 0
+#define MAX(a, b) (((a) < (b)) ? (b) : (a))
+
/**
* enum 40_command - The different commands and/or statuses.
*
@@ -100,8 +102,19 @@ static u32 d40_backup_regs[] = {
#define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs)
-/* TODO: Check if all these registers have to be saved/restored on dma40 v3 */
-static u32 d40_backup_regs_v3[] = {
+/*
+ * since 9540 and 8540 has the same HW revision
+ * use v4a for 9540 or ealier
+ * use v4b for 8540 or later
+ * HW revision:
+ * DB8500ed has revision 0
+ * DB8500v1 has revision 2
+ * DB8500v2 has revision 3
+ * AP9540v1 has revision 4
+ * DB8540v1 has revision 4
+ * TODO: Check if all these registers have to be saved/restored on dma40 v4a
+ */
+static u32 d40_backup_regs_v4a[] = {
D40_DREG_PSEG1,
D40_DREG_PSEG2,
D40_DREG_PSEG3,
@@ -120,7 +133,32 @@ static u32 d40_backup_regs_v3[] = {
D40_DREG_RCEG4,
};
-#define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3)
+#define BACKUP_REGS_SZ_V4A ARRAY_SIZE(d40_backup_regs_v4a)
+
+static u32 d40_backup_regs_v4b[] = {
+ D40_DREG_CPSEG1,
+ D40_DREG_CPSEG2,
+ D40_DREG_CPSEG3,
+ D40_DREG_CPSEG4,
+ D40_DREG_CPSEG5,
+ D40_DREG_CPCEG1,
+ D40_DREG_CPCEG2,
+ D40_DREG_CPCEG3,
+ D40_DREG_CPCEG4,
+ D40_DREG_CPCEG5,
+ D40_DREG_CRSEG1,
+ D40_DREG_CRSEG2,
+ D40_DREG_CRSEG3,
+ D40_DREG_CRSEG4,
+ D40_DREG_CRSEG5,
+ D40_DREG_CRCEG1,
+ D40_DREG_CRCEG2,
+ D40_DREG_CRCEG3,
+ D40_DREG_CRCEG4,
+ D40_DREG_CRCEG5,
+};
+
+#define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b)
static u32 d40_backup_regs_chan[] = {
D40_CHAN_REG_SSCFG,
@@ -134,6 +172,102 @@ static u32 d40_backup_regs_chan[] = {
};
/**
+ * struct d40_interrupt_lookup - lookup table for interrupt handler
+ *
+ * @src: Interrupt mask register.
+ * @clr: Interrupt clear register.
+ * @is_error: true if this is an error interrupt.
+ * @offset: start delta in the lookup_log_chans in d40_base. If equals to
+ * D40_PHY_CHAN, the lookup_phy_chans shall be used instead.
+ */
+struct d40_interrupt_lookup {
+ u32 src;
+ u32 clr;
+ bool is_error;
+ int offset;
+};
+
+
+static struct d40_interrupt_lookup il_v4a[] = {
+ {D40_DREG_LCTIS0, D40_DREG_LCICR0, false, 0},
+ {D40_DREG_LCTIS1, D40_DREG_LCICR1, false, 32},
+ {D40_DREG_LCTIS2, D40_DREG_LCICR2, false, 64},
+ {D40_DREG_LCTIS3, D40_DREG_LCICR3, false, 96},
+ {D40_DREG_LCEIS0, D40_DREG_LCICR0, true, 0},
+ {D40_DREG_LCEIS1, D40_DREG_LCICR1, true, 32},
+ {D40_DREG_LCEIS2, D40_DREG_LCICR2, true, 64},
+ {D40_DREG_LCEIS3, D40_DREG_LCICR3, true, 96},
+ {D40_DREG_PCTIS, D40_DREG_PCICR, false, D40_PHY_CHAN},
+ {D40_DREG_PCEIS, D40_DREG_PCICR, true, D40_PHY_CHAN},
+};
+
+static struct d40_interrupt_lookup il_v4b[] = {
+ {D40_DREG_CLCTIS1, D40_DREG_CLCICR1, false, 0},
+ {D40_DREG_CLCTIS2, D40_DREG_CLCICR2, false, 32},
+ {D40_DREG_CLCTIS3, D40_DREG_CLCICR3, false, 64},
+ {D40_DREG_CLCTIS4, D40_DREG_CLCICR4, false, 96},
+ {D40_DREG_CLCTIS5, D40_DREG_CLCICR5, false, 128},
+ {D40_DREG_CLCEIS1, D40_DREG_CLCICR1, true, 0},
+ {D40_DREG_CLCEIS2, D40_DREG_CLCICR2, true, 32},
+ {D40_DREG_CLCEIS3, D40_DREG_CLCICR3, true, 64},
+ {D40_DREG_CLCEIS4, D40_DREG_CLCICR4, true, 96},
+ {D40_DREG_CLCEIS5, D40_DREG_CLCICR5, true, 128},
+ {D40_DREG_CPCTIS, D40_DREG_CPCICR, false, D40_PHY_CHAN},
+ {D40_DREG_CPCEIS, D40_DREG_CPCICR, true, D40_PHY_CHAN},
+};
+
+/**
+ * struct d40_reg_val - simple lookup struct
+ *
+ * @reg: The register.
+ * @val: The value that belongs to the register in reg.
+ */
+struct d40_reg_val {
+ unsigned int reg;
+ unsigned int val;
+};
+
+static __initdata struct d40_reg_val dma_init_reg_v4a[] = {
+ /* Clock every part of the DMA block from start */
+ { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
+
+ /* Interrupts on all logical channels */
+ { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCMIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCMIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCMIS3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR0, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS0, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS3, .val = 0xFFFFFFFF}
+};
+static __initdata struct d40_reg_val dma_init_reg_v4b[] = {
+ /* Clock every part of the DMA block from start */
+ { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
+
+ /* Interrupts on all logical channels */
+ { .reg = D40_DREG_CLCMIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS4, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS5, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR4, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR5, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS4, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS5, .val = 0xFFFFFFFF}
+};
+
+/**
* struct d40_lli_pool - Structure for keeping LLIs in memory
*
* @base: Pointer to memory area when the pre_alloc_lli's are not large
@@ -289,6 +423,38 @@ struct d40_chan {
};
/**
+ * struct d40_gen_dmac - generic values to represent u8500/u8540 DMA
+ * controller
+ *
+ * @backup: the pointer to the registers address array for backup
+ * @backup_size: the size of the registers address array for backup
+ * @realtime_en: the realtime enable register
+ * @realtime_clear: the realtime clear register
+ * @high_prio_en: the high priority enable register
+ * @high_prio_clear: the high priority clear register
+ * @interrupt_en: the interrupt enable register
+ * @interrupt_clear: the interrupt clear register
+ * @il: the pointer to struct d40_interrupt_lookup
+ * @il_size: the size of d40_interrupt_lookup array
+ * @init_reg: the pointer to the struct d40_reg_val
+ * @init_reg_size: the size of d40_reg_val array
+ */
+struct d40_gen_dmac {
+ u32 *backup;
+ u32 backup_size;
+ u32 realtime_en;
+ u32 realtime_clear;
+ u32 high_prio_en;
+ u32 high_prio_clear;
+ u32 interrupt_en;
+ u32 interrupt_clear;
+ struct d40_interrupt_lookup *il;
+ u32 il_size;
+ struct d40_reg_val *init_reg;
+ u32 init_reg_size;
+};
+
+/**
* struct d40_base - The big global struct, one for each probe'd instance.
*
* @interrupt_lock: Lock used to make sure one interrupt is handle a time.
@@ -326,11 +492,13 @@ struct d40_chan {
* @desc_slab: cache for descriptors.
* @reg_val_backup: Here the values of some hardware registers are stored
* before the DMA is powered off. They are restored when the power is back on.
- * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and
- * later.
+ * @reg_val_backup_v4: Backup of registers that only exits on dma40 v3 and
+ * later
* @reg_val_backup_chan: Backup data for standard channel parameter registers.
* @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off.
* @initialized: true if the dma has been initialized
+ * @gen_dmac: the struct for generic registers values to represent u8500/8540
+ * DMA controller
*/
struct d40_base {
spinlock_t interrupt_lock;
@@ -362,37 +530,11 @@ struct d40_base {
resource_size_t lcpa_size;
struct kmem_cache *desc_slab;
u32 reg_val_backup[BACKUP_REGS_SZ];
- u32 reg_val_backup_v3[BACKUP_REGS_SZ_V3];
+ u32 reg_val_backup_v4[MAX(BACKUP_REGS_SZ_V4A, BACKUP_REGS_SZ_V4B)];
u32 *reg_val_backup_chan;
u16 gcc_pwr_off_mask;
bool initialized;
-};
-
-/**
- * struct d40_interrupt_lookup - lookup table for interrupt handler
- *
- * @src: Interrupt mask register.
- * @clr: Interrupt clear register.
- * @is_error: true if this is an error interrupt.
- * @offset: start delta in the lookup_log_chans in d40_base. If equals to
- * D40_PHY_CHAN, the lookup_phy_chans shall be used instead.
- */
-struct d40_interrupt_lookup {
- u32 src;
- u32 clr;
- bool is_error;
- int offset;
-};
-
-/**
- * struct d40_reg_val - simple lookup struct
- *
- * @reg: The register.
- * @val: The value that belongs to the register in reg.
- */
-struct d40_reg_val {
- unsigned int reg;
- unsigned int val;
+ struct d40_gen_dmac gen_dmac;
};
static struct device *chan2dev(struct d40_chan *d40c)
@@ -875,11 +1017,11 @@ static void d40_save_restore_registers(struct d40_base *base, bool save)
save);
/* Save/Restore registers only existing on dma40 v3 and later */
- if (base->rev >= 3)
- dma40_backup(base->virtbase, base->reg_val_backup_v3,
- d40_backup_regs_v3,
- ARRAY_SIZE(d40_backup_regs_v3),
- save);
+ if (base->gen_dmac.backup)
+ dma40_backup(base->virtbase, base->reg_val_backup_v4,
+ base->gen_dmac.backup,
+ base->gen_dmac.backup_size,
+ save);
}
#else
static void d40_save_restore_registers(struct d40_base *base, bool save)
@@ -1470,41 +1612,30 @@ err:
static irqreturn_t d40_handle_interrupt(int irq, void *data)
{
- static const struct d40_interrupt_lookup il[] = {
- {D40_DREG_LCTIS0, D40_DREG_LCICR0, false, 0},
- {D40_DREG_LCTIS1, D40_DREG_LCICR1, false, 32},
- {D40_DREG_LCTIS2, D40_DREG_LCICR2, false, 64},
- {D40_DREG_LCTIS3, D40_DREG_LCICR3, false, 96},
- {D40_DREG_LCEIS0, D40_DREG_LCICR0, true, 0},
- {D40_DREG_LCEIS1, D40_DREG_LCICR1, true, 32},
- {D40_DREG_LCEIS2, D40_DREG_LCICR2, true, 64},
- {D40_DREG_LCEIS3, D40_DREG_LCICR3, true, 96},
- {D40_DREG_PCTIS, D40_DREG_PCICR, false, D40_PHY_CHAN},
- {D40_DREG_PCEIS, D40_DREG_PCICR, true, D40_PHY_CHAN},
- };
-
int i;
- u32 regs[ARRAY_SIZE(il)];
u32 idx;
u32 row;
long chan = -1;
struct d40_chan *d40c;
unsigned long flags;
struct d40_base *base = data;
+ u32 regs[base->gen_dmac.il_size];
+ struct d40_interrupt_lookup *il = base->gen_dmac.il;
+ u32 il_size = base->gen_dmac.il_size;
spin_lock_irqsave(&base->interrupt_lock, flags);
/* Read interrupt status of both logical and physical channels */
- for (i = 0; i < ARRAY_SIZE(il); i++)
+ for (i = 0; i < il_size; i++)
regs[i] = readl(base->virtbase + il[i].src);
for (;;) {
chan = find_next_bit((unsigned long *)regs,
- BITS_PER_LONG * ARRAY_SIZE(il), chan + 1);
+ BITS_PER_LONG * il_size, chan + 1);
/* No more set bits found? */
- if (chan == BITS_PER_LONG * ARRAY_SIZE(il))
+ if (chan == BITS_PER_LONG * il_size)
break;
row = chan / BITS_PER_LONG;
@@ -2189,12 +2320,14 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
{
bool realtime = d40c->dma_cfg.realtime;
bool highprio = d40c->dma_cfg.high_priority;
- u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1;
+ u32 rtreg;
u32 event = D40_TYPE_TO_EVENT(dev_type);
u32 group = D40_TYPE_TO_GROUP(dev_type);
u32 bit = 1 << event;
u32 prioreg;
+ struct d40_gen_dmac *dmac = &d40c->base->gen_dmac;
+ rtreg = realtime ? dmac->realtime_en : dmac->realtime_clear;
/*
* Due to a hardware bug, in some cases a logical channel triggered by
* a high priority destination event line can generate extra packet
@@ -2206,7 +2339,7 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
if (!src && chan_is_logical(d40c))
highprio = false;
- prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
+ prioreg = highprio ? dmac->high_prio_en : dmac->high_prio_clear;
/* Destination event lines are stored in the upper halfword */
if (!src)
@@ -3056,6 +3189,36 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
base->phy_chans = ((void *)base) + ALIGN(sizeof(struct d40_base), 4);
base->log_chans = &base->phy_chans[num_phy_chans];
+ if (base->plat_data->num_of_phy_chans == 14) {
+ base->gen_dmac.backup = d40_backup_regs_v4b;
+ base->gen_dmac.backup_size = BACKUP_REGS_SZ_V4B;
+ base->gen_dmac.interrupt_en = D40_DREG_CPCMIS;
+ base->gen_dmac.interrupt_clear = D40_DREG_CPCICR;
+ base->gen_dmac.realtime_en = D40_DREG_CRSEG1;
+ base->gen_dmac.realtime_clear = D40_DREG_CRCEG1;
+ base->gen_dmac.high_prio_en = D40_DREG_CPSEG1;
+ base->gen_dmac.high_prio_clear = D40_DREG_CPCEG1;
+ base->gen_dmac.il = il_v4b;
+ base->gen_dmac.il_size = ARRAY_SIZE(il_v4b);
+ base->gen_dmac.init_reg = dma_init_reg_v4b;
+ base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4b);
+ } else {
+ if (base->rev >= 3) {
+ base->gen_dmac.backup = d40_backup_regs_v4a;
+ base->gen_dmac.backup_size = BACKUP_REGS_SZ_V4A;
+ }
+ base->gen_dmac.interrupt_en = D40_DREG_PCMIS;
+ base->gen_dmac.interrupt_clear = D40_DREG_PCICR;
+ base->gen_dmac.realtime_en = D40_DREG_RSEG1;
+ base->gen_dmac.realtime_clear = D40_DREG_RCEG1;
+ base->gen_dmac.high_prio_en = D40_DREG_PSEG1;
+ base->gen_dmac.high_prio_clear = D40_DREG_PCEG1;
+ base->gen_dmac.il = il_v4a;
+ base->gen_dmac.il_size = ARRAY_SIZE(il_v4a);
+ base->gen_dmac.init_reg = dma_init_reg_v4a;
+ base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4a);
+ }
+
base->phy_res = kzalloc(num_phy_chans * sizeof(struct d40_phy_res),
GFP_KERNEL);
if (!base->phy_res)
@@ -3127,31 +3290,15 @@ failure:
static void __init d40_hw_init(struct d40_base *base)
{
- static struct d40_reg_val dma_init_reg[] = {
- /* Clock every part of the DMA block from start */
- { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
-
- /* Interrupts on all logical channels */
- { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCMIS1, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCMIS2, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCMIS3, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR0, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR1, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR2, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR3, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS0, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS1, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS2, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS3, .val = 0xFFFFFFFF}
- };
int i;
u32 prmseo[2] = {0, 0};
u32 activeo[2] = {0xFFFFFFFF, 0xFFFFFFFF};
u32 pcmis = 0;
u32 pcicr = 0;
+ struct d40_reg_val *dma_init_reg = base->gen_dmac.init_reg;
+ u32 reg_size = base->gen_dmac.init_reg_size;
- for (i = 0; i < ARRAY_SIZE(dma_init_reg); i++)
+ for (i = 0; i < reg_size; i++)
writel(dma_init_reg[i].val,
base->virtbase + dma_init_reg[i].reg);
@@ -3184,11 +3331,14 @@ static void __init d40_hw_init(struct d40_base *base)
writel(activeo[0], base->virtbase + D40_DREG_ACTIVO);
/* Write which interrupt to enable */
- writel(pcmis, base->virtbase + D40_DREG_PCMIS);
+ writel(pcmis, base->virtbase + base->gen_dmac.interrupt_en);
/* Write which interrupt to clear */
- writel(pcicr, base->virtbase + D40_DREG_PCICR);
+ writel(pcicr, base->virtbase + base->gen_dmac.interrupt_clear);
+ /* These are __initdata and cannot be accessed after init */
+ base->gen_dmac.init_reg = NULL;
+ base->gen_dmac.init_reg_size = 0;
}
static int __init d40_lcla_allocate(struct d40_base *base)
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h
index 6d47373..fdde8ef 100644
--- a/drivers/dma/ste_dma40_ll.h
+++ b/drivers/dma/ste_dma40_ll.h
@@ -125,7 +125,7 @@
#define D40_DREG_GCC 0x000
#define D40_DREG_GCC_ENA 0x1
/* This assumes that there are only 4 event groups */
-#define D40_DREG_GCC_ENABLE_ALL 0xff01
+#define D40_DREG_GCC_ENABLE_ALL 0x3ff01
#define D40_DREG_GCC_EVTGRP_POS 8
#define D40_DREG_GCC_SRC 0
#define D40_DREG_GCC_DST 1
@@ -148,14 +148,31 @@
#define D40_DREG_LCPA 0x020
#define D40_DREG_LCLA 0x024
+
+#define D40_DREG_SSEG1 0x030
+#define D40_DREG_SSEG2 0x034
+#define D40_DREG_SSEG3 0x038
+#define D40_DREG_SSEG4 0x03C
+
+#define D40_DREG_SCEG1 0x040
+#define D40_DREG_SCEG2 0x044
+#define D40_DREG_SCEG3 0x048
+#define D40_DREG_SCEG4 0x04C
+
#define D40_DREG_ACTIVE 0x050
#define D40_DREG_ACTIVO 0x054
-#define D40_DREG_FSEB1 0x058
-#define D40_DREG_FSEB2 0x05C
+#define D40_DREG_CIDMOD 0x058
+#define D40_DREG_TCIDV 0x05C
#define D40_DREG_PCMIS 0x060
#define D40_DREG_PCICR 0x064
#define D40_DREG_PCTIS 0x068
#define D40_DREG_PCEIS 0x06C
+
+#define D40_DREG_SPCMIS 0x070
+#define D40_DREG_SPCICR 0x074
+#define D40_DREG_SPCTIS 0x078
+#define D40_DREG_SPCEIS 0x07C
+
#define D40_DREG_LCMIS0 0x080
#define D40_DREG_LCMIS1 0x084
#define D40_DREG_LCMIS2 0x088
@@ -172,6 +189,33 @@
#define D40_DREG_LCEIS1 0x0B4
#define D40_DREG_LCEIS2 0x0B8
#define D40_DREG_LCEIS3 0x0BC
+
+#define D40_DREG_SLCMIS1 0x0C0
+#define D40_DREG_SLCMIS2 0x0C4
+#define D40_DREG_SLCMIS3 0x0C8
+#define D40_DREG_SLCMIS4 0x0CC
+
+#define D40_DREG_SLCICR1 0x0D0
+#define D40_DREG_SLCICR2 0x0D4
+#define D40_DREG_SLCICR3 0x0D8
+#define D40_DREG_SLCICR4 0x0DC
+
+#define D40_DREG_SLCTIS1 0x0E0
+#define D40_DREG_SLCTIS2 0x0E4
+#define D40_DREG_SLCTIS3 0x0E8
+#define D40_DREG_SLCTIS4 0x0EC
+
+#define D40_DREG_SLCEIS1 0x0F0
+#define D40_DREG_SLCEIS2 0x0F4
+#define D40_DREG_SLCEIS3 0x0F8
+#define D40_DREG_SLCEIS4 0x0FC
+
+#define D40_DREG_FSESS1 0x100
+#define D40_DREG_FSESS2 0x104
+
+#define D40_DREG_FSEBS1 0x108
+#define D40_DREG_FSEBS2 0x10C
+
#define D40_DREG_PSEG1 0x110
#define D40_DREG_PSEG2 0x114
#define D40_DREG_PSEG3 0x118
@@ -188,6 +232,86 @@
#define D40_DREG_RCEG2 0x144
#define D40_DREG_RCEG3 0x148
#define D40_DREG_RCEG4 0x14C
+
+#define D40_DREG_PREFOT 0x15C
+#define D40_DREG_EXTCFG 0x160
+
+#define D40_DREG_CPSEG1 0x200
+#define D40_DREG_CPSEG2 0x204
+#define D40_DREG_CPSEG3 0x208
+#define D40_DREG_CPSEG4 0x20C
+#define D40_DREG_CPSEG5 0x210
+
+#define D40_DREG_CPCEG1 0x220
+#define D40_DREG_CPCEG2 0x224
+#define D40_DREG_CPCEG3 0x228
+#define D40_DREG_CPCEG4 0x22C
+#define D40_DREG_CPCEG5 0x230
+
+#define D40_DREG_CRSEG1 0x240
+#define D40_DREG_CRSEG2 0x244
+#define D40_DREG_CRSEG3 0x248
+#define D40_DREG_CRSEG4 0x24C
+#define D40_DREG_CRSEG5 0x250
+
+#define D40_DREG_CRCEG1 0x260
+#define D40_DREG_CRCEG2 0x264
+#define D40_DREG_CRCEG3 0x268
+#define D40_DREG_CRCEG4 0x26C
+#define D40_DREG_CRCEG5 0x270
+
+#define D40_DREG_CFSESS1 0x280
+#define D40_DREG_CFSESS2 0x284
+#define D40_DREG_CFSESS3 0x288
+
+#define D40_DREG_CFSEBS1 0x290
+#define D40_DREG_CFSEBS2 0x294
+#define D40_DREG_CFSEBS3 0x298
+
+#define D40_DREG_CLCMIS1 0x300
+#define D40_DREG_CLCMIS2 0x304
+#define D40_DREG_CLCMIS3 0x308
+#define D40_DREG_CLCMIS4 0x30C
+#define D40_DREG_CLCMIS5 0x310
+
+#define D40_DREG_CLCICR1 0x320
+#define D40_DREG_CLCICR2 0x324
+#define D40_DREG_CLCICR3 0x328
+#define D40_DREG_CLCICR4 0x32C
+#define D40_DREG_CLCICR5 0x330
+
+#define D40_DREG_CLCTIS1 0x340
+#define D40_DREG_CLCTIS2 0x344
+#define D40_DREG_CLCTIS3 0x348
+#define D40_DREG_CLCTIS4 0x34C
+#define D40_DREG_CLCTIS5 0x350
+
+#define D40_DREG_CLCEIS1 0x360
+#define D40_DREG_CLCEIS2 0x364
+#define D40_DREG_CLCEIS3 0x368
+#define D40_DREG_CLCEIS4 0x36C
+#define D40_DREG_CLCEIS5 0x370
+
+#define D40_DREG_CPCMIS 0x380
+#define D40_DREG_CPCICR 0x384
+#define D40_DREG_CPCTIS 0x388
+#define D40_DREG_CPCEIS 0x38C
+
+#define D40_DREG_SCCIDA1 0xE80
+#define D40_DREG_SCCIDA2 0xE90
+#define D40_DREG_SCCIDA3 0xEA0
+#define D40_DREG_SCCIDA4 0xEB0
+#define D40_DREG_SCCIDA5 0xEC0
+
+#define D40_DREG_SCCIDB1 0xE84
+#define D40_DREG_SCCIDB2 0xE94
+#define D40_DREG_SCCIDB3 0xEA4
+#define D40_DREG_SCCIDB4 0xEB4
+#define D40_DREG_SCCIDB5 0xEC4
+
+#define D40_DREG_PRSCCIDA 0xF80
+#define D40_DREG_PRSCCIDB 0xF84
+
#define D40_DREG_STFU 0xFC8
#define D40_DREG_ICFG 0xFCC
#define D40_DREG_PERIPHID0 0xFE0
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 09/16] dmaengine: ste_dma40: support more than 128 event lines
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
From: Tong Liu <tong.liu@stericsson.com>
U8540 DMA controller is different from u9540 we need define new
registers and use them to support handling more than 128 event lines.
Signed-off-by: Tong Liu <tong.liu@stericsson.com>
Reviewed-by: Per Forlin <per.forlin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 306 +++++++++++++++++++++++++++++++++------------
drivers/dma/ste_dma40_ll.h | 130 ++++++++++++++++++-
2 files changed, 355 insertions(+), 81 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ca18117..67e565b 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -53,6 +53,8 @@
#define D40_ALLOC_PHY (1 << 30)
#define D40_ALLOC_LOG_FREE 0
+#define MAX(a, b) (((a) < (b)) ? (b) : (a))
+
/**
* enum 40_command - The different commands and/or statuses.
*
@@ -100,8 +102,19 @@ static u32 d40_backup_regs[] = {
#define BACKUP_REGS_SZ ARRAY_SIZE(d40_backup_regs)
-/* TODO: Check if all these registers have to be saved/restored on dma40 v3 */
-static u32 d40_backup_regs_v3[] = {
+/*
+ * since 9540 and 8540 has the same HW revision
+ * use v4a for 9540 or ealier
+ * use v4b for 8540 or later
+ * HW revision:
+ * DB8500ed has revision 0
+ * DB8500v1 has revision 2
+ * DB8500v2 has revision 3
+ * AP9540v1 has revision 4
+ * DB8540v1 has revision 4
+ * TODO: Check if all these registers have to be saved/restored on dma40 v4a
+ */
+static u32 d40_backup_regs_v4a[] = {
D40_DREG_PSEG1,
D40_DREG_PSEG2,
D40_DREG_PSEG3,
@@ -120,7 +133,32 @@ static u32 d40_backup_regs_v3[] = {
D40_DREG_RCEG4,
};
-#define BACKUP_REGS_SZ_V3 ARRAY_SIZE(d40_backup_regs_v3)
+#define BACKUP_REGS_SZ_V4A ARRAY_SIZE(d40_backup_regs_v4a)
+
+static u32 d40_backup_regs_v4b[] = {
+ D40_DREG_CPSEG1,
+ D40_DREG_CPSEG2,
+ D40_DREG_CPSEG3,
+ D40_DREG_CPSEG4,
+ D40_DREG_CPSEG5,
+ D40_DREG_CPCEG1,
+ D40_DREG_CPCEG2,
+ D40_DREG_CPCEG3,
+ D40_DREG_CPCEG4,
+ D40_DREG_CPCEG5,
+ D40_DREG_CRSEG1,
+ D40_DREG_CRSEG2,
+ D40_DREG_CRSEG3,
+ D40_DREG_CRSEG4,
+ D40_DREG_CRSEG5,
+ D40_DREG_CRCEG1,
+ D40_DREG_CRCEG2,
+ D40_DREG_CRCEG3,
+ D40_DREG_CRCEG4,
+ D40_DREG_CRCEG5,
+};
+
+#define BACKUP_REGS_SZ_V4B ARRAY_SIZE(d40_backup_regs_v4b)
static u32 d40_backup_regs_chan[] = {
D40_CHAN_REG_SSCFG,
@@ -134,6 +172,102 @@ static u32 d40_backup_regs_chan[] = {
};
/**
+ * struct d40_interrupt_lookup - lookup table for interrupt handler
+ *
+ * @src: Interrupt mask register.
+ * @clr: Interrupt clear register.
+ * @is_error: true if this is an error interrupt.
+ * @offset: start delta in the lookup_log_chans in d40_base. If equals to
+ * D40_PHY_CHAN, the lookup_phy_chans shall be used instead.
+ */
+struct d40_interrupt_lookup {
+ u32 src;
+ u32 clr;
+ bool is_error;
+ int offset;
+};
+
+
+static struct d40_interrupt_lookup il_v4a[] = {
+ {D40_DREG_LCTIS0, D40_DREG_LCICR0, false, 0},
+ {D40_DREG_LCTIS1, D40_DREG_LCICR1, false, 32},
+ {D40_DREG_LCTIS2, D40_DREG_LCICR2, false, 64},
+ {D40_DREG_LCTIS3, D40_DREG_LCICR3, false, 96},
+ {D40_DREG_LCEIS0, D40_DREG_LCICR0, true, 0},
+ {D40_DREG_LCEIS1, D40_DREG_LCICR1, true, 32},
+ {D40_DREG_LCEIS2, D40_DREG_LCICR2, true, 64},
+ {D40_DREG_LCEIS3, D40_DREG_LCICR3, true, 96},
+ {D40_DREG_PCTIS, D40_DREG_PCICR, false, D40_PHY_CHAN},
+ {D40_DREG_PCEIS, D40_DREG_PCICR, true, D40_PHY_CHAN},
+};
+
+static struct d40_interrupt_lookup il_v4b[] = {
+ {D40_DREG_CLCTIS1, D40_DREG_CLCICR1, false, 0},
+ {D40_DREG_CLCTIS2, D40_DREG_CLCICR2, false, 32},
+ {D40_DREG_CLCTIS3, D40_DREG_CLCICR3, false, 64},
+ {D40_DREG_CLCTIS4, D40_DREG_CLCICR4, false, 96},
+ {D40_DREG_CLCTIS5, D40_DREG_CLCICR5, false, 128},
+ {D40_DREG_CLCEIS1, D40_DREG_CLCICR1, true, 0},
+ {D40_DREG_CLCEIS2, D40_DREG_CLCICR2, true, 32},
+ {D40_DREG_CLCEIS3, D40_DREG_CLCICR3, true, 64},
+ {D40_DREG_CLCEIS4, D40_DREG_CLCICR4, true, 96},
+ {D40_DREG_CLCEIS5, D40_DREG_CLCICR5, true, 128},
+ {D40_DREG_CPCTIS, D40_DREG_CPCICR, false, D40_PHY_CHAN},
+ {D40_DREG_CPCEIS, D40_DREG_CPCICR, true, D40_PHY_CHAN},
+};
+
+/**
+ * struct d40_reg_val - simple lookup struct
+ *
+ * @reg: The register.
+ * @val: The value that belongs to the register in reg.
+ */
+struct d40_reg_val {
+ unsigned int reg;
+ unsigned int val;
+};
+
+static __initdata struct d40_reg_val dma_init_reg_v4a[] = {
+ /* Clock every part of the DMA block from start */
+ { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
+
+ /* Interrupts on all logical channels */
+ { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCMIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCMIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCMIS3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR0, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCICR3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS0, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_LCTIS3, .val = 0xFFFFFFFF}
+};
+static __initdata struct d40_reg_val dma_init_reg_v4b[] = {
+ /* Clock every part of the DMA block from start */
+ { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
+
+ /* Interrupts on all logical channels */
+ { .reg = D40_DREG_CLCMIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS4, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCMIS5, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR4, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCICR5, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS1, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS2, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS3, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS4, .val = 0xFFFFFFFF},
+ { .reg = D40_DREG_CLCTIS5, .val = 0xFFFFFFFF}
+};
+
+/**
* struct d40_lli_pool - Structure for keeping LLIs in memory
*
* @base: Pointer to memory area when the pre_alloc_lli's are not large
@@ -289,6 +423,38 @@ struct d40_chan {
};
/**
+ * struct d40_gen_dmac - generic values to represent u8500/u8540 DMA
+ * controller
+ *
+ * @backup: the pointer to the registers address array for backup
+ * @backup_size: the size of the registers address array for backup
+ * @realtime_en: the realtime enable register
+ * @realtime_clear: the realtime clear register
+ * @high_prio_en: the high priority enable register
+ * @high_prio_clear: the high priority clear register
+ * @interrupt_en: the interrupt enable register
+ * @interrupt_clear: the interrupt clear register
+ * @il: the pointer to struct d40_interrupt_lookup
+ * @il_size: the size of d40_interrupt_lookup array
+ * @init_reg: the pointer to the struct d40_reg_val
+ * @init_reg_size: the size of d40_reg_val array
+ */
+struct d40_gen_dmac {
+ u32 *backup;
+ u32 backup_size;
+ u32 realtime_en;
+ u32 realtime_clear;
+ u32 high_prio_en;
+ u32 high_prio_clear;
+ u32 interrupt_en;
+ u32 interrupt_clear;
+ struct d40_interrupt_lookup *il;
+ u32 il_size;
+ struct d40_reg_val *init_reg;
+ u32 init_reg_size;
+};
+
+/**
* struct d40_base - The big global struct, one for each probe'd instance.
*
* @interrupt_lock: Lock used to make sure one interrupt is handle a time.
@@ -326,11 +492,13 @@ struct d40_chan {
* @desc_slab: cache for descriptors.
* @reg_val_backup: Here the values of some hardware registers are stored
* before the DMA is powered off. They are restored when the power is back on.
- * @reg_val_backup_v3: Backup of registers that only exits on dma40 v3 and
- * later.
+ * @reg_val_backup_v4: Backup of registers that only exits on dma40 v3 and
+ * later
* @reg_val_backup_chan: Backup data for standard channel parameter registers.
* @gcc_pwr_off_mask: Mask to maintain the channels that can be turned off.
* @initialized: true if the dma has been initialized
+ * @gen_dmac: the struct for generic registers values to represent u8500/8540
+ * DMA controller
*/
struct d40_base {
spinlock_t interrupt_lock;
@@ -362,37 +530,11 @@ struct d40_base {
resource_size_t lcpa_size;
struct kmem_cache *desc_slab;
u32 reg_val_backup[BACKUP_REGS_SZ];
- u32 reg_val_backup_v3[BACKUP_REGS_SZ_V3];
+ u32 reg_val_backup_v4[MAX(BACKUP_REGS_SZ_V4A, BACKUP_REGS_SZ_V4B)];
u32 *reg_val_backup_chan;
u16 gcc_pwr_off_mask;
bool initialized;
-};
-
-/**
- * struct d40_interrupt_lookup - lookup table for interrupt handler
- *
- * @src: Interrupt mask register.
- * @clr: Interrupt clear register.
- * @is_error: true if this is an error interrupt.
- * @offset: start delta in the lookup_log_chans in d40_base. If equals to
- * D40_PHY_CHAN, the lookup_phy_chans shall be used instead.
- */
-struct d40_interrupt_lookup {
- u32 src;
- u32 clr;
- bool is_error;
- int offset;
-};
-
-/**
- * struct d40_reg_val - simple lookup struct
- *
- * @reg: The register.
- * @val: The value that belongs to the register in reg.
- */
-struct d40_reg_val {
- unsigned int reg;
- unsigned int val;
+ struct d40_gen_dmac gen_dmac;
};
static struct device *chan2dev(struct d40_chan *d40c)
@@ -875,11 +1017,11 @@ static void d40_save_restore_registers(struct d40_base *base, bool save)
save);
/* Save/Restore registers only existing on dma40 v3 and later */
- if (base->rev >= 3)
- dma40_backup(base->virtbase, base->reg_val_backup_v3,
- d40_backup_regs_v3,
- ARRAY_SIZE(d40_backup_regs_v3),
- save);
+ if (base->gen_dmac.backup)
+ dma40_backup(base->virtbase, base->reg_val_backup_v4,
+ base->gen_dmac.backup,
+ base->gen_dmac.backup_size,
+ save);
}
#else
static void d40_save_restore_registers(struct d40_base *base, bool save)
@@ -1470,41 +1612,30 @@ err:
static irqreturn_t d40_handle_interrupt(int irq, void *data)
{
- static const struct d40_interrupt_lookup il[] = {
- {D40_DREG_LCTIS0, D40_DREG_LCICR0, false, 0},
- {D40_DREG_LCTIS1, D40_DREG_LCICR1, false, 32},
- {D40_DREG_LCTIS2, D40_DREG_LCICR2, false, 64},
- {D40_DREG_LCTIS3, D40_DREG_LCICR3, false, 96},
- {D40_DREG_LCEIS0, D40_DREG_LCICR0, true, 0},
- {D40_DREG_LCEIS1, D40_DREG_LCICR1, true, 32},
- {D40_DREG_LCEIS2, D40_DREG_LCICR2, true, 64},
- {D40_DREG_LCEIS3, D40_DREG_LCICR3, true, 96},
- {D40_DREG_PCTIS, D40_DREG_PCICR, false, D40_PHY_CHAN},
- {D40_DREG_PCEIS, D40_DREG_PCICR, true, D40_PHY_CHAN},
- };
-
int i;
- u32 regs[ARRAY_SIZE(il)];
u32 idx;
u32 row;
long chan = -1;
struct d40_chan *d40c;
unsigned long flags;
struct d40_base *base = data;
+ u32 regs[base->gen_dmac.il_size];
+ struct d40_interrupt_lookup *il = base->gen_dmac.il;
+ u32 il_size = base->gen_dmac.il_size;
spin_lock_irqsave(&base->interrupt_lock, flags);
/* Read interrupt status of both logical and physical channels */
- for (i = 0; i < ARRAY_SIZE(il); i++)
+ for (i = 0; i < il_size; i++)
regs[i] = readl(base->virtbase + il[i].src);
for (;;) {
chan = find_next_bit((unsigned long *)regs,
- BITS_PER_LONG * ARRAY_SIZE(il), chan + 1);
+ BITS_PER_LONG * il_size, chan + 1);
/* No more set bits found? */
- if (chan == BITS_PER_LONG * ARRAY_SIZE(il))
+ if (chan == BITS_PER_LONG * il_size)
break;
row = chan / BITS_PER_LONG;
@@ -2189,12 +2320,14 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
{
bool realtime = d40c->dma_cfg.realtime;
bool highprio = d40c->dma_cfg.high_priority;
- u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1;
+ u32 rtreg;
u32 event = D40_TYPE_TO_EVENT(dev_type);
u32 group = D40_TYPE_TO_GROUP(dev_type);
u32 bit = 1 << event;
u32 prioreg;
+ struct d40_gen_dmac *dmac = &d40c->base->gen_dmac;
+ rtreg = realtime ? dmac->realtime_en : dmac->realtime_clear;
/*
* Due to a hardware bug, in some cases a logical channel triggered by
* a high priority destination event line can generate extra packet
@@ -2206,7 +2339,7 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
if (!src && chan_is_logical(d40c))
highprio = false;
- prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
+ prioreg = highprio ? dmac->high_prio_en : dmac->high_prio_clear;
/* Destination event lines are stored in the upper halfword */
if (!src)
@@ -3056,6 +3189,36 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
base->phy_chans = ((void *)base) + ALIGN(sizeof(struct d40_base), 4);
base->log_chans = &base->phy_chans[num_phy_chans];
+ if (base->plat_data->num_of_phy_chans == 14) {
+ base->gen_dmac.backup = d40_backup_regs_v4b;
+ base->gen_dmac.backup_size = BACKUP_REGS_SZ_V4B;
+ base->gen_dmac.interrupt_en = D40_DREG_CPCMIS;
+ base->gen_dmac.interrupt_clear = D40_DREG_CPCICR;
+ base->gen_dmac.realtime_en = D40_DREG_CRSEG1;
+ base->gen_dmac.realtime_clear = D40_DREG_CRCEG1;
+ base->gen_dmac.high_prio_en = D40_DREG_CPSEG1;
+ base->gen_dmac.high_prio_clear = D40_DREG_CPCEG1;
+ base->gen_dmac.il = il_v4b;
+ base->gen_dmac.il_size = ARRAY_SIZE(il_v4b);
+ base->gen_dmac.init_reg = dma_init_reg_v4b;
+ base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4b);
+ } else {
+ if (base->rev >= 3) {
+ base->gen_dmac.backup = d40_backup_regs_v4a;
+ base->gen_dmac.backup_size = BACKUP_REGS_SZ_V4A;
+ }
+ base->gen_dmac.interrupt_en = D40_DREG_PCMIS;
+ base->gen_dmac.interrupt_clear = D40_DREG_PCICR;
+ base->gen_dmac.realtime_en = D40_DREG_RSEG1;
+ base->gen_dmac.realtime_clear = D40_DREG_RCEG1;
+ base->gen_dmac.high_prio_en = D40_DREG_PSEG1;
+ base->gen_dmac.high_prio_clear = D40_DREG_PCEG1;
+ base->gen_dmac.il = il_v4a;
+ base->gen_dmac.il_size = ARRAY_SIZE(il_v4a);
+ base->gen_dmac.init_reg = dma_init_reg_v4a;
+ base->gen_dmac.init_reg_size = ARRAY_SIZE(dma_init_reg_v4a);
+ }
+
base->phy_res = kzalloc(num_phy_chans * sizeof(struct d40_phy_res),
GFP_KERNEL);
if (!base->phy_res)
@@ -3127,31 +3290,15 @@ failure:
static void __init d40_hw_init(struct d40_base *base)
{
- static struct d40_reg_val dma_init_reg[] = {
- /* Clock every part of the DMA block from start */
- { .reg = D40_DREG_GCC, .val = D40_DREG_GCC_ENABLE_ALL},
-
- /* Interrupts on all logical channels */
- { .reg = D40_DREG_LCMIS0, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCMIS1, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCMIS2, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCMIS3, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR0, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR1, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR2, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCICR3, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS0, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS1, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS2, .val = 0xFFFFFFFF},
- { .reg = D40_DREG_LCTIS3, .val = 0xFFFFFFFF}
- };
int i;
u32 prmseo[2] = {0, 0};
u32 activeo[2] = {0xFFFFFFFF, 0xFFFFFFFF};
u32 pcmis = 0;
u32 pcicr = 0;
+ struct d40_reg_val *dma_init_reg = base->gen_dmac.init_reg;
+ u32 reg_size = base->gen_dmac.init_reg_size;
- for (i = 0; i < ARRAY_SIZE(dma_init_reg); i++)
+ for (i = 0; i < reg_size; i++)
writel(dma_init_reg[i].val,
base->virtbase + dma_init_reg[i].reg);
@@ -3184,11 +3331,14 @@ static void __init d40_hw_init(struct d40_base *base)
writel(activeo[0], base->virtbase + D40_DREG_ACTIVO);
/* Write which interrupt to enable */
- writel(pcmis, base->virtbase + D40_DREG_PCMIS);
+ writel(pcmis, base->virtbase + base->gen_dmac.interrupt_en);
/* Write which interrupt to clear */
- writel(pcicr, base->virtbase + D40_DREG_PCICR);
+ writel(pcicr, base->virtbase + base->gen_dmac.interrupt_clear);
+ /* These are __initdata and cannot be accessed after init */
+ base->gen_dmac.init_reg = NULL;
+ base->gen_dmac.init_reg_size = 0;
}
static int __init d40_lcla_allocate(struct d40_base *base)
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h
index 6d47373..fdde8ef 100644
--- a/drivers/dma/ste_dma40_ll.h
+++ b/drivers/dma/ste_dma40_ll.h
@@ -125,7 +125,7 @@
#define D40_DREG_GCC 0x000
#define D40_DREG_GCC_ENA 0x1
/* This assumes that there are only 4 event groups */
-#define D40_DREG_GCC_ENABLE_ALL 0xff01
+#define D40_DREG_GCC_ENABLE_ALL 0x3ff01
#define D40_DREG_GCC_EVTGRP_POS 8
#define D40_DREG_GCC_SRC 0
#define D40_DREG_GCC_DST 1
@@ -148,14 +148,31 @@
#define D40_DREG_LCPA 0x020
#define D40_DREG_LCLA 0x024
+
+#define D40_DREG_SSEG1 0x030
+#define D40_DREG_SSEG2 0x034
+#define D40_DREG_SSEG3 0x038
+#define D40_DREG_SSEG4 0x03C
+
+#define D40_DREG_SCEG1 0x040
+#define D40_DREG_SCEG2 0x044
+#define D40_DREG_SCEG3 0x048
+#define D40_DREG_SCEG4 0x04C
+
#define D40_DREG_ACTIVE 0x050
#define D40_DREG_ACTIVO 0x054
-#define D40_DREG_FSEB1 0x058
-#define D40_DREG_FSEB2 0x05C
+#define D40_DREG_CIDMOD 0x058
+#define D40_DREG_TCIDV 0x05C
#define D40_DREG_PCMIS 0x060
#define D40_DREG_PCICR 0x064
#define D40_DREG_PCTIS 0x068
#define D40_DREG_PCEIS 0x06C
+
+#define D40_DREG_SPCMIS 0x070
+#define D40_DREG_SPCICR 0x074
+#define D40_DREG_SPCTIS 0x078
+#define D40_DREG_SPCEIS 0x07C
+
#define D40_DREG_LCMIS0 0x080
#define D40_DREG_LCMIS1 0x084
#define D40_DREG_LCMIS2 0x088
@@ -172,6 +189,33 @@
#define D40_DREG_LCEIS1 0x0B4
#define D40_DREG_LCEIS2 0x0B8
#define D40_DREG_LCEIS3 0x0BC
+
+#define D40_DREG_SLCMIS1 0x0C0
+#define D40_DREG_SLCMIS2 0x0C4
+#define D40_DREG_SLCMIS3 0x0C8
+#define D40_DREG_SLCMIS4 0x0CC
+
+#define D40_DREG_SLCICR1 0x0D0
+#define D40_DREG_SLCICR2 0x0D4
+#define D40_DREG_SLCICR3 0x0D8
+#define D40_DREG_SLCICR4 0x0DC
+
+#define D40_DREG_SLCTIS1 0x0E0
+#define D40_DREG_SLCTIS2 0x0E4
+#define D40_DREG_SLCTIS3 0x0E8
+#define D40_DREG_SLCTIS4 0x0EC
+
+#define D40_DREG_SLCEIS1 0x0F0
+#define D40_DREG_SLCEIS2 0x0F4
+#define D40_DREG_SLCEIS3 0x0F8
+#define D40_DREG_SLCEIS4 0x0FC
+
+#define D40_DREG_FSESS1 0x100
+#define D40_DREG_FSESS2 0x104
+
+#define D40_DREG_FSEBS1 0x108
+#define D40_DREG_FSEBS2 0x10C
+
#define D40_DREG_PSEG1 0x110
#define D40_DREG_PSEG2 0x114
#define D40_DREG_PSEG3 0x118
@@ -188,6 +232,86 @@
#define D40_DREG_RCEG2 0x144
#define D40_DREG_RCEG3 0x148
#define D40_DREG_RCEG4 0x14C
+
+#define D40_DREG_PREFOT 0x15C
+#define D40_DREG_EXTCFG 0x160
+
+#define D40_DREG_CPSEG1 0x200
+#define D40_DREG_CPSEG2 0x204
+#define D40_DREG_CPSEG3 0x208
+#define D40_DREG_CPSEG4 0x20C
+#define D40_DREG_CPSEG5 0x210
+
+#define D40_DREG_CPCEG1 0x220
+#define D40_DREG_CPCEG2 0x224
+#define D40_DREG_CPCEG3 0x228
+#define D40_DREG_CPCEG4 0x22C
+#define D40_DREG_CPCEG5 0x230
+
+#define D40_DREG_CRSEG1 0x240
+#define D40_DREG_CRSEG2 0x244
+#define D40_DREG_CRSEG3 0x248
+#define D40_DREG_CRSEG4 0x24C
+#define D40_DREG_CRSEG5 0x250
+
+#define D40_DREG_CRCEG1 0x260
+#define D40_DREG_CRCEG2 0x264
+#define D40_DREG_CRCEG3 0x268
+#define D40_DREG_CRCEG4 0x26C
+#define D40_DREG_CRCEG5 0x270
+
+#define D40_DREG_CFSESS1 0x280
+#define D40_DREG_CFSESS2 0x284
+#define D40_DREG_CFSESS3 0x288
+
+#define D40_DREG_CFSEBS1 0x290
+#define D40_DREG_CFSEBS2 0x294
+#define D40_DREG_CFSEBS3 0x298
+
+#define D40_DREG_CLCMIS1 0x300
+#define D40_DREG_CLCMIS2 0x304
+#define D40_DREG_CLCMIS3 0x308
+#define D40_DREG_CLCMIS4 0x30C
+#define D40_DREG_CLCMIS5 0x310
+
+#define D40_DREG_CLCICR1 0x320
+#define D40_DREG_CLCICR2 0x324
+#define D40_DREG_CLCICR3 0x328
+#define D40_DREG_CLCICR4 0x32C
+#define D40_DREG_CLCICR5 0x330
+
+#define D40_DREG_CLCTIS1 0x340
+#define D40_DREG_CLCTIS2 0x344
+#define D40_DREG_CLCTIS3 0x348
+#define D40_DREG_CLCTIS4 0x34C
+#define D40_DREG_CLCTIS5 0x350
+
+#define D40_DREG_CLCEIS1 0x360
+#define D40_DREG_CLCEIS2 0x364
+#define D40_DREG_CLCEIS3 0x368
+#define D40_DREG_CLCEIS4 0x36C
+#define D40_DREG_CLCEIS5 0x370
+
+#define D40_DREG_CPCMIS 0x380
+#define D40_DREG_CPCICR 0x384
+#define D40_DREG_CPCTIS 0x388
+#define D40_DREG_CPCEIS 0x38C
+
+#define D40_DREG_SCCIDA1 0xE80
+#define D40_DREG_SCCIDA2 0xE90
+#define D40_DREG_SCCIDA3 0xEA0
+#define D40_DREG_SCCIDA4 0xEB0
+#define D40_DREG_SCCIDA5 0xEC0
+
+#define D40_DREG_SCCIDB1 0xE84
+#define D40_DREG_SCCIDB2 0xE94
+#define D40_DREG_SCCIDB3 0xEA4
+#define D40_DREG_SCCIDB4 0xEB4
+#define D40_DREG_SCCIDB5 0xEC4
+
+#define D40_DREG_PRSCCIDA 0xF80
+#define D40_DREG_PRSCCIDB 0xF84
+
#define D40_DREG_STFU 0xFC8
#define D40_DREG_ICFG 0xFCC
#define D40_DREG_PERIPHID0 0xFE0
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 10/16] dmaengine: ste_dma40: add a done queue for completed descriptors
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri, Rabin Vincent
This is to keep the active queue for only those transfers which are
actually active in the hardware. Descriptors will be moved to the done
queue after they are completed in the hardware (interrupt handler) but
before all the cleanup work has been completed (tasklet).
Mostly based on a previous patch by Rabin Vincent.
Cc: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 37 +++++++++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 67e565b..ff21dcb 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -382,6 +382,7 @@ struct d40_base;
* @client: Cliented owned descriptor list.
* @pending_queue: Submitted jobs, to be issued by issue_pending()
* @active: Active descriptor.
+ * @done: Completed jobs
* @queue: Queued jobs.
* @prepare_queue: Prepared jobs.
* @dma_cfg: The client configuration of this dma channel.
@@ -407,6 +408,7 @@ struct d40_chan {
struct list_head client;
struct list_head pending_queue;
struct list_head active;
+ struct list_head done;
struct list_head queue;
struct list_head prepare_queue;
struct stedma40_chan_cfg dma_cfg;
@@ -754,6 +756,11 @@ static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc)
writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK);
}
+static void d40_desc_done(struct d40_chan *d40c, struct d40_desc *desc)
+{
+ list_add_tail(&desc->node, &d40c->done);
+}
+
static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
{
struct d40_lcla_pool *pool = &chan->base->lcla_pool;
@@ -914,6 +921,14 @@ static struct d40_desc *d40_first_queued(struct d40_chan *d40c)
return d;
}
+static struct d40_desc *d40_first_done(struct d40_chan *d40c)
+{
+ if (list_empty(&d40c->done))
+ return NULL;
+
+ return list_first_entry(&d40c->done, struct d40_desc, node);
+}
+
static int d40_psize_2_burst_size(bool is_log, int psize)
{
if (is_log) {
@@ -1104,6 +1119,12 @@ static void d40_term_all(struct d40_chan *d40c)
struct d40_desc *d40d;
struct d40_desc *_d;
+ /* Release completed descriptors */
+ while ((d40d = d40_first_done(d40c))) {
+ d40_desc_remove(d40d);
+ d40_desc_free(d40c, d40d);
+ }
+
/* Release active descriptors */
while ((d40d = d40_first_active_get(d40c))) {
d40_desc_remove(d40d);
@@ -1541,6 +1562,9 @@ static void dma_tc_handle(struct d40_chan *d40c)
pm_runtime_put_autosuspend(d40c->base->dev);
}
+ d40_desc_remove(d40d);
+ d40_desc_done(d40c, d40d);
+
d40c->pending_tx++;
tasklet_schedule(&d40c->tasklet);
@@ -1556,10 +1580,14 @@ static void dma_tasklet(unsigned long data)
spin_lock_irqsave(&d40c->lock, flags);
- /* Get first active entry from list */
- d40d = d40_first_active_get(d40c);
- if (d40d == NULL)
- goto err;
+ /* Get first entry from the done list */
+ d40d = d40_first_done(d40c);
+ if (d40d == NULL) {
+ /* Check if we have reached here for cyclic job */
+ d40d = d40_first_active_get(d40c);
+ if (d40d == NULL || !d40d->cyclic)
+ goto err;
+ }
if (!d40d->cyclic)
dma_cookie_complete(&d40d->txd);
@@ -2823,6 +2851,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
d40c->log_num = D40_PHY_CHAN;
+ INIT_LIST_HEAD(&d40c->done);
INIT_LIST_HEAD(&d40c->active);
INIT_LIST_HEAD(&d40c->queue);
INIT_LIST_HEAD(&d40c->pending_queue);
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 10/16] dmaengine: ste_dma40: add a done queue for completed descriptors
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
This is to keep the active queue for only those transfers which are
actually active in the hardware. Descriptors will be moved to the done
queue after they are completed in the hardware (interrupt handler) but
before all the cleanup work has been completed (tasklet).
Mostly based on a previous patch by Rabin Vincent.
Cc: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 37 +++++++++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 67e565b..ff21dcb 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -382,6 +382,7 @@ struct d40_base;
* @client: Cliented owned descriptor list.
* @pending_queue: Submitted jobs, to be issued by issue_pending()
* @active: Active descriptor.
+ * @done: Completed jobs
* @queue: Queued jobs.
* @prepare_queue: Prepared jobs.
* @dma_cfg: The client configuration of this dma channel.
@@ -407,6 +408,7 @@ struct d40_chan {
struct list_head client;
struct list_head pending_queue;
struct list_head active;
+ struct list_head done;
struct list_head queue;
struct list_head prepare_queue;
struct stedma40_chan_cfg dma_cfg;
@@ -754,6 +756,11 @@ static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc)
writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK);
}
+static void d40_desc_done(struct d40_chan *d40c, struct d40_desc *desc)
+{
+ list_add_tail(&desc->node, &d40c->done);
+}
+
static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
{
struct d40_lcla_pool *pool = &chan->base->lcla_pool;
@@ -914,6 +921,14 @@ static struct d40_desc *d40_first_queued(struct d40_chan *d40c)
return d;
}
+static struct d40_desc *d40_first_done(struct d40_chan *d40c)
+{
+ if (list_empty(&d40c->done))
+ return NULL;
+
+ return list_first_entry(&d40c->done, struct d40_desc, node);
+}
+
static int d40_psize_2_burst_size(bool is_log, int psize)
{
if (is_log) {
@@ -1104,6 +1119,12 @@ static void d40_term_all(struct d40_chan *d40c)
struct d40_desc *d40d;
struct d40_desc *_d;
+ /* Release completed descriptors */
+ while ((d40d = d40_first_done(d40c))) {
+ d40_desc_remove(d40d);
+ d40_desc_free(d40c, d40d);
+ }
+
/* Release active descriptors */
while ((d40d = d40_first_active_get(d40c))) {
d40_desc_remove(d40d);
@@ -1541,6 +1562,9 @@ static void dma_tc_handle(struct d40_chan *d40c)
pm_runtime_put_autosuspend(d40c->base->dev);
}
+ d40_desc_remove(d40d);
+ d40_desc_done(d40c, d40d);
+
d40c->pending_tx++;
tasklet_schedule(&d40c->tasklet);
@@ -1556,10 +1580,14 @@ static void dma_tasklet(unsigned long data)
spin_lock_irqsave(&d40c->lock, flags);
- /* Get first active entry from list */
- d40d = d40_first_active_get(d40c);
- if (d40d == NULL)
- goto err;
+ /* Get first entry from the done list */
+ d40d = d40_first_done(d40c);
+ if (d40d == NULL) {
+ /* Check if we have reached here for cyclic job */
+ d40d = d40_first_active_get(d40c);
+ if (d40d == NULL || !d40d->cyclic)
+ goto err;
+ }
if (!d40d->cyclic)
dma_cookie_complete(&d40d->txd);
@@ -2823,6 +2851,7 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
d40c->log_num = D40_PHY_CHAN;
+ INIT_LIST_HEAD(&d40c->done);
INIT_LIST_HEAD(&d40c->active);
INIT_LIST_HEAD(&d40c->queue);
INIT_LIST_HEAD(&d40c->pending_queue);
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 11/16] dmaengine: ste_dma40: add missing kernel-doc entry
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
include/linux/platform_data/dma-ste-dma40.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index 833cb95..b99024b 100644
--- a/include/linux/platform_data/dma-ste-dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -147,6 +147,7 @@ struct stedma40_chan_cfg {
* @memcpy_conf_log: default configuration of logical channel memcpy
* @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver.
+ * @use_esram_lcla: flag for mapping the lcla into esram region
* @num_of_phy_chans: The number of physical channels implemented in HW.
* 0 means reading the number of channels from DMA HW but this is only valid
* for 'multiple of 4' channels, like 8.
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 11/16] dmaengine: ste_dma40: add missing kernel-doc entry
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
include/linux/platform_data/dma-ste-dma40.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index 833cb95..b99024b 100644
--- a/include/linux/platform_data/dma-ste-dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -147,6 +147,7 @@ struct stedma40_chan_cfg {
* @memcpy_conf_log: default configuration of logical channel memcpy
* @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver.
+ * @use_esram_lcla: flag for mapping the lcla into esram region
* @num_of_phy_chans: The number of physical channels implemented in HW.
* 0 means reading the number of channels from DMA HW but this is only valid
* for 'multiple of 4' channels, like 8.
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 12/16] dmaengine: ste_dma40: minor cosmetic fixes
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri
This patch contains various non functional cosmetic fixes.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 33 ++++++++++++---------------------
drivers/dma/ste_dma40_ll.c | 2 +-
2 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ff21dcb..623779e 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1609,13 +1609,11 @@ static void dma_tasklet(unsigned long data)
if (async_tx_test_ack(&d40d->txd)) {
d40_desc_remove(d40d);
d40_desc_free(d40c, d40d);
- } else {
- if (!d40d->is_in_client_list) {
- d40_desc_remove(d40d);
- d40_lcla_free_all(d40c, d40d);
- list_add_tail(&d40d->node, &d40c->client);
- d40d->is_in_client_list = true;
- }
+ } else if (!d40d->is_in_client_list) {
+ d40_desc_remove(d40d);
+ d40_lcla_free_all(d40c, d40d);
+ list_add_tail(&d40d->node, &d40c->client);
+ d40d->is_in_client_list = true;
}
}
@@ -2123,7 +2121,6 @@ _exit:
}
-
static u32 stedma40_residue(struct dma_chan *chan)
{
struct d40_chan *d40c =
@@ -2199,7 +2196,6 @@ d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc,
return ret < 0 ? ret : 0;
}
-
static struct d40_desc *
d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
unsigned int sg_len, unsigned long dma_flags)
@@ -2225,7 +2221,6 @@ d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
goto err;
}
-
desc->lli_current = 0;
desc->txd.flags = dma_flags;
desc->txd.tx_submit = d40_tx_submit;
@@ -2274,7 +2269,6 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
return NULL;
}
-
spin_lock_irqsave(&chan->lock, flags);
desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
@@ -2432,11 +2426,11 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)
d40c->lcpa = d40c->base->lcpa_base +
- d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE;
+ d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE;
else
d40c->lcpa = d40c->base->lcpa_base +
- d40c->dma_cfg.dst_dev_type *
- D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
+ d40c->dma_cfg.dst_dev_type *
+ D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
}
dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n",
@@ -2471,7 +2465,6 @@ static void d40_free_chan_resources(struct dma_chan *chan)
return;
}
-
spin_lock_irqsave(&d40c->lock, flags);
err = d40_free_dma(d40c);
@@ -2514,12 +2507,10 @@ d40_prep_memcpy_sg(struct dma_chan *chan,
return d40_prep_sg(chan, src_sg, dst_sg, src_nents, DMA_NONE, dma_flags);
}
-static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
- struct scatterlist *sgl,
- unsigned int sg_len,
- enum dma_transfer_direction direction,
- unsigned long dma_flags,
- void *context)
+static struct dma_async_tx_descriptor *
+d40_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long dma_flags, void *context)
{
if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV)
return NULL;
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 1cfe7ab..7180e0d 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -251,7 +251,7 @@ d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
return lli;
- err:
+err:
return NULL;
}
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 12/16] dmaengine: ste_dma40: minor cosmetic fixes
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
This patch contains various non functional cosmetic fixes.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 33 ++++++++++++---------------------
drivers/dma/ste_dma40_ll.c | 2 +-
2 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index ff21dcb..623779e 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1609,13 +1609,11 @@ static void dma_tasklet(unsigned long data)
if (async_tx_test_ack(&d40d->txd)) {
d40_desc_remove(d40d);
d40_desc_free(d40c, d40d);
- } else {
- if (!d40d->is_in_client_list) {
- d40_desc_remove(d40d);
- d40_lcla_free_all(d40c, d40d);
- list_add_tail(&d40d->node, &d40c->client);
- d40d->is_in_client_list = true;
- }
+ } else if (!d40d->is_in_client_list) {
+ d40_desc_remove(d40d);
+ d40_lcla_free_all(d40c, d40d);
+ list_add_tail(&d40d->node, &d40c->client);
+ d40d->is_in_client_list = true;
}
}
@@ -2123,7 +2121,6 @@ _exit:
}
-
static u32 stedma40_residue(struct dma_chan *chan)
{
struct d40_chan *d40c =
@@ -2199,7 +2196,6 @@ d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc,
return ret < 0 ? ret : 0;
}
-
static struct d40_desc *
d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
unsigned int sg_len, unsigned long dma_flags)
@@ -2225,7 +2221,6 @@ d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
goto err;
}
-
desc->lli_current = 0;
desc->txd.flags = dma_flags;
desc->txd.tx_submit = d40_tx_submit;
@@ -2274,7 +2269,6 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
return NULL;
}
-
spin_lock_irqsave(&chan->lock, flags);
desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
@@ -2432,11 +2426,11 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)
d40c->lcpa = d40c->base->lcpa_base +
- d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE;
+ d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE;
else
d40c->lcpa = d40c->base->lcpa_base +
- d40c->dma_cfg.dst_dev_type *
- D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
+ d40c->dma_cfg.dst_dev_type *
+ D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA;
}
dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n",
@@ -2471,7 +2465,6 @@ static void d40_free_chan_resources(struct dma_chan *chan)
return;
}
-
spin_lock_irqsave(&d40c->lock, flags);
err = d40_free_dma(d40c);
@@ -2514,12 +2507,10 @@ d40_prep_memcpy_sg(struct dma_chan *chan,
return d40_prep_sg(chan, src_sg, dst_sg, src_nents, DMA_NONE, dma_flags);
}
-static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
- struct scatterlist *sgl,
- unsigned int sg_len,
- enum dma_transfer_direction direction,
- unsigned long dma_flags,
- void *context)
+static struct dma_async_tx_descriptor *
+d40_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long dma_flags, void *context)
{
if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV)
return NULL;
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 1cfe7ab..7180e0d 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -251,7 +251,7 @@ d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
return lli;
- err:
+err:
return NULL;
}
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 13/16] dmaengine: ste_dma40: minor code readability fixes
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri
Use internal variables to the cycles to improve code readability, no
functional changes.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 623779e..e317deb 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -639,19 +639,18 @@ static int d40_lcla_alloc_one(struct d40_chan *d40c,
unsigned long flags;
int i;
int ret = -EINVAL;
- int p;
spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags);
- p = d40c->phy_chan->num * D40_LCLA_LINK_PER_EVENT_GRP;
-
/*
* Allocate both src and dst at the same time, therefore the half
* start on 1 since 0 can't be used since zero is used as end marker.
*/
for (i = 1 ; i < D40_LCLA_LINK_PER_EVENT_GRP / 2; i++) {
- if (!d40c->base->lcla_pool.alloc_map[p + i]) {
- d40c->base->lcla_pool.alloc_map[p + i] = d40d;
+ int idx = d40c->phy_chan->num * D40_LCLA_LINK_PER_EVENT_GRP + i;
+
+ if (!d40c->base->lcla_pool.alloc_map[idx]) {
+ d40c->base->lcla_pool.alloc_map[idx] = d40d;
d40d->lcla_alloc++;
ret = i;
break;
@@ -676,10 +675,10 @@ static int d40_lcla_free_all(struct d40_chan *d40c,
spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags);
for (i = 1 ; i < D40_LCLA_LINK_PER_EVENT_GRP / 2; i++) {
- if (d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num *
- D40_LCLA_LINK_PER_EVENT_GRP + i] == d40d) {
- d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num *
- D40_LCLA_LINK_PER_EVENT_GRP + i] = NULL;
+ int idx = d40c->phy_chan->num * D40_LCLA_LINK_PER_EVENT_GRP + i;
+
+ if (d40c->base->lcla_pool.alloc_map[idx] == d40d) {
+ d40c->base->lcla_pool.alloc_map[idx] = NULL;
d40d->lcla_alloc--;
if (d40d->lcla_alloc == 0) {
ret = 0;
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 13/16] dmaengine: ste_dma40: minor code readability fixes
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
Use internal variables to the cycles to improve code readability, no
functional changes.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 623779e..e317deb 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -639,19 +639,18 @@ static int d40_lcla_alloc_one(struct d40_chan *d40c,
unsigned long flags;
int i;
int ret = -EINVAL;
- int p;
spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags);
- p = d40c->phy_chan->num * D40_LCLA_LINK_PER_EVENT_GRP;
-
/*
* Allocate both src and dst at the same time, therefore the half
* start on 1 since 0 can't be used since zero is used as end marker.
*/
for (i = 1 ; i < D40_LCLA_LINK_PER_EVENT_GRP / 2; i++) {
- if (!d40c->base->lcla_pool.alloc_map[p + i]) {
- d40c->base->lcla_pool.alloc_map[p + i] = d40d;
+ int idx = d40c->phy_chan->num * D40_LCLA_LINK_PER_EVENT_GRP + i;
+
+ if (!d40c->base->lcla_pool.alloc_map[idx]) {
+ d40c->base->lcla_pool.alloc_map[idx] = d40d;
d40d->lcla_alloc++;
ret = i;
break;
@@ -676,10 +675,10 @@ static int d40_lcla_free_all(struct d40_chan *d40c,
spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags);
for (i = 1 ; i < D40_LCLA_LINK_PER_EVENT_GRP / 2; i++) {
- if (d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num *
- D40_LCLA_LINK_PER_EVENT_GRP + i] == d40d) {
- d40c->base->lcla_pool.alloc_map[d40c->phy_chan->num *
- D40_LCLA_LINK_PER_EVENT_GRP + i] = NULL;
+ int idx = d40c->phy_chan->num * D40_LCLA_LINK_PER_EVENT_GRP + i;
+
+ if (d40c->base->lcla_pool.alloc_map[idx] == d40d) {
+ d40c->base->lcla_pool.alloc_map[idx] = NULL;
d40d->lcla_alloc--;
if (d40d->lcla_alloc == 0) {
ret = 0;
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 14/16] dmaengine: ste_dma40: add software lli support
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri, Shreshtha Kumar Sahu
This patch add support to manage LLI by SW for select phy channels.
There is a HW issue in certain controllers due to which on certain
occassions HW LLI cannot be used on some physical channels. To avoid
the HW issue on a specific phy channel, the phy channel number can be
added to the list of soft_lli_channels and there after all the transfers
on that channel will use software LLI, for peripheral to memory
transfers.
SoftLLI introduces relink overhead, that could impact performace for
certain use cases.
This is based on a previous patch of Narayanan Gopalakrishnan.
Cc: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 20 +++++++++++++++++++-
include/linux/platform_data/dma-ste-dma40.h | 8 ++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index e317deb..2ecefb7 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -355,6 +355,7 @@ struct d40_lcla_pool {
* @allocated_dst: Same as for src but is dst.
* allocated_dst and allocated_src uses the D40_ALLOC* defines as well as
* event line number.
+ * @use_soft_lli: To mark if the linked lists of channel are managed by SW.
*/
struct d40_phy_res {
spinlock_t lock;
@@ -362,6 +363,7 @@ struct d40_phy_res {
int num;
u32 allocated_src;
u32 allocated_dst;
+ bool use_soft_lli;
};
struct d40_base;
@@ -783,7 +785,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
* can't link back to the one in LCPA space
*/
if (linkback || (lli_len - lli_current > 1)) {
- curr_lcla = d40_lcla_alloc_one(chan, desc);
+ /*
+ * If the channel is expected to use only soft_lli don't
+ * allocate a lcla. This is to avoid a HW issue that exists
+ * in some controller during a peripheral to memory transfer
+ * that uses linked lists.
+ */
+ if (!(chan->phy_chan->use_soft_lli &&
+ chan->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM))
+ curr_lcla = d40_lcla_alloc_one(chan, desc);
+
first_lcla = curr_lcla;
}
@@ -3063,6 +3074,13 @@ static int __init d40_phy_res_init(struct d40_base *base)
num_phy_chans_avail--;
}
+ /* Mark soft_lli channels */
+ for (i = 0; i < base->plat_data->num_of_soft_lli_chans; i++) {
+ int chan = base->plat_data->soft_lli_chans[i];
+
+ base->phy_res[chan].use_soft_lli = true;
+ }
+
dev_info(base->dev, "%d of %d physical DMA channels available\n",
num_phy_chans_avail, base->num_phy_chans);
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index b99024b..4b78101 100644
--- a/include/linux/platform_data/dma-ste-dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -147,6 +147,12 @@ struct stedma40_chan_cfg {
* @memcpy_conf_log: default configuration of logical channel memcpy
* @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver.
+ * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW
+ * which avoids HW bug that exists in some versions of the controller.
+ * SoftLLI introduces relink overhead that could impact performace for
+ * certain use cases.
+ * @num_of_soft_lli_chans: The number of channels that needs to be configured
+ * to use SoftLLI.
* @use_esram_lcla: flag for mapping the lcla into esram region
* @num_of_phy_chans: The number of physical channels implemented in HW.
* 0 means reading the number of channels from DMA HW but this is only valid
@@ -161,6 +167,8 @@ struct stedma40_platform_data {
struct stedma40_chan_cfg *memcpy_conf_phy;
struct stedma40_chan_cfg *memcpy_conf_log;
int disabled_channels[STEDMA40_MAX_PHYS];
+ int *soft_lli_chans;
+ int num_of_soft_lli_chans;
bool use_esram_lcla;
int num_of_phy_chans;
};
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 14/16] dmaengine: ste_dma40: add software lli support
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
This patch add support to manage LLI by SW for select phy channels.
There is a HW issue in certain controllers due to which on certain
occassions HW LLI cannot be used on some physical channels. To avoid
the HW issue on a specific phy channel, the phy channel number can be
added to the list of soft_lli_channels and there after all the transfers
on that channel will use software LLI, for peripheral to memory
transfers.
SoftLLI introduces relink overhead, that could impact performace for
certain use cases.
This is based on a previous patch of Narayanan Gopalakrishnan.
Cc: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 20 +++++++++++++++++++-
include/linux/platform_data/dma-ste-dma40.h | 8 ++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index e317deb..2ecefb7 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -355,6 +355,7 @@ struct d40_lcla_pool {
* @allocated_dst: Same as for src but is dst.
* allocated_dst and allocated_src uses the D40_ALLOC* defines as well as
* event line number.
+ * @use_soft_lli: To mark if the linked lists of channel are managed by SW.
*/
struct d40_phy_res {
spinlock_t lock;
@@ -362,6 +363,7 @@ struct d40_phy_res {
int num;
u32 allocated_src;
u32 allocated_dst;
+ bool use_soft_lli;
};
struct d40_base;
@@ -783,7 +785,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
* can't link back to the one in LCPA space
*/
if (linkback || (lli_len - lli_current > 1)) {
- curr_lcla = d40_lcla_alloc_one(chan, desc);
+ /*
+ * If the channel is expected to use only soft_lli don't
+ * allocate a lcla. This is to avoid a HW issue that exists
+ * in some controller during a peripheral to memory transfer
+ * that uses linked lists.
+ */
+ if (!(chan->phy_chan->use_soft_lli &&
+ chan->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM))
+ curr_lcla = d40_lcla_alloc_one(chan, desc);
+
first_lcla = curr_lcla;
}
@@ -3063,6 +3074,13 @@ static int __init d40_phy_res_init(struct d40_base *base)
num_phy_chans_avail--;
}
+ /* Mark soft_lli channels */
+ for (i = 0; i < base->plat_data->num_of_soft_lli_chans; i++) {
+ int chan = base->plat_data->soft_lli_chans[i];
+
+ base->phy_res[chan].use_soft_lli = true;
+ }
+
dev_info(base->dev, "%d of %d physical DMA channels available\n",
num_phy_chans_avail, base->num_phy_chans);
diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h
index b99024b..4b78101 100644
--- a/include/linux/platform_data/dma-ste-dma40.h
+++ b/include/linux/platform_data/dma-ste-dma40.h
@@ -147,6 +147,12 @@ struct stedma40_chan_cfg {
* @memcpy_conf_log: default configuration of logical channel memcpy
* @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver.
+ * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW
+ * which avoids HW bug that exists in some versions of the controller.
+ * SoftLLI introduces relink overhead that could impact performace for
+ * certain use cases.
+ * @num_of_soft_lli_chans: The number of channels that needs to be configured
+ * to use SoftLLI.
* @use_esram_lcla: flag for mapping the lcla into esram region
* @num_of_phy_chans: The number of physical channels implemented in HW.
* 0 means reading the number of channels from DMA HW but this is only valid
@@ -161,6 +167,8 @@ struct stedma40_platform_data {
struct stedma40_chan_cfg *memcpy_conf_phy;
struct stedma40_chan_cfg *memcpy_conf_log;
int disabled_channels[STEDMA40_MAX_PHYS];
+ int *soft_lli_chans;
+ int num_of_soft_lli_chans;
bool use_esram_lcla;
int num_of_phy_chans;
};
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 15/16] dmaengine: set_dma40: ignore spurious interrupts
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri, Rabin Vincent
Some DMA channels may be used by other cores in the SoC. This patch
modifies the dma interrupt handler to ignore interrupts from unknown
channels.
Cc: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 2ecefb7..a97bbd3 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1677,13 +1677,22 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data)
row = chan / BITS_PER_LONG;
idx = chan & (BITS_PER_LONG - 1);
- /* ACK interrupt */
- writel(1 << idx, base->virtbase + il[row].clr);
-
if (il[row].offset == D40_PHY_CHAN)
d40c = base->lookup_phy_chans[idx];
else
d40c = base->lookup_log_chans[il[row].offset + idx];
+
+ if (!d40c) {
+ /*
+ * No error because this can happen if something else
+ * in the system is using the channel.
+ */
+ continue;
+ }
+
+ /* ACK interrupt */
+ writel(1 << idx, base->virtbase + il[row].clr);
+
spin_lock(&d40c->lock);
if (!il[row].is_error)
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 15/16] dmaengine: set_dma40: ignore spurious interrupts
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
Some DMA channels may be used by other cores in the SoC. This patch
modifies the dma interrupt handler to ignore interrupts from unknown
channels.
Cc: Rabin Vincent <rabin.vincent@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 2ecefb7..a97bbd3 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1677,13 +1677,22 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data)
row = chan / BITS_PER_LONG;
idx = chan & (BITS_PER_LONG - 1);
- /* ACK interrupt */
- writel(1 << idx, base->virtbase + il[row].clr);
-
if (il[row].offset == D40_PHY_CHAN)
d40c = base->lookup_phy_chans[idx];
else
d40c = base->lookup_log_chans[il[row].offset + idx];
+
+ if (!d40c) {
+ /*
+ * No error because this can happen if something else
+ * in the system is using the channel.
+ */
+ continue;
+ }
+
+ /* ACK interrupt */
+ writel(1 << idx, base->virtbase + il[row].clr);
+
spin_lock(&d40c->lock);
if (!il[row].is_error)
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 16/16] dmaengine: set_dma40: balance clock in probe fail code
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 11:21 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: Vinod Koul
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel, Fabio Baltieri
Clock code was changed to use clk_prepare_enable in:
b707c65 dma/ste_dma40: Fixup clock usage during probe
but clk_disable on probe fail path was not updated. This patch fix this
by using clk_disable_unprepare in place of clk_disable.
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index a97bbd3..d77d41d 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3634,7 +3634,7 @@ failure:
release_mem_region(base->phy_start,
base->phy_size);
if (base->clk) {
- clk_disable(base->clk);
+ clk_disable_unprepare(base->clk);
clk_put(base->clk);
}
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* [PATCH 16/16] dmaengine: set_dma40: balance clock in probe fail code
@ 2013-01-07 11:21 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 11:21 UTC (permalink / raw)
To: linux-arm-kernel
Clock code was changed to use clk_prepare_enable in:
b707c65 dma/ste_dma40: Fixup clock usage during probe
but clk_disable on probe fail path was not updated. This patch fix this
by using clk_disable_unprepare in place of clk_disable.
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
drivers/dma/ste_dma40.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index a97bbd3..d77d41d 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -3634,7 +3634,7 @@ failure:
release_mem_region(base->phy_start,
base->phy_size);
if (base->clk) {
- clk_disable(base->clk);
+ clk_disable_unprepare(base->clk);
clk_put(base->clk);
}
--
1.7.12.1
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 00/16] various fixes and updates for ste_dma40
2013-01-07 11:21 ` Fabio Baltieri
@ 2013-01-07 14:33 ` Vinod Koul
-1 siblings, 0 replies; 38+ messages in thread
From: Vinod Koul @ 2013-01-07 14:33 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Dan Williams, Linus Walleij, Srinidhi Kasagar, linux-arm-kernel,
linux-kernel
On Mon, Jan 07, 2013 at 12:21:42PM +0100, Fabio Baltieri wrote:
> Hi all,
>
> this series contains many fixes and updates for the ste_dma40 driver.
>
> The first patches of the series were originally sent weeks ago but did not
> receive any feedback, so I'm also resending those, but I've rebased everything
> on top of v3.8-rc2 to avoid a (trivial) file rename conflict.
>
> Vinod, these should probably end up in the arm-soc tree so they can receive
> some testing from drivers using it. Can I have your Acked-by for this?
Sure the patchset looks fine by me
Acked-by: Vinod Koul <vinod.koul@intel.com>
>
> Thanks,
> Fabio
>
>
> Fabio Baltieri (7):
> dmaengine: ste_dma40: add a done queue for completed descriptors
> dmaengine: ste_dma40: add missing kernel-doc entry
> dmaengine: ste_dma40: minor cosmetic fixes
> dmaengine: ste_dma40: minor code readability fixes
> dmaengine: ste_dma40: add software lli support
> dmaengine: set_dma40: ignore spurious interrupts
> dmaengine: set_dma40: balance clock in probe fail code
>
> Gerald Baeza (2):
> dmaengine: ste_dma40: support fixed physical channel allocation
> dmaengine: ste_dma40: physical channels number correction
>
> Narayanan (1):
> dmaengine: ste_dma40: reset priority bit for logical channels
>
> Narayanan G (1):
> dmaengine: ste_dma40: don't check for pm_runtime_suspended()
>
> Per Forlin (3):
> dmaengine: ste_dma40: use writel_relaxed for lcxa
> dmaengine: ste_dma40: set dma max seg size
> dmaengine: ste_dma40: limit burst size to 16
>
> Rabin Vincent (1):
> dmaengine: ste_dma40: don't allow high priority dest event lines
>
> Tong Liu (1):
> dmaengine: ste_dma40: support more than 128 event lines
>
> drivers/dma/ste_dma40.c | 489 +++++++++++++++++++++-------
> drivers/dma/ste_dma40_ll.c | 29 +-
> drivers/dma/ste_dma40_ll.h | 130 +++++++-
> include/linux/platform_data/dma-ste-dma40.h | 13 +
> 4 files changed, 518 insertions(+), 143 deletions(-)
>
> --
> 1.7.12.1
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 00/16] various fixes and updates for ste_dma40
@ 2013-01-07 14:33 ` Vinod Koul
0 siblings, 0 replies; 38+ messages in thread
From: Vinod Koul @ 2013-01-07 14:33 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jan 07, 2013 at 12:21:42PM +0100, Fabio Baltieri wrote:
> Hi all,
>
> this series contains many fixes and updates for the ste_dma40 driver.
>
> The first patches of the series were originally sent weeks ago but did not
> receive any feedback, so I'm also resending those, but I've rebased everything
> on top of v3.8-rc2 to avoid a (trivial) file rename conflict.
>
> Vinod, these should probably end up in the arm-soc tree so they can receive
> some testing from drivers using it. Can I have your Acked-by for this?
Sure the patchset looks fine by me
Acked-by: Vinod Koul <vinod.koul@intel.com>
>
> Thanks,
> Fabio
>
>
> Fabio Baltieri (7):
> dmaengine: ste_dma40: add a done queue for completed descriptors
> dmaengine: ste_dma40: add missing kernel-doc entry
> dmaengine: ste_dma40: minor cosmetic fixes
> dmaengine: ste_dma40: minor code readability fixes
> dmaengine: ste_dma40: add software lli support
> dmaengine: set_dma40: ignore spurious interrupts
> dmaengine: set_dma40: balance clock in probe fail code
>
> Gerald Baeza (2):
> dmaengine: ste_dma40: support fixed physical channel allocation
> dmaengine: ste_dma40: physical channels number correction
>
> Narayanan (1):
> dmaengine: ste_dma40: reset priority bit for logical channels
>
> Narayanan G (1):
> dmaengine: ste_dma40: don't check for pm_runtime_suspended()
>
> Per Forlin (3):
> dmaengine: ste_dma40: use writel_relaxed for lcxa
> dmaengine: ste_dma40: set dma max seg size
> dmaengine: ste_dma40: limit burst size to 16
>
> Rabin Vincent (1):
> dmaengine: ste_dma40: don't allow high priority dest event lines
>
> Tong Liu (1):
> dmaengine: ste_dma40: support more than 128 event lines
>
> drivers/dma/ste_dma40.c | 489 +++++++++++++++++++++-------
> drivers/dma/ste_dma40_ll.c | 29 +-
> drivers/dma/ste_dma40_ll.h | 130 +++++++-
> include/linux/platform_data/dma-ste-dma40.h | 13 +
> 4 files changed, 518 insertions(+), 143 deletions(-)
>
> --
> 1.7.12.1
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 00/16] various fixes and updates for ste_dma40
2013-01-07 14:33 ` Vinod Koul
@ 2013-01-07 16:59 ` Fabio Baltieri
-1 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 16:59 UTC (permalink / raw)
To: Vinod Koul, Linus Walleij
Cc: Dan Williams, Srinidhi Kasagar, linux-arm-kernel, linux-kernel
On Mon, Jan 07, 2013 at 06:33:56AM -0800, Vinod Koul wrote:
> On Mon, Jan 07, 2013 at 12:21:42PM +0100, Fabio Baltieri wrote:
> > Hi all,
> >
> > this series contains many fixes and updates for the ste_dma40 driver.
> >
> > The first patches of the series were originally sent weeks ago but did not
> > receive any feedback, so I'm also resending those, but I've rebased everything
> > on top of v3.8-rc2 to avoid a (trivial) file rename conflict.
> >
> > Vinod, these should probably end up in the arm-soc tree so they can receive
> > some testing from drivers using it. Can I have your Acked-by for this?
> Sure the patchset looks fine by me
>
> Acked-by: Vinod Koul <vinod.koul@intel.com>
Thanks Vinod!
Linus, will you pick this up in ste-next for arm-soc?
Thanks,
Fabio
--
Fabio Baltieri
^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 00/16] various fixes and updates for ste_dma40
@ 2013-01-07 16:59 ` Fabio Baltieri
0 siblings, 0 replies; 38+ messages in thread
From: Fabio Baltieri @ 2013-01-07 16:59 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jan 07, 2013 at 06:33:56AM -0800, Vinod Koul wrote:
> On Mon, Jan 07, 2013 at 12:21:42PM +0100, Fabio Baltieri wrote:
> > Hi all,
> >
> > this series contains many fixes and updates for the ste_dma40 driver.
> >
> > The first patches of the series were originally sent weeks ago but did not
> > receive any feedback, so I'm also resending those, but I've rebased everything
> > on top of v3.8-rc2 to avoid a (trivial) file rename conflict.
> >
> > Vinod, these should probably end up in the arm-soc tree so they can receive
> > some testing from drivers using it. Can I have your Acked-by for this?
> Sure the patchset looks fine by me
>
> Acked-by: Vinod Koul <vinod.koul@intel.com>
Thanks Vinod!
Linus, will you pick this up in ste-next for arm-soc?
Thanks,
Fabio
--
Fabio Baltieri
^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2013-01-07 16:59 UTC | newest]
Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-07 11:21 [PATCH v2 00/16] various fixes and updates for ste_dma40 Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 01/16] dmaengine: ste_dma40: reset priority bit for logical channels Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 02/16] dmaengine: ste_dma40: use writel_relaxed for lcxa Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 03/16] dmaengine: ste_dma40: set dma max seg size Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 04/16] dmaengine: ste_dma40: limit burst size to 16 Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 05/16] dmaengine: ste_dma40: don't check for pm_runtime_suspended() Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 06/16] dmaengine: ste_dma40: don't allow high priority dest event lines Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 07/16] dmaengine: ste_dma40: support fixed physical channel allocation Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 08/16] dmaengine: ste_dma40: physical channels number correction Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 09/16] dmaengine: ste_dma40: support more than 128 event lines Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 10/16] dmaengine: ste_dma40: add a done queue for completed descriptors Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 11/16] dmaengine: ste_dma40: add missing kernel-doc entry Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 12/16] dmaengine: ste_dma40: minor cosmetic fixes Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 13/16] dmaengine: ste_dma40: minor code readability fixes Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 14/16] dmaengine: ste_dma40: add software lli support Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 15/16] dmaengine: set_dma40: ignore spurious interrupts Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 11:21 ` [PATCH 16/16] dmaengine: set_dma40: balance clock in probe fail code Fabio Baltieri
2013-01-07 11:21 ` Fabio Baltieri
2013-01-07 14:33 ` [PATCH v2 00/16] various fixes and updates for ste_dma40 Vinod Koul
2013-01-07 14:33 ` Vinod Koul
2013-01-07 16:59 ` Fabio Baltieri
2013-01-07 16:59 ` Fabio Baltieri
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.