Add support DMAX_NUM_CHANNELS > 16
Subsystems (2)
v2 cover Add support DMAX_NUM_CHANNELS > 16
This patch adds support for DW AXI DMA controller with 32 channels.
v2:
- Fix warning reported by kernel test robot:
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
Sergey Khimich (1):
dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16
.../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(-)
Signature · 1 line
2.30.2
PATCH v2 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 &= ~((u64)(BIT (chan->id) >>DMAC_CHAN_16 ) + << (DMAC_CHAN_EN_SHIFT +DMAC_CHAN_BLOCK_SHIFT )); + val |= (u64)(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 |= (u64)(BIT (chan->id) >>DMAC_CHAN_16 ) + << (DMAC_CHAN_EN_SHIFT +DMAC_CHAN_BLOCK_SHIFT ) | + (u64)(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 & ((u64)(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 |= (u64)(BIT (chan->id) >>DMAC_CHAN_16 ) + << (DMAC_CHAN_SUSP2_SHIFT +DMAC_CHAN_BLOCK_SHIFT ) | + (u64)(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 &= ~((u64)(BIT (chan->id) >>DMAC_CHAN_16 ) + << (DMAC_CHAN_SUSP2_SHIFT +DMAC_CHAN_BLOCK_SHIFT )); + val |= ((u64)(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
Quoted 9 lines · Sergey Khimich
This patch adds support for DW AXI DMA controller with 32 channels.
v2:
- Fix warning reported by kernel test robot:
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/[...]
Applied, thanks!
[1/1] dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16
commit: 495e18b16e3dd8218eaec6a8a55334fb55245d59
Best regards,
Signature · 1 line
~Vinod