Skip to content

Commit f9c3403

Browse files
caihuoqvinodkoul
authored andcommitted
dmaengine: dw-edma: Create a new dw_edma_core_ops structure to abstract controller operation
The structure dw_edma_core_ops has a set of the pointers abstracting out the DW eDMA vX and DW HDMA Native controllers. And use dw_edma_v0_core_register to set up operation. Signed-off-by: Cai Huoqing <cai.huoqing@linux.dev> Reviewed-by: Serge Semin <fancer.lancer@gmail.com> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Tested-by: Serge Semin <fancer.lancer@gmail.com> Link: https://lore.kernel.org/r/20230520050854.73160-3-cai.huoqing@linux.dev Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 4875175 commit f9c3403

File tree

4 files changed

+157
-82
lines changed

4 files changed

+157
-82
lines changed

drivers/dma/dw-edma/dw-edma-core.c

Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc)
183183

184184
static int dw_edma_start_transfer(struct dw_edma_chan *chan)
185185
{
186+
struct dw_edma *dw = chan->dw;
186187
struct dw_edma_chunk *child;
187188
struct dw_edma_desc *desc;
188189
struct virt_dma_desc *vd;
@@ -200,7 +201,7 @@ static int dw_edma_start_transfer(struct dw_edma_chan *chan)
200201
if (!child)
201202
return 0;
202203

203-
dw_edma_v0_core_start(child, !desc->xfer_sz);
204+
dw_edma_core_start(dw, child, !desc->xfer_sz);
204205
desc->xfer_sz += child->ll_region.sz;
205206
dw_edma_free_burst(child);
206207
list_del(&child->list);
@@ -287,7 +288,7 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan)
287288
chan->configured = false;
288289
} else if (chan->status == EDMA_ST_IDLE) {
289290
chan->configured = false;
290-
} else if (dw_edma_v0_core_ch_status(chan) == DMA_COMPLETE) {
291+
} else if (dw_edma_core_ch_status(chan) == DMA_COMPLETE) {
291292
/*
292293
* The channel is in a false BUSY state, probably didn't
293294
* receive or lost an interrupt
@@ -599,8 +600,6 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
599600
struct virt_dma_desc *vd;
600601
unsigned long flags;
601602

602-
dw_edma_v0_core_clear_done_int(chan);
603-
604603
spin_lock_irqsave(&chan->vc.lock, flags);
605604
vd = vchan_next_desc(&chan->vc);
606605
if (vd) {
@@ -641,8 +640,6 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)
641640
struct virt_dma_desc *vd;
642641
unsigned long flags;
643642

644-
dw_edma_v0_core_clear_abort_int(chan);
645-
646643
spin_lock_irqsave(&chan->vc.lock, flags);
647644
vd = vchan_next_desc(&chan->vc);
648645
if (vd) {
@@ -654,63 +651,32 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)
654651
chan->status = EDMA_ST_IDLE;
655652
}
656653

657-
static irqreturn_t dw_edma_interrupt(int irq, void *data, bool write)
654+
static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data)
658655
{
659656
struct dw_edma_irq *dw_irq = data;
660-
struct dw_edma *dw = dw_irq->dw;
661-
unsigned long total, pos, val;
662-
unsigned long off;
663-
u32 mask;
664-
665-
if (write) {
666-
total = dw->wr_ch_cnt;
667-
off = 0;
668-
mask = dw_irq->wr_mask;
669-
} else {
670-
total = dw->rd_ch_cnt;
671-
off = dw->wr_ch_cnt;
672-
mask = dw_irq->rd_mask;
673-
}
674-
675-
val = dw_edma_v0_core_status_done_int(dw, write ?
676-
EDMA_DIR_WRITE :
677-
EDMA_DIR_READ);
678-
val &= mask;
679-
for_each_set_bit(pos, &val, total) {
680-
struct dw_edma_chan *chan = &dw->chan[pos + off];
681-
682-
dw_edma_done_interrupt(chan);
683-
}
684-
685-
val = dw_edma_v0_core_status_abort_int(dw, write ?
686-
EDMA_DIR_WRITE :
687-
EDMA_DIR_READ);
688-
val &= mask;
689-
for_each_set_bit(pos, &val, total) {
690-
struct dw_edma_chan *chan = &dw->chan[pos + off];
691-
692-
dw_edma_abort_interrupt(chan);
693-
}
694-
695-
return IRQ_HANDLED;
696-
}
697657

698-
static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data)
699-
{
700-
return dw_edma_interrupt(irq, data, true);
658+
return dw_edma_core_handle_int(dw_irq, EDMA_DIR_WRITE,
659+
dw_edma_done_interrupt,
660+
dw_edma_abort_interrupt);
701661
}
702662

703663
static inline irqreturn_t dw_edma_interrupt_read(int irq, void *data)
704664
{
705-
return dw_edma_interrupt(irq, data, false);
665+
struct dw_edma_irq *dw_irq = data;
666+
667+
return dw_edma_core_handle_int(dw_irq, EDMA_DIR_READ,
668+
dw_edma_done_interrupt,
669+
dw_edma_abort_interrupt);
706670
}
707671

708672
static irqreturn_t dw_edma_interrupt_common(int irq, void *data)
709673
{
710-
dw_edma_interrupt(irq, data, true);
711-
dw_edma_interrupt(irq, data, false);
674+
irqreturn_t ret = IRQ_NONE;
675+
676+
ret |= dw_edma_interrupt_write(irq, data);
677+
ret |= dw_edma_interrupt_read(irq, data);
712678

713-
return IRQ_HANDLED;
679+
return ret;
714680
}
715681

716682
static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
@@ -811,7 +777,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
811777

812778
vchan_init(&chan->vc, dma);
813779

814-
dw_edma_v0_core_device_config(chan);
780+
dw_edma_core_ch_config(chan);
815781
}
816782

817783
/* Set DMA channel capabilities */
@@ -956,14 +922,16 @@ int dw_edma_probe(struct dw_edma_chip *chip)
956922

957923
dw->chip = chip;
958924

925+
dw_edma_v0_core_register(dw);
926+
959927
raw_spin_lock_init(&dw->lock);
960928

961929
dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt,
962-
dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
930+
dw_edma_core_ch_count(dw, EDMA_DIR_WRITE));
963931
dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
964932

