dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16
Subsystems (2)
PATCH 1/1 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.
--- .../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(-)
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +115 -41
@@ -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;
drivers/dma/dw-axi-dmac/dw-axi-dmac.h +5 -1
@@ -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
Signature · 1 line
2.30.2
kernel test robot
build botkernel test robot noticed the following build warnings:
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
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki