Skip to content

Commit 495e18b

Browse files
skhimichvinodkoul
authored andcommitted
dmaengine: dw-axi-dmac: Add support DMAX_NUM_CHANNELS > 16
Added support for DMA controller with more than 16 channels. Signed-off-by: Sergey Khimich <serghox@gmail.com> Link: https://lore.kernel.org/r/20231010101450.2949126-2-serghox@gmail.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent c1939c2 commit 495e18b

File tree

2 files changed

+120
-42
lines changed

2 files changed

+120
-42
lines changed

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c

Lines changed: 115 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ static inline u32 axi_dma_ioread32(struct axi_dma_chip *chip, u32 reg)
6262
return ioread32(chip->regs + reg);
6363
}
6464

65+
static inline void
66+
axi_dma_iowrite64(struct axi_dma_chip *chip, u32 reg, u64 val)
67+
{
68+
iowrite64(val, chip->regs + reg);
69+
}
70+
71+
static inline u64 axi_dma_ioread64(struct axi_dma_chip *chip, u32 reg)
72+
{
73+
return ioread64(chip->regs + reg);
74+
}
75+
6576
static inline void
6677
axi_chan_iowrite32(struct axi_dma_chan *chan, u32 reg, u32 val)
6778
{
@@ -182,38 +193,73 @@ static inline u32 axi_chan_irq_read(struct axi_dma_chan *chan)
182193

183194
static inline void axi_chan_disable(struct axi_dma_chan *chan)
184195
{
185-
u32 val;
186-
187-
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
188-
val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
189-
if (chan->chip->dw->hdata->reg_map_8_channels)
190-
val |= BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
191-
else
192-
val |= BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
193-
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
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 &= ~((u64)(BIT(chan->id) >> DMAC_CHAN_16)
202+
<< (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
203+
val |= (u64)(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+
}
194219
}
195220

196221
static inline void axi_chan_enable(struct axi_dma_chan *chan)
197222
{
198-
u32 val;
199-
200-
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
201-
if (chan->chip->dw->hdata->reg_map_8_channels)
202-
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
203-
BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
204-
else
205-
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
223+
u64 val;
224+
225+
if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
226+
val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
227+
if (chan->id >= DMAC_CHAN_16) {
228+
val |= (u64)(BIT(chan->id) >> DMAC_CHAN_16)
229+
<< (DMAC_CHAN_EN_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
230+
(u64)(BIT(chan->id) >> DMAC_CHAN_16)
231+
<< (DMAC_CHAN_EN2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
232+
} else {
233+
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
206234
BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
207-
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
235+
}
236+
axi_dma_iowrite64(chan->chip, DMAC_CHEN, val);
237+
} else {
238+
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
239+
if (chan->chip->dw->hdata->reg_map_8_channels) {
240+
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
241+
BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
242+
} else {
243+
val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
244+
BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
245+
}
246+
axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
247+
}
208248
}
209249

210250
static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
211251
{
212-
u32 val;
252+
u64 val;
213253

214-
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
254+
if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16)
255+
val = axi_dma_ioread64(chan->chip, DMAC_CHEN);
256+
else
257+
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
215258

216-
return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
259+
if (chan->id >= DMAC_CHAN_16)
260+
return !!(val & ((u64)(BIT(chan->id) >> DMAC_CHAN_16) << DMAC_CHAN_BLOCK_SHIFT));
261+
else
262+
return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
217263
}
218264

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

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

1182-
if (chan->chip->dw->hdata->reg_map_8_channels) {
1183-
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
1184-
val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
1185-
BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
1186-
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
1228+
if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
1229+
val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
1230+
if (chan->id >= DMAC_CHAN_16) {
1231+
val |= (u64)(BIT(chan->id) >> DMAC_CHAN_16)
1232+
<< (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT) |
1233+
(u64)(BIT(chan->id) >> DMAC_CHAN_16)
1234+
<< (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT);
1235+
} else {
1236+
val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
1237+
BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
1238+
}
1239+
axi_dma_iowrite64(chan->chip, DMAC_CHSUSPREG, val);
11871240
} else {
1188-
val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
1189-
val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
1241+
if (chan->chip->dw->hdata->reg_map_8_channels) {
1242+
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
1243+
val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
1244+
BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
1245+
axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
1246+
} else {
1247+
val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
1248+
val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
11901249
BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
1191-
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
1250+
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, (u32)val);
1251+
}
11921252
}
11931253

11941254
do {
@@ -1210,18 +1270,32 @@ static int dma_chan_pause(struct dma_chan *dchan)
12101270
/* Called in chan locked context */
12111271
static inline void axi_chan_resume(struct axi_dma_chan *chan)
12121272
{
1213-
u32 val;
1214-
1215-
if (chan->chip->dw->hdata->reg_map_8_channels) {
1216-
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
1217-
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
1218-
val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
1219-
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
1273+
u64 val;
1274+
1275+
if (chan->chip->dw->hdata->nr_channels >= DMAC_CHAN_16) {
1276+
val = axi_dma_ioread64(chan->chip, DMAC_CHSUSPREG);
1277+
if (chan->id >= DMAC_CHAN_16) {
1278+
val &= ~((u64)(BIT(chan->id) >> DMAC_CHAN_16)
1279+
<< (DMAC_CHAN_SUSP2_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
1280+
val |= ((u64)(BIT(chan->id) >> DMAC_CHAN_16)
1281+
<< (DMAC_CHAN_SUSP2_WE_SHIFT + DMAC_CHAN_BLOCK_SHIFT));
1282+
} else {
1283+
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
1284+
val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
1285+
}
1286+
axi_dma_iowrite64(chan->chip, DMAC_CHSUSPREG, val);
12201287
} else {
1221-
val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
1222-
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
1223-
val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
1224-
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
1288+
if (chan->chip->dw->hdata->reg_map_8_channels) {
1289+
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
1290+
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
1291+
val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
1292+
axi_dma_iowrite32(chan->chip, DMAC_CHEN, (u32)val);
1293+
} else {
1294+
val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
1295+
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
1296+
val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
1297+
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, (u32)val);
1298+
}
12251299
}
12261300

12271301
chan->is_paused = false;

drivers/dma/dw-axi-dmac/dw-axi-dmac.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

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

21-
#define DMAC_MAX_CHANNELS 16
21+
#define DMAC_MAX_CHANNELS 32
2222
#define DMAC_MAX_MASTERS 2
2323
#define DMAC_MAX_BLK_SIZE 0x200000
2424

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

225+
/* DMAC CHAN BLOCKS */
226+
#define DMAC_CHAN_BLOCK_SHIFT 32
227+
#define DMAC_CHAN_16 16
228+
225229
/* DMAC_CHSUSP */
226230
#define DMAC_CHAN_SUSP2_SHIFT 0
227231
#define DMAC_CHAN_SUSP2_WE_SHIFT 16

0 commit comments

Comments
 (0)