965933
dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt,
966-
dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
934+
dw_edma_core_ch_count(dw, EDMA_DIR_READ));
967935
dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
968936

969937
if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)
@@ -982,7 +950,7 @@ int dw_edma_probe(struct dw_edma_chip *chip)
982950
dev_name(chip->dev));
983951

984952
/* Disable eDMA, only to establish the ideal initial conditions */
985-
dw_edma_v0_core_off(dw);
953+
dw_edma_core_off(dw);
986954

987955
/* Request IRQs */
988956
err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
@@ -995,7 +963,7 @@ int dw_edma_probe(struct dw_edma_chip *chip)
995963
goto err_irq_free;
996964

997965
/* Turn debugfs on */
998-
dw_edma_v0_core_debugfs_on(dw);
966+
dw_edma_core_debugfs_on(dw);
999967

1000968
chip->dw = dw;
1001969

@@ -1021,7 +989,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
1021989
return -ENODEV;
1022990

1023991
/* Disable eDMA */
1024-
dw_edma_v0_core_off(dw);
992+
dw_edma_core_off(dw);
1025993

1026994
/* Free irqs */
1027995
for (i = (dw->nr_irqs - 1); i >= 0; i--)

drivers/dma/dw-edma/dw-edma-core.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,21 @@ struct dw_edma {
111111
raw_spinlock_t lock; /* Only for legacy */
112112

113113
struct dw_edma_chip *chip;
114+
115+
const struct dw_edma_core_ops *core;
116+
};
117+
118+
typedef void (*dw_edma_handler_t)(struct dw_edma_chan *);
119+
120+
struct dw_edma_core_ops {
121+
void (*off)(struct dw_edma *dw);
122+
u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir);
123+
enum dma_status (*ch_status)(struct dw_edma_chan *chan);
124+
irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
125+
dw_edma_handler_t done, dw_edma_handler_t abort);
126+
void (*start)(struct dw_edma_chunk *chunk, bool first);
127+
void (*ch_config)(struct dw_edma_chan *chan);
128+
void (*debugfs_on)(struct dw_edma *dw);
114129
};
115130

116131
struct dw_edma_sg {
@@ -148,4 +163,47 @@ struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan)
148163
return vc2dw_edma_chan(to_virt_chan(dchan));
149164
}
150165

166+
static inline
167+
void dw_edma_core_off(struct dw_edma *dw)
168+
{
169+
dw->core->off(dw);
170+
}
171+
172+
static inline
173+
u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
174+
{
175+
return dw->core->ch_count(dw, dir);
176+
}
177+
178+
static inline
179+
enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan)
180+
{
181+
return chan->dw->core->ch_status(chan);
182+
}
183+
184+
static inline irqreturn_t
185+
dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
186+
dw_edma_handler_t done, dw_edma_handler_t abort)
187+
{
188+
return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort);
189+
}
190+
191+
static inline
192+
void dw_edma_core_start(struct dw_edma *dw, struct dw_edma_chunk *chunk, bool first)
193+
{
194+
dw->core->start(chunk, first);
195+
}
196+
197+
static inline
198+
void dw_edma_core_ch_config(struct dw_edma_chan *chan)
199+
{
200+
chan->dw->core->ch_config(chan);
201+
}
202+
203+
static inline
204+
void dw_edma_core_debugfs_on(struct dw_edma *dw)
205+
{
206+
dw->core->debugfs_on(dw);
207+
}
208+
151209
#endif /* _DW_EDMA_CORE_H */

0 commit comments

Comments
 (0)