2023-10-05 16:14:05

by Sergey Khimich

[permalink] [raw]
Subject: [PATCH] dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16

From: Sergey Khimich <[email protected]>

Added support for DMA controller with more than 16 channels.

Signed-off-by: Sergey Khimich <[email protected]>
---
.../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 156 +++++++++++++-----
drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 6 +-
2 files changed, 120 insertions(+), 42 deletions(-)

diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index dd02f84e404d..984e953046c4 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -62,6 +62,17 @@ static inline u32 axi_dma_ioread32(struct axi_dma_chip *chip, u32 reg)
return ioread32(chip->regs + reg);
}

+static inline void
+axi_dma_iowrite64(struct axi_dma_chip *chip, u32 reg, u64 val)
+{
+ iowrite64(val, chip->regs + reg);
+}
+
+static inline u64 axi_dma_ioread64(struct axi_dma_chip *chip, u32 reg)
+{
+ return ioread64(chip->regs + reg);
+}
+
static inline void
axi_chan_iowrite32(struct axi_dma_chan *chan, u32 reg, u32 val)
{
@@ -182,38 +193,73 @@ static inline u32 axi_chan_irq_read(struct axi_dma_chan *chan)

static inline void axi_chan_disable(struct axi_dma_chan *chan)
{
- u32 val;
-
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
- if (chan->chip->dw->hdata->reg_map_8_channels)
- val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
- else
- val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ u64 val;
+
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
+ if (chan->id >= DMAC_CHAN_16) {
+ val &= ~((BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
+ val |= (BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
+ } else {
+ val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
+ val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
+ if (chan->chip->dw->hdata->reg_map_8_channels)
+ val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ else
+ val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ }
}

static inline void axi_chan_enable(struct axi_dma_chan *chan)
{
- u32 val;
-
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- if (chan->chip->dw->hdata->reg_map_8_channels)
- val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
- BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
- else
- val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ u64 val;
+
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
+ if (chan->id >= DMAC_CHAN_16) {
+ val |= (BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
+ (BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
+ } else {
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+ } else {
+ val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+ }
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ }
}

static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
{
- u32 val;
+ u64 val;

- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16)
+ val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
+ else
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);

- return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
+ if (chan->id >= DMAC_CHAN_16)
+ return !!(val & ((BIT(chan->id) >> DMAC_CHAN_16) << DMAC_CHAN_BLOCK_SHIFT));
+ else
+ return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
}

static void axi_dma_hw_init(struct axi_dma_chip *chip)
@@ -1175,20 +1221,34 @@ static int dma_chan_pause(struct dma_chan *dchan)
struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
unsigned long flags;
unsigned int timeout = 20; /* timeout iterations */
- u32 val;
+ u64 val;

spin_lock_irqsave(&chan->vc.lock, flags);

- if (chan->chip->dw->hdata->reg_map_8_channels) {
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
- BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
+ if (chan->id >= DMAC_CHAN_16) {
+ val |= (BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
+ (BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
+ } else {
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHSUSPREG, val);
} else {
- val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
- val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
+ BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+ val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
- axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+ axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, (u32)val);
+ }
}

do {
@@ -1210,18 +1270,32 @@ static int dma_chan_pause(struct dma_chan *dchan)
/* Called in chan locked context */
static inline void axi_chan_resume(struct axi_dma_chan *chan)
{
- u32 val;
-
- if (chan->chip->dw->hdata->reg_map_8_channels) {
- val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
- val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
- val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
- axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+ u64 val;
+
+ if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
+ val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
+ if (chan->id >= DMAC_CHAN_16) {
+ val &= ~((BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
+ val |= ((BIT(chan->id) >> DMAC_CHAN_16)
+ << (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
+ } else {
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
+ }
+ axi_dma_iowrite64(chan->chip, DMAC_CHSUSPREG, val);
} else {
- val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
- val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
- val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
- axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+ if (chan->chip->dw->hdata->reg_map_8_channels) {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
+ } else {
+ val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+ val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
+ val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
+ axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, (u32)val);
+ }
}

chan->is_paused = false;
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index eb267cb24f67..454904d99654 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -18,7 +18,7 @@

#include "../virt-dma.h"

-#define DMAC_MAX_CHANNELS 16
+#define DMAC_MAX_CHANNELS 32
#define DMAC_MAX_MASTERS 2
#define DMAC_MAX_BLK_SIZE 0x200000

@@ -222,6 +222,10 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
/* DMAC_CHEN2 */
#define DMAC_CHAN_EN2_WE_SHIFT 16

+/* DMAC CHAN BLOCKS */
+#define DMAC_CHAN_BLOCK_SHIFT 32
+#define DMAC_CHAN_16 16
+
/* DMAC_CHSUSP */
#define DMAC_CHAN_SUSP2_SHIFT 0
#define DMAC_CHAN_SUSP2_WE_SHIFT 16
--
2.30.2


2023-10-05 17:48:45

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16

Hi Sergey,

kernel test robot noticed the following build warnings:

[auto build test WARNING on vkoul-dmaengine/next]
[also build test WARNING on linus/master v6.6-rc4 next-20231005]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Sergey-Khimich/dmaengine-dw-axi-dmac-Add-support-DMAX_NUM_CHANNELS-16/20231006-002509
base: https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next
patch link: https://lore.kernel.org/r/20231005113638.2039726-1-serghox%40gmail.com
patch subject: [PATCH] dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20231006/[email protected]/config)
compiler: m68k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231006/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All warnings (new ones prefixed by >>):

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c: In function 'axi_chan_disable':
>> drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:202:33: warning: left shift count >= width of type [-Wshift-count-overflow]
202 | << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:204:33: warning: left shift count >= width of type [-Wshift-count-overflow]
204 | << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c: In function 'axi_chan_enable':
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:229:33: warning: left shift count >= width of type [-Wshift-count-overflow]
229 | << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:231:33: warning: left shift count >= width of type [-Wshift-count-overflow]
231 | << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c: In function 'axi_chan_is_hw_enable':
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:260:66: warning: left shift count >= width of type [-Wshift-count-overflow]
260 | return !!(val & ((BIT(chan->id) >> DMAC_CHAN_16) << DMAC_CHAN_BLOCK_SHIFT));
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c: In function 'dma_chan_pause':
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:1232:33: warning: left shift count >= width of type [-Wshift-count-overflow]
1232 | << (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:1234:33: warning: left shift count >= width of type [-Wshift-count-overflow]
1234 | << (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c: In function 'axi_chan_resume':
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:1279:33: warning: left shift count >= width of type [-Wshift-count-overflow]
1279 | << (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
| ^~
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:1281:33: warning: left shift count >= width of type [-Wshift-count-overflow]
1281 | << (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
| ^~


vim +202 drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c

193
194 static inline void axi_chan_disable(struct axi_dma_chan *chan)
195 {
196 u64 val;
197
198 if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
199 val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
200 if (chan->id >= DMAC_CHAN_16) {
201 val &= ~((BIT(chan->id) >> DMAC_CHAN_16)
> 202 << (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
203 val |= (BIT(chan->id) >> DMAC_CHAN_16)
204 << (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
205 } else {
206 val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
207 val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
208 }
209 axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
210 } else {
211 val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
212 val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
213 if (chan->chip->dw->hdata->reg_map_8_channels)
214 val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
215 else
216 val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
217 axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
218 }
219 }
220

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki