dmaengine: dw-edma: Add support for native HDMA
Subsystems (5)
v7 cover dmaengine: dw-edma: Add support for native HDMA
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA,
so this patch add support for HDMA NATIVE mode.
HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when youhave multiple write channels.
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
Cai Huoqing (2):
dmaengine: dw-edma: Add support for native HDMA
dmaengine: dw-edma: Optimization in dw_edma_v0_core_handle_int
Cai huoqing (3):
dmaengine: dw-edma: Rename dw_edma_core_ops structure to
dw_edma_plat_ops
dmaengine: dw-edma: Create a new dw_edma_core_ops structure to
abstract controller operation
dmaengine: dw-edma: Add HDMA DebugFS support
v6->v7:
[1/5]
1.Update the commit log.
[2/5]
2.Revert dw_edma_core_handle_int back to dw-edma-core.h. 3.Fix code style.
[3/5]
4.Move the change of register file from patch[4/5] to patch[3/5]. 5.Fix code style.
v6 link:
https://lore.kernel.org/lkml/[email protected]/
drivers/dma/dw-edma/Makefile | 8 +- drivers/dma/dw-edma/dw-edma-core.c | 86 ++---- drivers/dma/dw-edma/dw-edma-core.h | 58 ++++ drivers/dma/dw-edma/dw-edma-pcie.c | 4 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 91 ++++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 277 +++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 ++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 +++++++++ drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 7 +- 13 files changed, 785 insertions(+), 107 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.h
Signature · 1 line
2.34.1
PATCH v7 1/5 dmaengine: dw-edma: Rename dw_edma_core_ops structure to dw_edma_plat_ops
From: Cai huoqing <[email protected]>
The dw_edma_core_ops structure contains a set of the operations:
device IRQ numbers getter, CPU/PCI address translation. Based on the functions semantics the structure name "dw_edma_plat_ops" looks more descriptive since indeed the operations are platform-specific. The "dw_edma_core_ops" name shall be used for a structure with the IP-core specific set of callbacks in order to abstract out DW eDMA and DW HDMA setups. Such structure will be added in one of the next commit in the framework of the set of changes adding the DW HDMA device support.
Anyway the renaming was necessary to distinguish two types of the implementation callbacks:
1. DW eDMA/hDMA IP-core specific operations: device-specific CSR setups in one or another aspect of the DMA-engine initialization.
2. DW eDMA/hDMA platform specific operations: the DMA device environment configs like IRQs, address translation, etc.
---v6->v7:
1.Update the commit log.
v6 link:
https://lore.kernel.org/lkml/[email protected]/
drivers/dma/dw-edma/dw-edma-pcie.c | 4 ++-- drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-)
drivers/dma/dw-edma/dw-edma-pcie.c +2 -2
@@ -109,7 +109,7 @@ static u64 dw_edma_pcie_address(struct device *dev, phys_addr_t cpu_addr)return region.start; } -static const struct dw_edma_core_ops dw_edma_pcie_core_ops = { +static const struct dw_edma_plat_ops dw_edma_pcie_plat_ops = { .irq_vector = dw_edma_pcie_irq_vector, .pci_address = dw_edma_pcie_address, };
@@ -225,7 +225,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, chip->mf = vsec_data.mf; chip->nr_irqs = nr_irqs; - chip->ops = &dw_edma_pcie_core_ops; + chip->ops = &dw_edma_pcie_plat_ops; chip->ll_wr_cnt = vsec_data.wr_ch_cnt; chip->ll_rd_cnt = vsec_data.rd_ch_cnt;
drivers/pci/controller/dwc/pcie-designware.c +1 -1
@@ -828,7 +828,7 @@ static int dw_pcie_edma_irq_vector(struct device *dev, unsigned int nr)return platform_get_irq_byname_optional (pdev, name); } -static struct dw_edma_core_ops dw_pcie_edma_ops = { +static struct dw_edma_plat_ops dw_pcie_edma_ops = { .irq_vector = dw_pcie_edma_irq_vector, };
include/linux/dma/edma.h +2 -2
@@ -40,7 +40,7 @@ struct dw_edma_region {* iATU windows. That will be done by the controller * automatically. */ -struct dw_edma_core_ops { +struct dw_edma_plat_ops {int (*irq_vector)(struct device *dev,unsigned int nr);u64 (*pci_address)(struct device *dev,phys_addr_t cpu_addr); };
@@ -80,7 +80,7 @@ enum dw_edma_chip_flags {struct dw_edma_chip {struct device *dev;int nr_irqs; -const struct dw_edma_core_ops *ops; +const struct dw_edma_plat_ops *ops;u32 flags;void __iomem *reg_base;
Signature · 1 line
2.34.1
PATCH v7 2/5 dmaengine: dw-edma: Create a new dw_edma_core_ops structure to abstract controller operation
In reply to Cai HuoqingFrom: Cai huoqing <[email protected]>
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.
---v6->v7:
1.Revert dw_edma_core_handle_int back to dw-edma-core.h. 2.Fix code style.
v6 link:
https://lore.kernel.org/lkml/[email protected]/
drivers/dma/dw-edma/dw-edma-core.c | 82 ++++++++------------------ drivers/dma/dw-edma/dw-edma-core.h | 58 ++++++++++++++++++ drivers/dma/dw-edma/dw-edma-v0-core.c | 85 +++++++++++++++++++++++---- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +---- 4 files changed, 157 insertions(+), 82 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +25 -57
@@ -183,6 +183,7 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc)static void dw_edma_start_transfer (struct dw_edma_chan *chan) { +struct dw_edma *dw = chan->dw;struct dw_edma_chunk *child;struct dw_edma_desc *desc;struct virt_dma_desc *vd;
@@ -200,7 +201,7 @@ static void dw_edma_start_transfer(struct dw_edma_chan *chan)if (!child)return ; -dw_edma_v0_core_start (child, !desc->xfer_sz); +dw_edma_core_start (dw, child, !desc->xfer_sz); desc->xfer_sz += child->ll_region.sz;dw_edma_free_burst (child);list_del (&child->list);
@@ -285,7 +286,7 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan) chan->configured = false; }else if (chan->status ==EDMA_ST_IDLE ) { chan->configured = false; - }else if (dw_edma_v0_core_ch_status (chan) ==DMA_COMPLETE ) { + }else if (dw_edma_core_ch_status (chan) ==DMA_COMPLETE ) {/* * The channel is in a false BUSY state, probably didn't * receive or lost an interrupt
@@ -594,8 +595,6 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)struct virt_dma_desc *vd;unsigned long flags; -dw_edma_v0_core_clear_done_int (chan); -spin_lock_irqsave (&chan->vc.lock, flags); vd =vchan_next_desc (&chan->vc);if (vd) {
@@ -636,8 +635,6 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)struct virt_dma_desc *vd;unsigned long flags; -dw_edma_v0_core_clear_abort_int (chan); -spin_lock_irqsave (&chan->vc.lock, flags); vd =vchan_next_desc (&chan->vc);if (vd) {
@@ -649,63 +646,32 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) chan->status =EDMA_ST_IDLE ; } -static irqreturn_t dw_edma_interrupt (int irq,void *data,bool write) +static inline irqreturn_t dw_edma_interrupt_write (int irq,void *data) {struct dw_edma_irq *dw_irq = data; -struct dw_edma *dw = dw_irq->dw; -unsigned long total, pos, val; -unsigned long off; -u32 mask; - -if (write) { - total = dw->wr_ch_cnt; - off =0 ; - mask = dw_irq->wr_mask; - }else { - total = dw->rd_ch_cnt; - off = dw->wr_ch_cnt; - mask = dw_irq->rd_mask; - } - - val =dw_edma_v0_core_status_done_int (dw, write ? -EDMA_DIR_WRITE : -EDMA_DIR_READ ); - val &= mask; -for_each_set_bit (pos, &val, total) { -struct dw_edma_chan *chan = &dw->chan[pos + off]; - -dw_edma_done_interrupt (chan); - } - - val =dw_edma_v0_core_status_abort_int (dw, write ? -EDMA_DIR_WRITE : -EDMA_DIR_READ ); - val &= mask; -for_each_set_bit (pos, &val, total) { -struct dw_edma_chan *chan = &dw->chan[pos + off]; - -dw_edma_abort_interrupt (chan); - } - -return IRQ_HANDLED ; -} -static inline irqreturn_t dw_edma_interrupt_write (int irq,void *data) -{ -return dw_edma_interrupt (irq, data, true); +return dw_edma_core_handle_int (dw_irq,EDMA_DIR_WRITE , + dw_edma_done_interrupt, + dw_edma_abort_interrupt); }static inline irqreturn_t dw_edma_interrupt_read (int irq,void *data) { -return dw_edma_interrupt (irq, data, false); +struct dw_edma_irq *dw_irq = data; + +return dw_edma_core_handle_int (dw_irq,EDMA_DIR_READ , + dw_edma_done_interrupt, + dw_edma_abort_interrupt); }static irqreturn_t dw_edma_interrupt_common (int irq,void *data) { -dw_edma_interrupt (irq, data, true); -dw_edma_interrupt (irq, data, false); +irqreturn_t ret =IRQ_NONE ; + + ret |=dw_edma_interrupt_write (irq, data); + ret |=dw_edma_interrupt_read (irq, data); -return IRQ_HANDLED ; +return ret; }static int dw_edma_alloc_chan_resources (struct dma_chan *dchan)
@@ -806,7 +772,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)vchan_init (&chan->vc, dma); -dw_edma_v0_core_device_config (chan); +dw_edma_core_ch_config (chan); }/* Set DMA channel capabilities */
@@ -951,14 +917,16 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; +dw_edma_v0_core_register (dw); +raw_spin_lock_init (&dw->lock); dw->wr_ch_cnt =min_t (u16, chip->ll_wr_cnt, -dw_edma_v0_core_ch_count (dw,EDMA_DIR_WRITE )); +dw_edma_core_ch_count (dw,EDMA_DIR_WRITE )); dw->wr_ch_cnt =min_t (u16, dw->wr_ch_cnt,EDMA_MAX_WR_CH ); dw->rd_ch_cnt =min_t (u16, chip->ll_rd_cnt, -dw_edma_v0_core_ch_count (dw,EDMA_DIR_READ )); +dw_edma_core_ch_count (dw,EDMA_DIR_READ )); dw->rd_ch_cnt =min_t (u16, dw->rd_ch_cnt,EDMA_MAX_RD_CH );if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)
@@ -977,7 +945,7 @@ int dw_edma_probe(struct dw_edma_chip *chip) dev_name(chip->dev));/* Disable eDMA, only to establish the ideal initial conditions */ -dw_edma_v0_core_off (dw); +dw_edma_core_off (dw);/* Request IRQs */ err =dw_edma_irq_request (dw, &wr_alloc, &rd_alloc);
@@ -990,7 +958,7 @@ int dw_edma_probe(struct dw_edma_chip *chip) goto err_irq_free;/* Turn debugfs on */ -dw_edma_v0_core_debugfs_on (dw); +dw_edma_core_debugfs_on (dw); chip->dw = dw;
@@ -1016,7 +984,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)return -ENODEV ;/* Disable eDMA */ -dw_edma_v0_core_off (dw); +dw_edma_core_off (dw);/* Free irqs */ for (i = (dw->nr_irqs -1 ); i >=0 ; i--)
drivers/dma/dw-edma/dw-edma-core.h +58 -0
68 lines not on this page · raw message
drivers/dma/dw-edma/dw-edma-v0-core.c +72 -13
158 lines not on this page · raw message
drivers/dma/dw-edma/dw-edma-v0-core.h +2 -12
@@ -11,17 +11,7 @@#include <linux/dma/edma.h> -/* eDMA management callbacks */ -void dw_edma_v0_core_off (struct dw_edma *chan); -u16 dw_edma_v0_core_ch_count (struct dw_edma *chan,enum dw_edma_dir dir); -enum dma_status dw_edma_v0_core_ch_status (struct dw_edma_chan *chan); -void dw_edma_v0_core_clear_done_int (struct dw_edma_chan *chan); -void dw_edma_v0_core_clear_abort_int (struct dw_edma_chan *chan); -u32 dw_edma_v0_core_status_done_int (struct dw_edma *chan,enum dw_edma_dir dir); -u32 dw_edma_v0_core_status_abort_int (struct dw_edma *chan,enum dw_edma_dir dir); -void dw_edma_v0_core_start (struct dw_edma_chunk *chunk,bool first); -int dw_edma_v0_core_device_config (struct dw_edma_chan *chan); -/* eDMA debug fs callbacks */ -void dw_edma_v0_core_debugfs_on (struct dw_edma *dw); +/* eDMA core register */ +void dw_edma_v0_core_register (struct dw_edma *dw);#endif /* _DW_EDMA_V0_CORE_H */
Signature · 1 line
2.34.1
Re: [PATCH v7 2/5] dmaengine: dw-edma: Create a new dw_edma_core_ops structure to abstract controller operation
Quoted 7 lines · Cai Huoqing
From: Cai huoqing <[email protected]>
The structure
dw_edma_core_opshas a set of the pointers abstracting out the DW eDMA vX and DW HDMA Native controllers. And usedw_edma_v0_core_registerto set up operation.Signed-off-by Cai huoqing <[email protected]>
LGTM. Thanks.
-Serge(y)
Quoted 468 lines
---
v6->v7:
1.Revertdw_edma_core_handle_intback todw-edma-core.h. 2.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/dw-edma-core.c | 82 ++++++++------------------ drivers/dma/dw-edma/dw-edma-core.h | 58 ++++++++++++++++++ drivers/dma/dw-edma/dw-edma-v0-core.c | 85 +++++++++++++++++++++++---- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +---- 4 files changed, 157 insertions(+), 82 deletions(-)drivers/dma/dw-edma/dw-edma-core.c +25
-57@@ -183,6 +183,7 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc)static void dw_edma_start_transfer (struct dw_edma_chan *chan) { +struct dw_edma *dw = chan->dw;struct dw_edma_chunk *child;struct dw_edma_desc *desc;struct virt_dma_desc *vd;@@ -200,7 +201,7 @@ static void dw_edma_start_transfer(struct dw_edma_chan *chan)if (!child)return ; -dw_edma_v0_core_start (child, !desc->xfer_sz); +dw_edma_core_start (dw, child, !desc->xfer_sz); desc->xfer_sz += child->ll_region.sz;dw_edma_free_burst (child);list_del (&child->list);@@ -285,7 +286,7 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan) chan->configured = false; }else if (chan->status ==EDMA_ST_IDLE ) { chan->configured = false; - }else if (dw_edma_v0_core_ch_status (chan) ==DMA_COMPLETE ) { + }else if (dw_edma_core_ch_status (chan) ==DMA_COMPLETE ) {/* * The channel is in a false BUSY state, probably didn't * receive or lost an interrupt @@ -594,8 +595,6 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)struct virt_dma_desc *vd;unsigned long flags; -dw_edma_v0_core_clear_done_int (chan); -spin_lock_irqsave (&chan->vc.lock, flags); vd =vchan_next_desc (&chan->vc);if (vd) {@@ -636,8 +635,6 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)struct virt_dma_desc *vd;unsigned long flags; -dw_edma_v0_core_clear_abort_int (chan); -spin_lock_irqsave (&chan->vc.lock, flags); vd =vchan_next_desc (&chan->vc);if (vd) {@@ -649,63 +646,32 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) chan->status =EDMA_ST_IDLE ; } -static irqreturn_t dw_edma_interrupt (int irq,void *data,bool write) +static inline irqreturn_t dw_edma_interrupt_write (int irq,void *data) {struct dw_edma_irq *dw_irq = data; -struct dw_edma *dw = dw_irq->dw; -unsigned long total, pos, val; -unsigned long off; -u32 mask; - -if (write) { - total = dw->wr_ch_cnt; - off =0 ; - mask = dw_irq->wr_mask; - }else { - total = dw->rd_ch_cnt; - off = dw->wr_ch_cnt; - mask = dw_irq->rd_mask; - } - - val =dw_edma_v0_core_status_done_int (dw, write ? -EDMA_DIR_WRITE : -EDMA_DIR_READ ); - val &= mask; -for_each_set_bit (pos, &val, total) { -struct dw_edma_chan *chan = &dw->chan[pos + off]; - -dw_edma_done_interrupt (chan); - } - - val =dw_edma_v0_core_status_abort_int (dw, write ? -EDMA_DIR_WRITE : -EDMA_DIR_READ ); - val &= mask; -for_each_set_bit (pos, &val, total) { -struct dw_edma_chan *chan = &dw->chan[pos + off]; - -dw_edma_abort_interrupt (chan); - } - -return IRQ_HANDLED ; -} -static inline irqreturn_t dw_edma_interrupt_write (int irq,void *data) -{ -return dw_edma_interrupt (irq, data, true); +return dw_edma_core_handle_int (dw_irq,EDMA_DIR_WRITE , + dw_edma_done_interrupt, + dw_edma_abort_interrupt); }static inline irqreturn_t dw_edma_interrupt_read (int irq,void *data) { -return dw_edma_interrupt (irq, data, false); +struct dw_edma_irq *dw_irq = data; + +return dw_edma_core_handle_int (dw_irq,EDMA_DIR_READ , + dw_edma_done_interrupt, + dw_edma_abort_interrupt); }static irqreturn_t dw_edma_interrupt_common (int irq,void *data) { -dw_edma_interrupt (irq, data, true); -dw_edma_interrupt (irq, data, false); +irqreturn_t ret =IRQ_NONE ; + + ret |=dw_edma_interrupt_write (irq, data); + ret |=dw_edma_interrupt_read (irq, data); -return IRQ_HANDLED ; +return ret; }static int dw_edma_alloc_chan_resources (struct dma_chan *dchan)@@ -806,7 +772,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)vchan_init (&chan->vc, dma); -dw_edma_v0_core_device_config (chan); +dw_edma_core_ch_config (chan); }/* Set DMA channel capabilities */ @@ -951,14 +917,16 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; +dw_edma_v0_core_register (dw); +raw_spin_lock_init (&dw->lock); dw->wr_ch_cnt =min_t (u16, chip->ll_wr_cnt, -dw_edma_v0_core_ch_count (dw,EDMA_DIR_WRITE )); +dw_edma_core_ch_count (dw,EDMA_DIR_WRITE )); dw->wr_ch_cnt =min_t (u16, dw->wr_ch_cnt,EDMA_MAX_WR_CH ); dw->rd_ch_cnt =min_t (u16, chip->ll_rd_cnt, -dw_edma_v0_core_ch_count (dw,EDMA_DIR_READ )); +dw_edma_core_ch_count (dw,EDMA_DIR_READ )); dw->rd_ch_cnt =min_t (u16, dw->rd_ch_cnt,EDMA_MAX_RD_CH );if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)@@ -977,7 +945,7 @@ int dw_edma_probe(struct dw_edma_chip *chip) dev_name(chip->dev));/* Disable eDMA, only to establish the ideal initial conditions */ -dw_edma_v0_core_off (dw); +dw_edma_core_off (dw);/* Request IRQs */ err =dw_edma_irq_request (dw, &wr_alloc, &rd_alloc);@@ -990,7 +958,7 @@ int dw_edma_probe(struct dw_edma_chip *chip) goto err_irq_free;/* Turn debugfs on */ -dw_edma_v0_core_debugfs_on (dw); +dw_edma_core_debugfs_on (dw); chip->dw = dw;@@ -1016,7 +984,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)return -ENODEV ;/* Disable eDMA */ -dw_edma_v0_core_off (dw); +dw_edma_core_off (dw);/* Free irqs */ for (i = (dw->nr_irqs -1 ); i >=0 ; i--)drivers/dma/dw-edma/dw-edma-core.h +58
-0@@ -111,6 +111,21 @@ struct dw_edma {raw_spinlock_t lock;/* Only for legacy */ struct dw_edma_chip *chip; + +const struct dw_edma_core_ops *core; +}; + +typedef void (*dw_edma_handler_t )(struct dw_edma_chan *); + +struct dw_edma_core_ops { +void (*off)(struct dw_edma *dw); +u16 (*ch_count)(struct dw_edma *dw,enum dw_edma_dir dir); +enum dma_status (*ch_status)(struct dw_edma_chan *chan); +irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq,enum dw_edma_dir dir, +dw_edma_handler_t done,dw_edma_handler_t abort); +void (*start)(struct dw_edma_chunk *chunk,bool first); +void (*ch_config)(struct dw_edma_chan *chan); +void (*debugfs_on)(struct dw_edma *dw); };struct dw_edma_sg {@@ -148,4 +163,47 @@ struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan)return vc2dw_edma_chan (to_virt_chan (dchan)); } +static inline +void dw_edma_core_off (struct dw_edma *dw) +{ + dw->core->off (dw); +} + +static inline +u16 dw_edma_core_ch_count (struct dw_edma *dw,enum dw_edma_dir dir) +{ +return dw->core->ch_count (dw, dir); +} + +static inline +enum dma_status dw_edma_core_ch_status (struct dw_edma_chan *chan) +{ +return chan->dw->core->ch_status (chan); +} + +static inline irqreturn_t +dw_edma_core_handle_int (struct dw_edma_irq *dw_irq,enum dw_edma_dir dir, +dw_edma_handler_t done,dw_edma_handler_t abort) +{ +return dw_irq->dw->core->handle_int (dw_irq, dir, done, abort); +} + +static inline +void dw_edma_core_start (struct dw_edma *dw,struct dw_edma_chunk *chunk,bool first) +{ + dw->core->start (chunk, first); +} + +static inline +void dw_edma_core_ch_config (struct dw_edma_chan *chan) +{ + chan->dw->core->ch_config (chan); +} + +static inline +void dw_edma_core_debugfs_on (struct dw_edma *dw) +{ + dw->core->debugfs_on (dw); +} +#endif /* _DW_EDMA_CORE_H */ drivers/dma/dw-edma/dw-edma-v0-core.c +72
-13@@ -7,7 +7,7 @@*/ #include <linux/bitfield.h> - +#include <linux/irqreturn.h> #include <linux/io-64-nonatomic-lo-hi.h> #include "dw-edma-core.h" @@ -216,7 +216,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,readq_ch (dw, dir, ch, &(__dw_ch_regs (dw, dir, ch)->name)) /* eDMA management callbacks */ -void dw_edma_v0_core_off (struct dw_edma *dw) +static void dw_edma_v0_core_off (struct dw_edma *dw) {SET_BOTH_32 (dw, int_mask,EDMA_V0_DONE_INT_MASK |EDMA_V0_ABORT_INT_MASK );@@ -225,7 +225,7 @@ void dw_edma_v0_core_off(struct dw_edma *dw)SET_BOTH_32 (dw, engine_en,0 ); } -u16 dw_edma_v0_core_ch_count (struct dw_edma *dw,enum dw_edma_dir dir) +static u16 dw_edma_v0_core_ch_count (struct dw_edma *dw,enum dw_edma_dir dir) {u32 num_ch;@@ -242,7 +242,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)return (u16 )num_ch; } -enum dma_status dw_edma_v0_core_ch_status (struct dw_edma_chan *chan) +static enum dma_status dw_edma_v0_core_ch_status (struct dw_edma_chan *chan) {struct dw_edma *dw = chan->dw;u32 tmp;@@ -258,7 +258,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)return DMA_ERROR ; } -void dw_edma_v0_core_clear_done_int (struct dw_edma_chan *chan) +static void dw_edma_v0_core_clear_done_int (struct dw_edma_chan *chan) {struct dw_edma *dw = chan->dw;@@ -266,7 +266,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan) FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id))); } -void dw_edma_v0_core_clear_abort_int (struct dw_edma_chan *chan) +static void dw_edma_v0_core_clear_abort_int (struct dw_edma_chan *chan) {struct dw_edma *dw = chan->dw;@@ -274,18 +274,64 @@ void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan) FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id))); } -u32 dw_edma_v0_core_status_done_int (struct dw_edma *dw,enum dw_edma_dir dir) +static u32 dw_edma_v0_core_status_done_int (struct dw_edma *dw,enum dw_edma_dir dir) {return FIELD_GET (EDMA_V0_DONE_INT_MASK ,GET_RW_32 (dw, dir, int_status)); } -u32 dw_edma_v0_core_status_abort_int (struct dw_edma *dw,enum dw_edma_dir dir) +static u32 dw_edma_v0_core_status_abort_int (struct dw_edma *dw,enum dw_edma_dir dir) {return FIELD_GET (EDMA_V0_ABORT_INT_MASK ,GET_RW_32 (dw, dir, int_status)); } +static irqreturn_t +dw_edma_v0_core_handle_int (struct dw_edma_irq *dw_irq,enum dw_edma_dir dir, +dw_edma_handler_t done,dw_edma_handler_t abort) +{ +struct dw_edma *dw = dw_irq->dw; +unsigned long total, pos, val; +irqreturn_t ret =IRQ_NONE ; +struct dw_edma_chan *chan; +unsigned long off; +u32 mask; + +if (dir ==EDMA_DIR_WRITE ) { + total = dw->wr_ch_cnt; + off =0 ; + mask = dw_irq->wr_mask; + }else { + total = dw->rd_ch_cnt; + off = dw->wr_ch_cnt; + mask = dw_irq->rd_mask; + } + + val =dw_edma_v0_core_status_done_int (dw, dir); + val &= mask; +for_each_set_bit (pos, &val, total) { + chan = &dw->chan[pos + off]; + +dw_edma_v0_core_clear_done_int (chan); +done (chan); + + ret =IRQ_HANDLED ; + } + + val =dw_edma_v0_core_status_abort_int (dw, dir); + val &= mask; +for_each_set_bit (pos, &val, total) { + chan = &dw->chan[pos + off]; + +dw_edma_v0_core_clear_abort_int (chan); +abort (chan); + + ret =IRQ_HANDLED ; + } + +return ret; +} +static void dw_edma_v0_write_ll_data (struct dw_edma_chunk *chunk,int i,u32 control,u32 size,u64 sar,u64 dar) {@@ -356,7 +402,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)dw_edma_v0_write_ll_link (chunk, i, control, chunk->ll_region.paddr); } -void dw_edma_v0_core_start (struct dw_edma_chunk *chunk,bool first) +static void dw_edma_v0_core_start (struct dw_edma_chunk *chunk,bool first) {struct dw_edma_chan *chan = chunk->chan;struct dw_edma *dw = chan->dw;@@ -427,7 +473,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first) FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id)); } -int dw_edma_v0_core_device_config (struct dw_edma_chan *chan) +static void dw_edma_v0_core_ch_config (struct dw_edma_chan *chan) {struct dw_edma *dw = chan->dw;u32 tmp =0 ;@@ -494,12 +540,25 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)SET_RW_32 (dw, chan->dir, ch67_imwr_data, tmp);break ; } - -return 0 ; }/* eDMA debugfs callbacks */ -void dw_edma_v0_core_debugfs_on (struct dw_edma *dw) +static void dw_edma_v0_core_debugfs_on (struct dw_edma *dw) {dw_edma_v0_debugfs_on (dw); } + +static const struct dw_edma_core_ops dw_edma_v0_core = { + .off = dw_edma_v0_core_off, + .ch_count = dw_edma_v0_core_ch_count, + .ch_status = dw_edma_v0_core_ch_status, + .handle_int = dw_edma_v0_core_handle_int, + .start = dw_edma_v0_core_start, + .ch_config = dw_edma_v0_core_ch_config, + .debugfs_on = dw_edma_v0_core_debugfs_on, +}; + +void dw_edma_v0_core_register (struct dw_edma *dw) +{ + dw->core = &dw_edma_v0_core; +}drivers/dma/dw-edma/dw-edma-v0-core.h +2
-12@@ -11,17 +11,7 @@#include <linux/dma/edma.h> -/* eDMA management callbacks */ -void dw_edma_v0_core_off (struct dw_edma *chan); -u16 dw_edma_v0_core_ch_count (struct dw_edma *chan,enum dw_edma_dir dir); -enum dma_status dw_edma_v0_core_ch_status (struct dw_edma_chan *chan); -void dw_edma_v0_core_clear_done_int (struct dw_edma_chan *chan); -void dw_edma_v0_core_clear_abort_int (struct dw_edma_chan *chan); -u32 dw_edma_v0_core_status_done_int (struct dw_edma *chan,enum dw_edma_dir dir); -u32 dw_edma_v0_core_status_abort_int (struct dw_edma *chan,enum dw_edma_dir dir); -void dw_edma_v0_core_start (struct dw_edma_chunk *chunk,bool first); -int dw_edma_v0_core_device_config (struct dw_edma_chan *chan); -/* eDMA debug fs callbacks */ -void dw_edma_v0_core_debugfs_on (struct dw_edma *dw); +/* eDMA core register */ +void dw_edma_v0_core_register (struct dw_edma *dw);#endif /* _DW_EDMA_V0_CORE_H */ Signature · 1 line
2.34.1
PATCH v7 3/5 dmaengine: dw-edma: Add support for native HDMA
In reply to Cai HuoqingAdd support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA, so this patch add support for HDMA NATIVE mode.
HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when you have multiple write channels.
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
---v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5]. 2.Fix code style.
v6 link:
https://lore.kernel.org/lkml/[email protected]/
drivers/dma/dw-edma/Makefile | 5 +- drivers/dma/dw-edma/dw-edma-core.c | 6 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 275 ++++++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 ++++++++++++ include/linux/dma/edma.h | 3 +- 6 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.h
drivers/dma/dw-edma/Makefile +3 -2
@@ -2,6 +2,7 @@ obj-$(CONFIG_DW_EDMA) += dw-edma.o dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o -dw-edma-objs := dw-edma-core.o \ - dw-edma-v0-core.o $(dw-edma-y) +dw-edma-objs := dw-edma-core.o \ + dw-edma-v0-core.o \ + dw-hdma-v0-core.o $(dw-edma-y) obj-$(CONFIG_DW_EDMA_PCIE) += dw-edma-pcie.o
drivers/dma/dw-edma/dw-edma-core.c +5 -1
@@ -18,6 +18,7 @@#include "dw-edma-core.h" #include "dw-edma-v0-core.h" +#include "dw-hdma-v0-core.h" #include "../dmaengine.h" #include "../virt-dma.h"
@@ -917,7 +918,10 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; -dw_edma_v0_core_register (dw); +if (dw->chip->mf ==EDMA_MF_HDMA_NATIVE ) +dw_hdma_v0_core_register (dw); +else +dw_edma_v0_core_register (dw);raw_spin_lock_init (&dw->lock);
drivers/dma/dw-edma/dw-hdma-v0-core.c new file +275 -0
275 lines not on this page · raw message
drivers/dma/dw-edma/dw-hdma-v0-core.h new file +17 -0
@@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 core +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_CORE_H +#define _DW_HDMA_V0_CORE_H + +#include <linux/dma/edma.h> + +/* HDMA core register */ +void dw_hdma_v0_core_register (struct dw_edma *dw); + +#endif /* _DW_HDMA_V0_CORE_H */
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +130 -0
130 lines not on this page · raw message
include/linux/dma/edma.h +2 -1
@@ -48,7 +48,8 @@ struct dw_edma_plat_ops {enum dw_edma_map_format {EDMA_MF_EDMA_LEGACY =0x0 ,EDMA_MF_EDMA_UNROLL =0x1 , -EDMA_MF_HDMA_COMPAT =0x5 +EDMA_MF_HDMA_COMPAT =0x5 , +EDMA_MF_HDMA_NATIVE =0x7 , };/**
Signature · 1 line
2.34.1
drivers/dma/dw-edma/dw-hdma-v0-regs.h line 87
Quoted 13 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +3
-0@@ -0,0 +1,130 @@ +struct dw_hdma_v0_ch_regs { +u32 msi_msgdata;/* 0x00a8 */ +u32 padding_2[21 ];/* 0x00ac..0x00e8 */
The comment here is wrong. This goes all the way to 0x00fc.
Quoted 2 lines
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +2
-0+} __packed; +
Quoted 10 lines · Lars-Peter Clausen
Quoted 9 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +0
-0@@ -0,0 +1,130 @@
Quoted 5 lines
drivers/dma/dw-edma/dw-hdma-v0-regs.h line 87
Quoted 4 lines
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +3
-0+struct dw_hdma_v0_ch_regs { +u32 msi_msgdata;/* 0x00a8 */ +u32 padding_2[21 ];/* 0x00ac..0x00e8 */ The comment here is wrong. This goes all the way to
0x00fc.
Will fix, if send next version.
Thanks,
Cai-
Quoted 3 lines
Quoted 2 lines
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +2
-0+} __packed; +
Quoted 438 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA, so this patch add support for HDMA NATIVE mode.
HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when you have multiple write channels.
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
Signed-off-by Cai Huoqing <[email protected]>---
v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5]. 2.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 5 +- drivers/dma/dw-edma/dw-edma-core.c | 6 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 275 ++++++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 ++++++++++++ include/linux/dma/edma.h | 3 +- 6 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hdrivers/dma/dw-edma/Makefile +3
-2@@ -2,6 +2,7 @@ obj-$(CONFIG_DW_EDMA) += dw-edma.o dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o -dw-edma-objs := dw-edma-core.o \ - dw-edma-v0-core.o $(dw-edma-y) +dw-edma-objs := dw-edma-core.o \ + dw-edma-v0-core.o \ + dw-hdma-v0-core.o $(dw-edma-y) obj-$(CONFIG_DW_EDMA_PCIE) += dw-edma-pcie.odrivers/dma/dw-edma/dw-edma-core.c +5
-1@@ -18,6 +18,7 @@#include "dw-edma-core.h" #include "dw-edma-v0-core.h" +#include "dw-hdma-v0-core.h" #include "../dmaengine.h" #include "../virt-dma.h" @@ -917,7 +918,10 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; -dw_edma_v0_core_register (dw); +if (dw->chip->mf ==EDMA_MF_HDMA_NATIVE ) +dw_hdma_v0_core_register (dw); +else +dw_edma_v0_core_register (dw);raw_spin_lock_init (&dw->lock);drivers/dma/dw-edma/dw-hdma-v0-core.c new file +275
-0@@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 core +*/ + +#include <linux/bitfield.h> +#include <linux/irqreturn.h> +#include <linux/io-64-nonatomic-lo-hi.h> + +#include "dw-edma-core.h" +#include "dw-hdma-v0-core.h" +#include "dw-hdma-v0-regs.h" + +enum dw_hdma_control { +DW_HDMA_V0_CB =BIT (0 ), +DW_HDMA_V0_TCB =BIT (1 ), +DW_HDMA_V0_LLP =BIT (2 ), +DW_HDMA_V0_LIE =BIT (3 ), +DW_HDMA_V0_RIE =BIT (4 ), +DW_HDMA_V0_CCS =BIT (8 ), +DW_HDMA_V0_LLE =BIT (9 ), +}; + +static inline struct dw_hdma_v0_regs __iomem *__dw_regs (struct dw_edma *dw) +{ +return dw->chip->reg_base; +} + +static inline struct dw_hdma_v0_ch_regs __iomem * +__dw_ch_regs (struct dw_edma *dw,enum dw_edma_dir dir,u16 ch) +{ +if (dir ==EDMA_DIR_WRITE ) +return &(__dw_regs (dw)->ch[ch].wr); +else +return &(__dw_regs (dw)->ch[ch].rd); +} + +#define SET_CH_32 (dw, dir, ch, name, value) \ + writel(value, &(__dw_ch_regs(dw, dir, ch)->name)) + +#define GET_CH_32 (dw, dir, ch, name) \ + readl(&(__dw_ch_regs(dw, dir, ch)->name)) + +#define SET_BOTH_CH_32 (dw, ch, name, value) \ + do { \ + writel(value, &(__dw_ch_regs(dw, EDMA_DIR_WRITE, ch)->name)); \ + writel(value, &(__dw_ch_regs(dw, EDMA_DIR_READ, ch)->name)); \ + } while (0) + +/* HDMA management callbacks */ +static void dw_hdma_v0_core_off (struct dw_edma *dw) +{ +int id; + +for (id =0 ; id <HDMA_V0_MAX_NR_CH ; id++) { +SET_BOTH_CH_32 (dw, id, int_setup, +HDMA_V0_STOP_INT_MASK |HDMA_V0_ABORT_INT_MASK ); +SET_BOTH_CH_32 (dw, id, int_clear, +HDMA_V0_STOP_INT_MASK |HDMA_V0_ABORT_INT_MASK ); +SET_BOTH_CH_32 (dw, id, ch_en,0 ); + } +} + +static u16 dw_hdma_v0_core_ch_count (struct dw_edma *dw,enum dw_edma_dir dir) +{ +u32 num_ch =0 ; +int id; + +for (id =0 ; id <HDMA_V0_MAX_NR_CH ; id++) { +if (GET_CH_32 (dw, id, dir, ch_en) &BIT (0 )) + num_ch++; + } + +if (num_ch >HDMA_V0_MAX_NR_CH ) + num_ch =HDMA_V0_MAX_NR_CH ; + +return (u16 )num_ch; +} + +static enum dma_status dw_hdma_v0_core_ch_status (struct dw_edma_chan *chan) +{ +struct dw_edma *dw = chan->dw; +u32 tmp; + + tmp =FIELD_GET (HDMA_V0_CH_STATUS_MASK , +GET_CH_32 (dw, chan->id, chan->dir, ch_stat)); + +if (tmp ==1 ) +return DMA_IN_PROGRESS ; +else if (tmp ==3 ) +return DMA_COMPLETE ; +else +return DMA_ERROR ; +} + +static irqreturn_t +dw_hdma_v0_core_handle_int (struct dw_edma_irq *dw_irq,enum dw_edma_dir dir, +dw_edma_handler_t done,dw_edma_handler_t abort) +{ +struct dw_edma *dw = dw_irq->dw; +unsigned long total, pos, val; +irqreturn_t ret =IRQ_NONE ; +struct dw_edma_chan *chan; +unsigned long off, mask; + +if (dir ==EDMA_DIR_WRITE ) { + total = dw->wr_ch_cnt; + off =0 ; + mask = dw_irq->wr_mask; + }else { + total = dw->rd_ch_cnt; + off = dw->wr_ch_cnt; + mask = dw_irq->rd_mask; + } + +for_each_set_bit (pos, &mask, total) { + chan = &dw->chan[pos + off]; + + val =GET_CH_32 (dw, chan->dir, chan->id, int_stat); +if (FIELD_GET (HDMA_V0_STOP_INT_MASK , val)) { +SET_CH_32 (dw, chan->dir, chan->id, + int_clear,HDMA_V0_STOP_INT_MASK ); +done (chan); + + ret =IRQ_HANDLED ; + } + +if (FIELD_GET (HDMA_V0_ABORT_INT_MASK , val)) { +SET_CH_32 (dw, chan->dir, chan->id, + int_clear,HDMA_V0_ABORT_INT_MASK ); +abort (chan); + + ret =IRQ_HANDLED ; + } + } + +return ret; +} + +static void dw_hdma_v0_write_ll_data (struct dw_edma_chunk *chunk,int i, +u32 control,u32 size,u64 sar,u64 dar) +{ +ptrdiff_t ofs = i *sizeof (struct dw_hdma_v0_lli ); + +if (chunk->chan->dw->chip->flags &DW_EDMA_CHIP_LOCAL ) { +struct dw_hdma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs; + + lli->control = control; + lli->transfer_size = size; + lli->sar.reg = sar; + lli->dar.reg = dar; + }else { +struct dw_hdma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io + ofs; + +writel (control, &lli->control); +writel (size, &lli->transfer_size); +writeq (sar, &lli->sar.reg); +writeq (dar, &lli->dar.reg); + } +} + +static void dw_hdma_v0_write_ll_link (struct dw_edma_chunk *chunk, +int i,u32 control,u64 pointer) +{ +ptrdiff_t ofs = i *sizeof (struct dw_hdma_v0_lli ); + +if (chunk->chan->dw->chip->flags &DW_EDMA_CHIP_LOCAL ) { +struct dw_hdma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs; + + llp->control = control; + llp->llp.reg = pointer; + }else { +struct dw_hdma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io + ofs; + +writel (control, &llp->control); +writeq (pointer, &llp->llp.reg); + } +} + +static void dw_hdma_v0_core_write_chunk (struct dw_edma_chunk *chunk) +{ +struct dw_edma_burst *child; +struct dw_edma_chan *chan = chunk->chan; +u32 control =0 , i =0 ; +int j; + +if (chunk->cb) + control =DW_HDMA_V0_CB ; + + j = chunk->bursts_alloc; +list_for_each_entry (child, &chunk->burst->list, list) { + j--; +if (!j) { + control |=DW_HDMA_V0_LIE ; +if (!(chan->dw->chip->flags &DW_EDMA_CHIP_LOCAL )) + control |=DW_HDMA_V0_RIE ; + } + +dw_hdma_v0_write_ll_data (chunk, i++, control, child->sz, + child->sar, child->dar); + } + + control =DW_HDMA_V0_LLP |DW_HDMA_V0_TCB ; +if (!chunk->cb) + control |=DW_HDMA_V0_CB ; + +dw_hdma_v0_write_ll_link (chunk, i, control, chunk->ll_region.paddr); +} + +static void dw_hdma_v0_core_start (struct dw_edma_chunk *chunk,bool first) +{ +struct dw_edma_chan *chan = chunk->chan; +struct dw_edma *dw = chan->dw; +u32 tmp; + +dw_hdma_v0_core_write_chunk (chunk); + +if (first) { +/* Enable engine */ +SET_CH_32 (dw, chan->dir, chan->id, ch_en,BIT (0 )); +/* Interrupt enable&unmask - done, abort */ + tmp =GET_CH_32 (dw, chan->dir, chan->id, int_setup) | +HDMA_V0_STOP_INT_MASK |HDMA_V0_ABORT_INT_MASK | +HDMA_V0_LOCAL_STOP_INT_EN |HDMA_V0_LOCAL_STOP_INT_EN ; +SET_CH_32 (dw, chan->dir, chan->id, int_setup, tmp); +/* Channel control */ +SET_CH_32 (dw, chan->dir, chan->id, control1,HDMA_V0_LINKLIST_EN ); +/* Linked list */ +/* llp is not aligned on 64bit -> keep 32bit accesses */ +SET_CH_32 (dw, chan->dir, chan->id, llp.lsb, +lower_32_bits (chunk->ll_region.paddr)); +SET_CH_32 (dw, chan->dir, chan->id, llp.msb, +upper_32_bits (chunk->ll_region.paddr)); + } +/* Set consumer cycle */ +SET_CH_32 (dw, chan->dir, chan->id, cycle_sync, +HDMA_V0_CONSUMER_CYCLE_STAT |HDMA_V0_CONSUMER_CYCLE_BIT ); +/* Doorbell */ +SET_CH_32 (dw, chan->dir, chan->id, doorbell,HDMA_V0_DOORBELL_START ); +} + +static void dw_hdma_v0_core_ch_config (struct dw_edma_chan *chan) +{ +struct dw_edma *dw = chan->dw; + +/* MSI done addr - low, high */ +SET_CH_32 (dw, chan->dir, chan->id, msi_stop.lsb, chan->msi.address_lo); +SET_CH_32 (dw, chan->dir, chan->id, msi_stop.msb, chan->msi.address_hi); +/* MSI abort addr - low, high */ +SET_CH_32 (dw, chan->dir, chan->id, msi_abort.lsb, chan->msi.address_lo); +SET_CH_32 (dw, chan->dir, chan->id, msi_abort.msb, chan->msi.address_hi); +/* config MSI data */ +SET_CH_32 (dw, chan->dir, chan->id, msi_msgdata, chan->msi.data); +} + +/* HDMA debugfs callbacks */ +static void dw_hdma_v0_core_debugfs_on (struct dw_edma *dw) +{ +} + +static const struct dw_edma_core_ops dw_hdma_v0_core = { + .off = dw_hdma_v0_core_off, + .ch_count = dw_hdma_v0_core_ch_count, + .ch_status = dw_hdma_v0_core_ch_status, + .handle_int = dw_hdma_v0_core_handle_int, + .start = dw_hdma_v0_core_start, + .ch_config = dw_hdma_v0_core_ch_config, + .debugfs_on = dw_hdma_v0_core_debugfs_on, +}; + +void dw_hdma_v0_core_register (struct dw_edma *dw) +{ + dw->core = &dw_hdma_v0_core; +}drivers/dma/dw-edma/dw-hdma-v0-core.h new file +17
-0@@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 core +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_CORE_H +#define _DW_HDMA_V0_CORE_H + +#include <linux/dma/edma.h> + +/* HDMA core register */ +void dw_hdma_v0_core_register (struct dw_edma *dw); + +#endif /* _DW_HDMA_V0_CORE_H */ drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +50
-0@@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 reg +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_REGS_H +#define _DW_HDMA_V0_REGS_H + +#include <linux/dmaengine.h> + +#define HDMA_V0_MAX_NR_CH 8 +#define HDMA_V0_LOCAL_ABORT_INT_EN BIT(6) +#define HDMA_V0_REMOTE_ABORT_INT_EN BIT(5) +#define HDMA_V0_LOCAL_STOP_INT_EN BIT(4) +#define HDMA_V0_REMOTEL_STOP_INT_EN BIT(3) +#define HDMA_V0_ABORT_INT_MASK BIT(2) +#define HDMA_V0_STOP_INT_MASK BIT(0) +#define HDMA_V0_LINKLIST_EN BIT(0) +#define HDMA_V0_CONSUMER_CYCLE_STAT BIT(1) +#define HDMA_V0_CONSUMER_CYCLE_BIT BIT(0) +#define HDMA_V0_DOORBELL_START BIT(0) +#define HDMA_V0_CH_STATUS_MASK GENMASK(1, 0) + +struct dw_hdma_v0_ch_regs { + u32 ch_en; /* 0x0000 */ + u32 doorbell; /* 0x0004 */ + u32 prefetch; /* 0x0008 */ + u32 handshake; /* 0x000c */ + union { + u64 reg; /* 0x0010..0x0014 */ + struct { + u32 lsb; /* 0x0010 */ + u32 msb; /* 0x0014 */ + }; + } llp; + u32 cycle_sync; /* 0x0018 */ + u32 transfer_size; /* 0x001c */ + union { + u64 reg; /* 0x0020..0x0024 */ + struct { + u32 lsb; /* 0x0020 */ + u32 msb; /* 0x0024 */ + }; + } sar; + union { + u64 reg; /* 0x0028..0x002c */ + struct {
drivers/dma/dw-edma/dw-hdma-v0-regs.h line 60
Quoted 10 lines
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +10
-0+u32 lsb;/* 0x0028 */ +u32 msb;/* 0x002c */ + }; + } dar; + +u32 watermark_en;/* 0x0030 */ +u32 control1;/* 0x0034 */ +u32 func_num;/* 0x0038 */ +u32 qos;/* 0x003c */ +u32 padding_1[16 ];/* 0x0040..0x0078 */
Will change it to 0x007c instead of 0x0078
Quoted 87 lines
drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +70
-0+u32 ch_stat;/* 0x0080 */ +u32 int_stat;/* 0x0084 */ +u32 int_setup;/* 0x0088 */ +u32 int_clear;/* 0x008c */ +union { +u64 reg;/* 0x0090..0x0094 */ +struct { +u32 lsb;/* 0x0090 */ +u32 msb;/* 0x0094 */ + }; + } msi_stop; +union { +u64 reg;/* 0x0098..0x009c */ +struct { +u32 lsb;/* 0x0098 */ +u32 msb;/* 0x009c */ + }; + } msi_watermark; +union { +u64 reg;/* 0x00a0..0x00a4 */ +struct { +u32 lsb;/* 0x00a0 */ +u32 msb;/* 0x00a4 */ + }; + } msi_abort; +u32 msi_msgdata;/* 0x00a8 */ + u32 padding_2[21]; /* 0x00ac..0x00e8 */ +} __packed; + +struct dw_hdma_v0_ch { +struct dw_hdma_v0_ch_regs wr;/* 0x0000 */ +struct dw_hdma_v0_ch_regs rd;/* 0x0100 */ +} __packed; + +struct dw_hdma_v0_regs { +struct dw_hdma_v0_ch ch[HDMA_V0_MAX_NR_CH ];/* 0x0000..0x0fa8 */ +} __packed; + +struct dw_hdma_v0_lli { +u32 control; +u32 transfer_size; +union { +u64 reg; +struct { +u32 lsb; +u32 msb; + }; + } sar; +union { +u64 reg; +struct { +u32 lsb; +u32 msb; + }; + } dar; +} __packed; + +struct dw_hdma_v0_llp { +u32 control; +u32 reserved; +union { +u64 reg; +struct { +u32 lsb; +u32 msb; + }; + } llp; +} __packed; + +#endif /* _DW_HDMA_V0_REGS_H */ include/linux/dma/edma.h +2
-1@@ -48,7 +48,8 @@ struct dw_edma_plat_ops {enum dw_edma_map_format {EDMA_MF_EDMA_LEGACY =0x0 ,EDMA_MF_EDMA_UNROLL =0x1 , -EDMA_MF_HDMA_COMPAT =0x5 +EDMA_MF_HDMA_COMPAT =0x5 , +EDMA_MF_HDMA_NATIVE =0x7 , };/** Signature · 1 line
2.34.1
Quoted 206 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA, so this patch add support for HDMA NATIVE mode.
HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when you have multiple write channels.
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
Signed-off-by Cai Huoqing <[email protected]>---
v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5]. 2.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 5 +- drivers/dma/dw-edma/dw-edma-core.c | 6 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 275 ++++++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 ++++++++++++ include/linux/dma/edma.h | 3 +- 6 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hdrivers/dma/dw-edma/Makefile +3
-2@@ -2,6 +2,7 @@ obj-$(CONFIG_DW_EDMA) += dw-edma.o dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o -dw-edma-objs := dw-edma-core.o \ - dw-edma-v0-core.o $(dw-edma-y) +dw-edma-objs := dw-edma-core.o \ + dw-edma-v0-core.o \ + dw-hdma-v0-core.o $(dw-edma-y) obj-$(CONFIG_DW_EDMA_PCIE) += dw-edma-pcie.odrivers/dma/dw-edma/dw-edma-core.c +5
-1@@ -18,6 +18,7 @@#include "dw-edma-core.h" #include "dw-edma-v0-core.h" +#include "dw-hdma-v0-core.h" #include "../dmaengine.h" #include "../virt-dma.h" @@ -917,7 +918,10 @@ int dw_edma_probe(struct dw_edma_chip *chip) dw->chip = chip; -dw_edma_v0_core_register (dw); +if (dw->chip->mf ==EDMA_MF_HDMA_NATIVE ) +dw_hdma_v0_core_register (dw); +else +dw_edma_v0_core_register (dw);raw_spin_lock_init (&dw->lock);drivers/dma/dw-edma/dw-hdma-v0-core.c new file +121
-0@@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 core +*/ + +#include <linux/bitfield.h> +#include <linux/irqreturn.h> +#include <linux/io-64-nonatomic-lo-hi.h> + +#include "dw-edma-core.h" +#include "dw-hdma-v0-core.h" +#include "dw-hdma-v0-regs.h" + +enum dw_hdma_control { +DW_HDMA_V0_CB =BIT (0 ), +DW_HDMA_V0_TCB =BIT (1 ), +DW_HDMA_V0_LLP =BIT (2 ), +DW_HDMA_V0_LIE =BIT (3 ), +DW_HDMA_V0_RIE =BIT (4 ), +DW_HDMA_V0_CCS =BIT (8 ), +DW_HDMA_V0_LLE =BIT (9 ), +}; + +static inline struct dw_hdma_v0_regs __iomem *__dw_regs (struct dw_edma *dw) +{ +return dw->chip->reg_base; +} + +static inline struct dw_hdma_v0_ch_regs __iomem * +__dw_ch_regs (struct dw_edma *dw,enum dw_edma_dir dir,u16 ch) +{ +if (dir ==EDMA_DIR_WRITE ) +return &(__dw_regs (dw)->ch[ch].wr); +else +return &(__dw_regs (dw)->ch[ch].rd); +} + +#define SET_CH_32 (dw, dir, ch, name, value) \ + writel(value, &(__dw_ch_regs(dw, dir, ch)->name)) + +#define GET_CH_32 (dw, dir, ch, name) \ + readl(&(__dw_ch_regs(dw, dir, ch)->name)) + +#define SET_BOTH_CH_32 (dw, ch, name, value) \ + do { \ + writel(value, &(__dw_ch_regs(dw, EDMA_DIR_WRITE, ch)->name)); \ + writel(value, &(__dw_ch_regs(dw, EDMA_DIR_READ, ch)->name)); \ + } while (0) + +/* HDMA management callbacks */ +static void dw_hdma_v0_core_off (struct dw_edma *dw) +{ +int id; + +for (id =0 ; id <HDMA_V0_MAX_NR_CH ; id++) { +SET_BOTH_CH_32 (dw, id, int_setup, +HDMA_V0_STOP_INT_MASK |HDMA_V0_ABORT_INT_MASK ); +SET_BOTH_CH_32 (dw, id, int_clear, +HDMA_V0_STOP_INT_MASK |HDMA_V0_ABORT_INT_MASK ); +SET_BOTH_CH_32 (dw, id, ch_en,0 ); + } +} + +static u16 dw_hdma_v0_core_ch_count (struct dw_edma *dw,enum dw_edma_dir dir) +{ +u32 num_ch =0 ; +int id; + +for (id =0 ; id <HDMA_V0_MAX_NR_CH ; id++) { +if (GET_CH_32 (dw, id, dir, ch_en) &BIT (0 )) + num_ch++; + } + +if (num_ch >HDMA_V0_MAX_NR_CH ) + num_ch =HDMA_V0_MAX_NR_CH ; + +return (u16 )num_ch; +} + +static enum dma_status dw_hdma_v0_core_ch_status (struct dw_edma_chan *chan) +{ +struct dw_edma *dw = chan->dw; +u32 tmp; + + tmp =FIELD_GET (HDMA_V0_CH_STATUS_MASK , +GET_CH_32 (dw, chan->id, chan->dir, ch_stat)); + +if (tmp ==1 ) +return DMA_IN_PROGRESS ; +else if (tmp ==3 ) +return DMA_COMPLETE ; +else +return DMA_ERROR ; +} + +static irqreturn_t +dw_hdma_v0_core_handle_int (struct dw_edma_irq *dw_irq,enum dw_edma_dir dir, +dw_edma_handler_t done,dw_edma_handler_t abort) +{ +struct dw_edma *dw = dw_irq->dw; +unsigned long total, pos, val; +irqreturn_t ret =IRQ_NONE ; +struct dw_edma_chan *chan; +unsigned long off, mask; + +if (dir ==EDMA_DIR_WRITE ) { + total = dw->wr_ch_cnt; + off =0 ; + mask = dw_irq->wr_mask; + }else { + total = dw->rd_ch_cnt; + off = dw->wr_ch_cnt; + mask = dw_irq->rd_mask; + } + +for_each_set_bit (pos, &mask, total) { + chan = &dw->chan[pos + off]; + + val =GET_CH_32 (dw, chan->dir, chan->id, int_stat); +if (FIELD_GET (HDMA_V0_STOP_INT_MASK , val)) {
drivers/dma/dw-edma/dw-hdma-v0-core.c line 131
Quoted 10 lines
drivers/dma/dw-edma/dw-hdma-v0-core.c new file +10
-0+SET_CH_32 (dw, chan->dir, chan->id, + int_clear,HDMA_V0_STOP_INT_MASK ); +done (chan); + + ret =IRQ_HANDLED ; + } + +if (FIELD_GET (HDMA_V0_ABORT_INT_MASK , val)) { +SET_CH_32 (dw, chan->dir, chan->id, + int_clear,HDMA_V0_ABORT_INT_MASK );
Let's get back the static methods: dw_hdma_v0_core_clear_done_int(), dw_hdma_v0_core_clear_abort_int() and dw_hdma_v0_core_status_int(). It shall look a little tiny bit more readable at least in case of the DW eDMA. Meanwhile having them here, in DW HDMA, would look more coherent with the DW eDMA core code. So please get them back and drop the last patch in the series.
Other than that looks good.
-Serge(y)
Quoted 320 lines
drivers/dma/dw-edma/dw-hdma-v0-core.c new file +144
-0+abort (chan); + + ret =IRQ_HANDLED ; + } + } + +return ret; +} + +static void dw_hdma_v0_write_ll_data (struct dw_edma_chunk *chunk,int i, +u32 control,u32 size,u64 sar,u64 dar) +{ +ptrdiff_t ofs = i *sizeof (struct dw_hdma_v0_lli ); + +if (chunk->chan->dw->chip->flags &DW_EDMA_CHIP_LOCAL ) { +struct dw_hdma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs; + + lli->control = control; + lli->transfer_size = size; + lli->sar.reg = sar; + lli->dar.reg = dar; + }else { +struct dw_hdma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io + ofs; + +writel (control, &lli->control); +writel (size, &lli->transfer_size); +writeq (sar, &lli->sar.reg); +writeq (dar, &lli->dar.reg); + } +} + +static void dw_hdma_v0_write_ll_link (struct dw_edma_chunk *chunk, +int i,u32 control,u64 pointer) +{ +ptrdiff_t ofs = i *sizeof (struct dw_hdma_v0_lli ); + +if (chunk->chan->dw->chip->flags &DW_EDMA_CHIP_LOCAL ) { +struct dw_hdma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs; + + llp->control = control; + llp->llp.reg = pointer; + }else { +struct dw_hdma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io + ofs; + +writel (control, &llp->control); +writeq (pointer, &llp->llp.reg); + } +} + +static void dw_hdma_v0_core_write_chunk (struct dw_edma_chunk *chunk) +{ +struct dw_edma_burst *child; +struct dw_edma_chan *chan = chunk->chan; +u32 control =0 , i =0 ; +int j; + +if (chunk->cb) + control =DW_HDMA_V0_CB ; + + j = chunk->bursts_alloc; +list_for_each_entry (child, &chunk->burst->list, list) { + j--; +if (!j) { + control |=DW_HDMA_V0_LIE ; +if (!(chan->dw->chip->flags &DW_EDMA_CHIP_LOCAL )) + control |=DW_HDMA_V0_RIE ; + } + +dw_hdma_v0_write_ll_data (chunk, i++, control, child->sz, + child->sar, child->dar); + } + + control =DW_HDMA_V0_LLP |DW_HDMA_V0_TCB ; +if (!chunk->cb) + control |=DW_HDMA_V0_CB ; + +dw_hdma_v0_write_ll_link (chunk, i, control, chunk->ll_region.paddr); +} + +static void dw_hdma_v0_core_start (struct dw_edma_chunk *chunk,bool first) +{ +struct dw_edma_chan *chan = chunk->chan; +struct dw_edma *dw = chan->dw; +u32 tmp; + +dw_hdma_v0_core_write_chunk (chunk); + +if (first) { +/* Enable engine */ +SET_CH_32 (dw, chan->dir, chan->id, ch_en,BIT (0 )); +/* Interrupt enable&unmask - done, abort */ + tmp =GET_CH_32 (dw, chan->dir, chan->id, int_setup) | +HDMA_V0_STOP_INT_MASK |HDMA_V0_ABORT_INT_MASK | +HDMA_V0_LOCAL_STOP_INT_EN |HDMA_V0_LOCAL_STOP_INT_EN ; +SET_CH_32 (dw, chan->dir, chan->id, int_setup, tmp); +/* Channel control */ +SET_CH_32 (dw, chan->dir, chan->id, control1,HDMA_V0_LINKLIST_EN ); +/* Linked list */ +/* llp is not aligned on 64bit -> keep 32bit accesses */ +SET_CH_32 (dw, chan->dir, chan->id, llp.lsb, +lower_32_bits (chunk->ll_region.paddr)); +SET_CH_32 (dw, chan->dir, chan->id, llp.msb, +upper_32_bits (chunk->ll_region.paddr)); + } +/* Set consumer cycle */ +SET_CH_32 (dw, chan->dir, chan->id, cycle_sync, +HDMA_V0_CONSUMER_CYCLE_STAT |HDMA_V0_CONSUMER_CYCLE_BIT ); +/* Doorbell */ +SET_CH_32 (dw, chan->dir, chan->id, doorbell,HDMA_V0_DOORBELL_START ); +} + +static void dw_hdma_v0_core_ch_config (struct dw_edma_chan *chan) +{ +struct dw_edma *dw = chan->dw; + +/* MSI done addr - low, high */ +SET_CH_32 (dw, chan->dir, chan->id, msi_stop.lsb, chan->msi.address_lo); +SET_CH_32 (dw, chan->dir, chan->id, msi_stop.msb, chan->msi.address_hi); +/* MSI abort addr - low, high */ +SET_CH_32 (dw, chan->dir, chan->id, msi_abort.lsb, chan->msi.address_lo); +SET_CH_32 (dw, chan->dir, chan->id, msi_abort.msb, chan->msi.address_hi); +/* config MSI data */ +SET_CH_32 (dw, chan->dir, chan->id, msi_msgdata, chan->msi.data); +} + +/* HDMA debugfs callbacks */ +static void dw_hdma_v0_core_debugfs_on (struct dw_edma *dw) +{ +} + +static const struct dw_edma_core_ops dw_hdma_v0_core = { + .off = dw_hdma_v0_core_off, + .ch_count = dw_hdma_v0_core_ch_count, + .ch_status = dw_hdma_v0_core_ch_status, + .handle_int = dw_hdma_v0_core_handle_int, + .start = dw_hdma_v0_core_start, + .ch_config = dw_hdma_v0_core_ch_config, + .debugfs_on = dw_hdma_v0_core_debugfs_on, +}; + +void dw_hdma_v0_core_register (struct dw_edma *dw) +{ + dw->core = &dw_hdma_v0_core; +}drivers/dma/dw-edma/dw-hdma-v0-core.h new file +17
-0@@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 core +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_CORE_H +#define _DW_HDMA_V0_CORE_H + +#include <linux/dma/edma.h> + +/* HDMA core register */ +void dw_hdma_v0_core_register (struct dw_edma *dw); + +#endif /* _DW_HDMA_V0_CORE_H */ drivers/dma/dw-edma/dw-hdma-v0-regs.h new file +130
-0@@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 reg +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_REGS_H +#define _DW_HDMA_V0_REGS_H + +#include <linux/dmaengine.h> + +#define HDMA_V0_MAX_NR_CH 8 +#define HDMA_V0_LOCAL_ABORT_INT_EN BIT(6) +#define HDMA_V0_REMOTE_ABORT_INT_EN BIT(5) +#define HDMA_V0_LOCAL_STOP_INT_EN BIT(4) +#define HDMA_V0_REMOTEL_STOP_INT_EN BIT(3) +#define HDMA_V0_ABORT_INT_MASK BIT(2) +#define HDMA_V0_STOP_INT_MASK BIT(0) +#define HDMA_V0_LINKLIST_EN BIT(0) +#define HDMA_V0_CONSUMER_CYCLE_STAT BIT(1) +#define HDMA_V0_CONSUMER_CYCLE_BIT BIT(0) +#define HDMA_V0_DOORBELL_START BIT(0) +#define HDMA_V0_CH_STATUS_MASK GENMASK(1, 0) + +struct dw_hdma_v0_ch_regs { +u32 ch_en;/* 0x0000 */ +u32 doorbell;/* 0x0004 */ +u32 prefetch;/* 0x0008 */ +u32 handshake;/* 0x000c */ +union { +u64 reg;/* 0x0010..0x0014 */ +struct { +u32 lsb;/* 0x0010 */ +u32 msb;/* 0x0014 */ + }; + } llp; +u32 cycle_sync;/* 0x0018 */ +u32 transfer_size;/* 0x001c */ +union { +u64 reg;/* 0x0020..0x0024 */ +struct { +u32 lsb;/* 0x0020 */ +u32 msb;/* 0x0024 */ + }; + } sar; +union { +u64 reg;/* 0x0028..0x002c */ +struct { +u32 lsb;/* 0x0028 */ +u32 msb;/* 0x002c */ + }; + } dar; + +u32 watermark_en;/* 0x0030 */ +u32 control1;/* 0x0034 */ +u32 func_num;/* 0x0038 */ +u32 qos;/* 0x003c */ +u32 padding_1[16 ];/* 0x0040..0x0078 */ +u32 ch_stat;/* 0x0080 */ +u32 int_stat;/* 0x0084 */ +u32 int_setup;/* 0x0088 */ +u32 int_clear;/* 0x008c */ +union { +u64 reg;/* 0x0090..0x0094 */ +struct { +u32 lsb;/* 0x0090 */ +u32 msb;/* 0x0094 */ + }; + } msi_stop; +union { +u64 reg;/* 0x0098..0x009c */ +struct { +u32 lsb;/* 0x0098 */ +u32 msb;/* 0x009c */ + }; + } msi_watermark; +union { +u64 reg;/* 0x00a0..0x00a4 */ +struct { +u32 lsb;/* 0x00a0 */ +u32 msb;/* 0x00a4 */ + }; + } msi_abort; +u32 msi_msgdata;/* 0x00a8 */ +u32 padding_2[21 ];/* 0x00ac..0x00e8 */ +} __packed; + +struct dw_hdma_v0_ch { +struct dw_hdma_v0_ch_regs wr;/* 0x0000 */ +struct dw_hdma_v0_ch_regs rd;/* 0x0100 */ +} __packed; + +struct dw_hdma_v0_regs { +struct dw_hdma_v0_ch ch[HDMA_V0_MAX_NR_CH ];/* 0x0000..0x0fa8 */ +} __packed; + +struct dw_hdma_v0_lli { +u32 control; +u32 transfer_size; +union { +u64 reg; +struct { +u32 lsb; +u32 msb; + }; + } sar; +union { +u64 reg; +struct { +u32 lsb; +u32 msb; + }; + } dar; +} __packed; + +struct dw_hdma_v0_llp { +u32 control; +u32 reserved; +union { +u64 reg; +struct { +u32 lsb; +u32 msb; + }; + } llp; +} __packed; + +#endif /* _DW_HDMA_V0_REGS_H */ include/linux/dma/edma.h +2
-1@@ -48,7 +48,8 @@ struct dw_edma_plat_ops {enum dw_edma_map_format {EDMA_MF_EDMA_LEGACY =0x0 ,EDMA_MF_EDMA_UNROLL =0x1 , -EDMA_MF_HDMA_COMPAT =0x5 +EDMA_MF_HDMA_COMPAT =0x5 , +EDMA_MF_HDMA_NATIVE =0x7 , };/** Signature · 1 line
2.34.1
PATCH v7 4/5 dmaengine: dw-edma: Add HDMA DebugFS support
In reply to Cai HuoqingFrom: Cai huoqing <[email protected]>
Add HDMA DebugFS support to show register information
---v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5].
v6 link:
https://lore.kernel.org/lkml/[email protected]/
drivers/dma/dw-edma/Makefile | 3 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 2 + drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 +++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 +++ 4 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h
drivers/dma/dw-edma/Makefile +2 -1
@@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DW_EDMA) += dw-edma.o -dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o +dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o \ + dw-hdma-v0-debugfs.o dw-edma-objs := dw-edma-core.o \ dw-edma-v0-core.o \ dw-hdma-v0-core.o $(dw-edma-y)
drivers/dma/dw-edma/dw-hdma-v0-core.c +2 -0
@@ -11,6 +11,7 @@#include "dw-edma-core.h" #include "dw-hdma-v0-core.h" #include "dw-hdma-v0-regs.h" +#include "dw-hdma-v0-debugfs.h" enum dw_hdma_control {DW_HDMA_V0_CB =BIT (0 ),
@@ -257,6 +258,7 @@ static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan)/* HDMA debugfs callbacks */ static void dw_hdma_v0_core_debugfs_on (struct dw_edma *dw) { +dw_hdma_v0_debugfs_on (dw); }static const struct dw_edma_core_ops dw_hdma_v0_core = {
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +176 -0
176 lines not on this page · raw message
drivers/dma/dw-edma/dw-hdma-v0-debugfs.h new file +22 -0
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_DEBUG_FS_H +#define _DW_HDMA_V0_DEBUG_FS_H + +#include <linux/dma/edma.h> + +#ifdef CONFIG_DEBUG_FS +void dw_hdma_v0_debugfs_on (struct dw_edma *dw); +#else +static inline void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* _DW_HDMA_V0_DEBUG_FS_H */
Signature · 1 line
2.34.1
Re: [PATCH v7 4/5] dmaengine: dw-edma: Add HDMA DebugFS support
Quoted 101 lines · Cai Huoqing
From: Cai huoqing <[email protected]>
Add HDMA DebugFS support to show register information
Signed-off-by Cai huoqing <[email protected]>---
v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5].
v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 3 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 2 + drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 +++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 +++ 4 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.hdrivers/dma/dw-edma/Makefile +2
-1@@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DW_EDMA) += dw-edma.o -dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o +dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o \ + dw-hdma-v0-debugfs.o dw-edma-objs := dw-edma-core.o \ dw-edma-v0-core.o \ dw-hdma-v0-core.o $(dw-edma-y)drivers/dma/dw-edma/dw-hdma-v0-core.c +2
-0@@ -11,6 +11,7 @@#include "dw-edma-core.h" #include "dw-hdma-v0-core.h" #include "dw-hdma-v0-regs.h" +#include "dw-hdma-v0-debugfs.h" enum dw_hdma_control {DW_HDMA_V0_CB =BIT (0 ),@@ -257,6 +258,7 @@ static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan)/* HDMA debugfs callbacks */ static void dw_hdma_v0_core_debugfs_on (struct dw_edma *dw) { +dw_hdma_v0_debugfs_on (dw); }static const struct dw_edma_core_ops dw_hdma_v0_core = {drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +42
-0@@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/bitfield.h> + +#include "dw-hdma-v0-debugfs.h" +#include "dw-hdma-v0-regs.h" +#include "dw-edma-core.h" + +#define REGS_ADDR (dw, name) \ + ({ \ + struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \ + \ + (void __iomem *)&__regs->name; \ + }) + +#define REGS_CH_ADDR (dw, name, _dir, _ch) \ + ({ \ + struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ + \ + if (_dir == EDMA_DIR_READ) \ + __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \ + else \ + __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \ + \ + (void __iomem *)&__ch_regs->name; \ + }) + +#define CTX_REGISTER (dw, name, dir, ch) \ + { dw, #name, REGS_CH_ADDR(dw, name, dir, ch), dir, ch } + +#define REGISTER (dw, name) \ + { dw, #name, REGS_ADDR(dw, name) } + +#define WRITE_STR "write" +#define READ_STR "read"
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c line 51
Quoted 10 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +9
-0+#define CHANNEL_STR "channel" +#define REGISTERS_STR "registers" + +struct dw_hdma_debugfs_entry { +struct dw_edma *dw; +const char *name; +void __iomem *reg; +enum dw_edma_dir dir; +u16 ch;
Fields above seems like unused. What about dropping them?
* Note the CTX_REGISTER() initializer will need to be fixed too.
BTW it doesn't seem like HDMA will ever need the fields above, does it? In case of DW eDMA they were necessary to perform the viewport-based access of the CSR. AFAICS HDMA has always unrolled CSRs mapping. Am I right?
Other than that looks good.
-Serge(y)
Quoted 156 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +125
-0+}; + +static int dw_hdma_debugfs_u32_get (void *data,u64 *val) +{ +struct dw_hdma_debugfs_entry *entry = data; +void __iomem *reg = entry->reg; + + *val =readl (reg); + +return 0 ; +} +DEFINE_DEBUGFS_ATTRIBUTE (fops_x32, dw_hdma_debugfs_u32_get,NULL ,"0x%08llx\n" ); + +static void dw_hdma_debugfs_create_x32 (struct dw_edma *dw, +const struct dw_hdma_debugfs_entry ini[], +int nr_entries,struct dentry *dent) +{ +struct dw_hdma_debugfs_entry *entries; +int i; + + entries =devm_kcalloc (dw->chip->dev, nr_entries,sizeof (*entries), +GFP_KERNEL ); +if (!entries) +return ; + +for (i =0 ; i < nr_entries; i++) { + entries[i] = ini[i]; + +debugfs_create_file_unsafe (entries[i].name,0444 , dent, + &entries[i], &fops_x32); + } +} + +static void dw_hdma_debugfs_regs_ch (struct dw_edma *dw,enum dw_edma_dir dir, +u16 ch,struct dentry *dent) +{ +const struct dw_hdma_debugfs_entry debugfs_regs[] = { +CTX_REGISTER (dw, ch_en, dir, ch), +CTX_REGISTER (dw, doorbell, dir, ch), +CTX_REGISTER (dw, prefetch, dir, ch), +CTX_REGISTER (dw, handshake, dir, ch), +CTX_REGISTER (dw, llp.lsb, dir, ch), +CTX_REGISTER (dw, llp.msb, dir, ch), +CTX_REGISTER (dw, cycle_sync, dir, ch), +CTX_REGISTER (dw, transfer_size, dir, ch), +CTX_REGISTER (dw, sar.lsb, dir, ch), +CTX_REGISTER (dw, sar.msb, dir, ch), +CTX_REGISTER (dw, dar.lsb, dir, ch), +CTX_REGISTER (dw, dar.msb, dir, ch), +CTX_REGISTER (dw, watermark_en, dir, ch), +CTX_REGISTER (dw, control1, dir, ch), +CTX_REGISTER (dw, func_num, dir, ch), +CTX_REGISTER (dw, qos, dir, ch), +CTX_REGISTER (dw, ch_stat, dir, ch), +CTX_REGISTER (dw, int_stat, dir, ch), +CTX_REGISTER (dw, int_setup, dir, ch), +CTX_REGISTER (dw, int_clear, dir, ch), +CTX_REGISTER (dw, msi_stop.lsb, dir, ch), +CTX_REGISTER (dw, msi_stop.msb, dir, ch), +CTX_REGISTER (dw, msi_watermark.lsb, dir, ch), +CTX_REGISTER (dw, msi_watermark.msb, dir, ch), +CTX_REGISTER (dw, msi_abort.lsb, dir, ch), +CTX_REGISTER (dw, msi_abort.msb, dir, ch), +CTX_REGISTER (dw, msi_msgdata, dir, ch), + }; +int nr_entries =ARRAY_SIZE (debugfs_regs); + +dw_hdma_debugfs_create_x32 (dw, debugfs_regs, nr_entries, dent); +} + +static void dw_hdma_debugfs_regs_wr (struct dw_edma *dw,struct dentry *dent) +{ +struct dentry *regs_dent, *ch_dent; +char name[16 ]; +int i; + + regs_dent =debugfs_create_dir (WRITE_STR , dent); + +for (i =0 ; i < dw->wr_ch_cnt; i++) { +snprintf (name,sizeof (name),"%s:%d" ,CHANNEL_STR , i); + + ch_dent =debugfs_create_dir (name, regs_dent); + +dw_hdma_debugfs_regs_ch (dw,EDMA_DIR_WRITE , i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs_rd (struct dw_edma *dw,struct dentry *dent) +{ +struct dentry *regs_dent, *ch_dent; +char name[16 ]; +int i; + + regs_dent =debugfs_create_dir (READ_STR , dent); + +for (i =0 ; i < dw->rd_ch_cnt; i++) { +snprintf (name,sizeof (name),"%s:%d" ,CHANNEL_STR , i); + + ch_dent =debugfs_create_dir (name, regs_dent); + +dw_hdma_debugfs_regs_ch (dw,EDMA_DIR_READ , i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs (struct dw_edma *dw) +{ +struct dentry *regs_dent; + + regs_dent =debugfs_create_dir (REGISTERS_STR , dw->dma.dbg_dev_root); + +dw_hdma_debugfs_regs_wr (dw, regs_dent); +dw_hdma_debugfs_regs_rd (dw, regs_dent); +} + +void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +if (!debugfs_initialized ()) +return ; + +debugfs_create_u32 ("mf" ,0444 , dw->dma.dbg_dev_root, &dw->chip->mf); +debugfs_create_u16 ("wr_ch_cnt" ,0444 , dw->dma.dbg_dev_root, &dw->wr_ch_cnt); +debugfs_create_u16 ("rd_ch_cnt" ,0444 , dw->dma.dbg_dev_root, &dw->rd_ch_cnt); + +dw_hdma_debugfs_regs (dw); +}drivers/dma/dw-edma/dw-hdma-v0-debugfs.h new file +22
-0@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_DEBUG_FS_H +#define _DW_HDMA_V0_DEBUG_FS_H + +#include <linux/dma/edma.h> + +#ifdef CONFIG_DEBUG_FS +void dw_hdma_v0_debugfs_on (struct dw_edma *dw); +#else +static inline void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* _DW_HDMA_V0_DEBUG_FS_H */ Signature · 1 line
2.34.1
Re: [PATCH v7 4/5] dmaengine: dw-edma: Add HDMA DebugFS support
Quoted 110 lines · Serge Semin
Quoted 108 lines · Cai Huoqing
From: Cai huoqing <[email protected]>
Add HDMA DebugFS support to show register information
Signed-off-by Cai huoqing <[email protected]>---
v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5].
v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 3 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 2 + drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 +++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 +++ 4 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.hdrivers/dma/dw-edma/Makefile +2
-1@@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DW_EDMA) += dw-edma.o -dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o +dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o \ + dw-hdma-v0-debugfs.o dw-edma-objs := dw-edma-core.o \ dw-edma-v0-core.o \ dw-hdma-v0-core.o $(dw-edma-y)drivers/dma/dw-edma/dw-hdma-v0-core.c +2
-0@@ -11,6 +11,7 @@#include "dw-edma-core.h" #include "dw-hdma-v0-core.h" #include "dw-hdma-v0-regs.h" +#include "dw-hdma-v0-debugfs.h" enum dw_hdma_control {DW_HDMA_V0_CB =BIT (0 ),@@ -257,6 +258,7 @@ static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan)/* HDMA debugfs callbacks */ static void dw_hdma_v0_core_debugfs_on (struct dw_edma *dw) { +dw_hdma_v0_debugfs_on (dw); }static const struct dw_edma_core_ops dw_hdma_v0_core = {drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +49
-0@@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/bitfield.h> + +#include "dw-hdma-v0-debugfs.h" +#include "dw-hdma-v0-regs.h" +#include "dw-edma-core.h" + +#define REGS_ADDR (dw, name) \ + ({ \ + struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \ + \ + (void __iomem *)&__regs->name; \ + }) + +#define REGS_CH_ADDR (dw, name, _dir, _ch) \ + ({ \ + struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ + \ + if (_dir == EDMA_DIR_READ) \ + __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \ + else \ + __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \ + \ + (void __iomem *)&__ch_regs->name; \ + }) + +#define CTX_REGISTER (dw, name, dir, ch) \ + { dw, #name, REGS_CH_ADDR(dw, name, dir, ch), dir, ch } + +#define REGISTER (dw, name) \ + { dw, #name, REGS_ADDR(dw, name) } + +#define WRITE_STR "write" +#define READ_STR "read" +#define CHANNEL_STR "channel" +#define REGISTERS_STR "registers" + +struct dw_hdma_debugfs_entry { +struct dw_edma *dw; +const char *name; +void __iomem *reg;
Quoted 5 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c line 51
Quoted 2 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +2
-0+enum dw_edma_dir dir; +u16 ch;Fields above seems like unused. What about dropping them?
* Note theCTX_REGISTER()initializer will need to be fixed too.
Do you mean that,
CTX_REGISTER() like this
+#define CTX_REGISTER(dw, name, dir, ch) \
+ {#name, REGS_CH_ADDR(dw, name, dir, ch)}
dw_hdma_debug_debugfs_entry will be changed to
+struct dw_hdma_debugfs_entry {
+ const char *name;
+ void __iomem *reg;
+};
right?
Thanks,
-Cai
Quoted 166 lines
BTW it doesn't seem like HDMA will ever need the fields above, does it? In case of DW eDMA they were necessary to perform the viewport-based access of the CSR. AFAICS HDMA has always unrolled CSRs mapping. Am I right?
Other than that looks good.
-Serge(y)
Quoted 156 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +125
-0+}; + +static int dw_hdma_debugfs_u32_get (void *data,u64 *val) +{ +struct dw_hdma_debugfs_entry *entry = data; +void __iomem *reg = entry->reg; + + *val =readl (reg); + +return 0 ; +} +DEFINE_DEBUGFS_ATTRIBUTE (fops_x32, dw_hdma_debugfs_u32_get,NULL ,"0x%08llx\n" ); + +static void dw_hdma_debugfs_create_x32 (struct dw_edma *dw, +const struct dw_hdma_debugfs_entry ini[], +int nr_entries,struct dentry *dent) +{ +struct dw_hdma_debugfs_entry *entries; +int i; + + entries =devm_kcalloc (dw->chip->dev, nr_entries,sizeof (*entries), +GFP_KERNEL ); +if (!entries) +return ; + +for (i =0 ; i < nr_entries; i++) { + entries[i] = ini[i]; + +debugfs_create_file_unsafe (entries[i].name,0444 , dent, + &entries[i], &fops_x32); + } +} + +static void dw_hdma_debugfs_regs_ch (struct dw_edma *dw,enum dw_edma_dir dir, +u16 ch,struct dentry *dent) +{ +const struct dw_hdma_debugfs_entry debugfs_regs[] = { +CTX_REGISTER (dw, ch_en, dir, ch), +CTX_REGISTER (dw, doorbell, dir, ch), +CTX_REGISTER (dw, prefetch, dir, ch), +CTX_REGISTER (dw, handshake, dir, ch), +CTX_REGISTER (dw, llp.lsb, dir, ch), +CTX_REGISTER (dw, llp.msb, dir, ch), +CTX_REGISTER (dw, cycle_sync, dir, ch), +CTX_REGISTER (dw, transfer_size, dir, ch), +CTX_REGISTER (dw, sar.lsb, dir, ch), +CTX_REGISTER (dw, sar.msb, dir, ch), +CTX_REGISTER (dw, dar.lsb, dir, ch), +CTX_REGISTER (dw, dar.msb, dir, ch), +CTX_REGISTER (dw, watermark_en, dir, ch), +CTX_REGISTER (dw, control1, dir, ch), +CTX_REGISTER (dw, func_num, dir, ch), +CTX_REGISTER (dw, qos, dir, ch), +CTX_REGISTER (dw, ch_stat, dir, ch), +CTX_REGISTER (dw, int_stat, dir, ch), +CTX_REGISTER (dw, int_setup, dir, ch), +CTX_REGISTER (dw, int_clear, dir, ch), +CTX_REGISTER (dw, msi_stop.lsb, dir, ch), +CTX_REGISTER (dw, msi_stop.msb, dir, ch), +CTX_REGISTER (dw, msi_watermark.lsb, dir, ch), +CTX_REGISTER (dw, msi_watermark.msb, dir, ch), +CTX_REGISTER (dw, msi_abort.lsb, dir, ch), +CTX_REGISTER (dw, msi_abort.msb, dir, ch), +CTX_REGISTER (dw, msi_msgdata, dir, ch), + }; +int nr_entries =ARRAY_SIZE (debugfs_regs); + +dw_hdma_debugfs_create_x32 (dw, debugfs_regs, nr_entries, dent); +} + +static void dw_hdma_debugfs_regs_wr (struct dw_edma *dw,struct dentry *dent) +{ +struct dentry *regs_dent, *ch_dent; +char name[16 ]; +int i; + + regs_dent =debugfs_create_dir (WRITE_STR , dent); + +for (i =0 ; i < dw->wr_ch_cnt; i++) { +snprintf (name,sizeof (name),"%s:%d" ,CHANNEL_STR , i); + + ch_dent =debugfs_create_dir (name, regs_dent); + +dw_hdma_debugfs_regs_ch (dw,EDMA_DIR_WRITE , i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs_rd (struct dw_edma *dw,struct dentry *dent) +{ +struct dentry *regs_dent, *ch_dent; +char name[16 ]; +int i; + + regs_dent =debugfs_create_dir (READ_STR , dent); + +for (i =0 ; i < dw->rd_ch_cnt; i++) { +snprintf (name,sizeof (name),"%s:%d" ,CHANNEL_STR , i); + + ch_dent =debugfs_create_dir (name, regs_dent); + +dw_hdma_debugfs_regs_ch (dw,EDMA_DIR_READ , i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs (struct dw_edma *dw) +{ +struct dentry *regs_dent; + + regs_dent =debugfs_create_dir (REGISTERS_STR , dw->dma.dbg_dev_root); + +dw_hdma_debugfs_regs_wr (dw, regs_dent); +dw_hdma_debugfs_regs_rd (dw, regs_dent); +} + +void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +if (!debugfs_initialized ()) +return ; + +debugfs_create_u32 ("mf" ,0444 , dw->dma.dbg_dev_root, &dw->chip->mf); +debugfs_create_u16 ("wr_ch_cnt" ,0444 , dw->dma.dbg_dev_root, &dw->wr_ch_cnt); +debugfs_create_u16 ("rd_ch_cnt" ,0444 , dw->dma.dbg_dev_root, &dw->rd_ch_cnt); + +dw_hdma_debugfs_regs (dw); +}drivers/dma/dw-edma/dw-hdma-v0-debugfs.h new file +22
-0@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_DEBUG_FS_H +#define _DW_HDMA_V0_DEBUG_FS_H + +#include <linux/dma/edma.h> + +#ifdef CONFIG_DEBUG_FS +void dw_hdma_v0_debugfs_on (struct dw_edma *dw); +#else +static inline void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* _DW_HDMA_V0_DEBUG_FS_H */ Signature · 1 line
2.34.1
Re: [PATCH v7 4/5] dmaengine: dw-edma: Add HDMA DebugFS support
Quoted 132 lines · Cai Huoqing
Quoted 110 lines · Serge Semin
Quoted 108 lines · Cai Huoqing
From: Cai huoqing <[email protected]>
Add HDMA DebugFS support to show register information
Signed-off-by Cai huoqing <[email protected]>---
v6->v7:
1.Move the change of register file from patch[4/5] to patch[3/5].
v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 3 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 2 + drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 +++++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 +++ 4 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.hdrivers/dma/dw-edma/Makefile +2
-1@@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DW_EDMA) += dw-edma.o -dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o +dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o \ + dw-hdma-v0-debugfs.o dw-edma-objs := dw-edma-core.o \ dw-edma-v0-core.o \ dw-hdma-v0-core.o $(dw-edma-y)drivers/dma/dw-edma/dw-hdma-v0-core.c +2
-0@@ -11,6 +11,7 @@#include "dw-edma-core.h" #include "dw-hdma-v0-core.h" #include "dw-hdma-v0-regs.h" +#include "dw-hdma-v0-debugfs.h" enum dw_hdma_control {DW_HDMA_V0_CB =BIT (0 ),@@ -257,6 +258,7 @@ static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan)/* HDMA debugfs callbacks */ static void dw_hdma_v0_core_debugfs_on (struct dw_edma *dw) { +dw_hdma_v0_debugfs_on (dw); }static const struct dw_edma_core_ops dw_hdma_v0_core = {drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +49
-0@@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#include <linux/debugfs.h> +#include <linux/bitfield.h> + +#include "dw-hdma-v0-debugfs.h" +#include "dw-hdma-v0-regs.h" +#include "dw-edma-core.h" + +#define REGS_ADDR (dw, name) \ + ({ \ + struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \ + \ + (void __iomem *)&__regs->name; \ + }) + +#define REGS_CH_ADDR (dw, name, _dir, _ch) \ + ({ \ + struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ + \ + if (_dir == EDMA_DIR_READ) \ + __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \ + else \ + __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \ + \ + (void __iomem *)&__ch_regs->name; \ + }) + +#define CTX_REGISTER (dw, name, dir, ch) \ + { dw, #name, REGS_CH_ADDR(dw, name, dir, ch), dir, ch } + +#define REGISTER (dw, name) \ + { dw, #name, REGS_ADDR(dw, name) } + +#define WRITE_STR "write" +#define READ_STR "read" +#define CHANNEL_STR "channel" +#define REGISTERS_STR "registers" + +struct dw_hdma_debugfs_entry { +struct dw_edma *dw; +const char *name; +void __iomem *reg;Quoted 5 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c line 51
Quoted 2 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +2
-0+enum dw_edma_dir dir; +u16 ch;Fields above seems like unused. What about dropping them?
* Note theCTX_REGISTER()initializer will need to be fixed too.Do you mean that,
CTX_REGISTER()like this(quoted diff) +2
-0+#define CTX_REGISTER(dw, name, dir, ch) \ + {#name, REGS_CH_ADDR(dw, name, dir, ch)}
dw_hdma_debug_debugfs_entrywill be changed todrivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +4
-0+struct dw_hdma_debugfs_entry { +const char *name; +void __iomem *reg; +};
Quoted 1 line
right?
Yes.
-Serge(y)
Quoted 169 lines
Thanks,
-CaiQuoted 166 lines
BTW it doesn't seem like HDMA will ever need the fields above, does it? In case of DW eDMA they were necessary to perform the viewport-based access of the CSR. AFAICS HDMA has always unrolled CSRs mapping. Am I right?
Other than that looks good.
-Serge(y)
Quoted 156 lines
drivers/dma/dw-edma/dw-hdma-v0-debugfs.c new file +125
-0+}; + +static int dw_hdma_debugfs_u32_get (void *data,u64 *val) +{ +struct dw_hdma_debugfs_entry *entry = data; +void __iomem *reg = entry->reg; + + *val =readl (reg); + +return 0 ; +} +DEFINE_DEBUGFS_ATTRIBUTE (fops_x32, dw_hdma_debugfs_u32_get,NULL ,"0x%08llx\n" ); + +static void dw_hdma_debugfs_create_x32 (struct dw_edma *dw, +const struct dw_hdma_debugfs_entry ini[], +int nr_entries,struct dentry *dent) +{ +struct dw_hdma_debugfs_entry *entries; +int i; + + entries =devm_kcalloc (dw->chip->dev, nr_entries,sizeof (*entries), +GFP_KERNEL ); +if (!entries) +return ; + +for (i =0 ; i < nr_entries; i++) { + entries[i] = ini[i]; + +debugfs_create_file_unsafe (entries[i].name,0444 , dent, + &entries[i], &fops_x32); + } +} + +static void dw_hdma_debugfs_regs_ch (struct dw_edma *dw,enum dw_edma_dir dir, +u16 ch,struct dentry *dent) +{ +const struct dw_hdma_debugfs_entry debugfs_regs[] = { +CTX_REGISTER (dw, ch_en, dir, ch), +CTX_REGISTER (dw, doorbell, dir, ch), +CTX_REGISTER (dw, prefetch, dir, ch), +CTX_REGISTER (dw, handshake, dir, ch), +CTX_REGISTER (dw, llp.lsb, dir, ch), +CTX_REGISTER (dw, llp.msb, dir, ch), +CTX_REGISTER (dw, cycle_sync, dir, ch), +CTX_REGISTER (dw, transfer_size, dir, ch), +CTX_REGISTER (dw, sar.lsb, dir, ch), +CTX_REGISTER (dw, sar.msb, dir, ch), +CTX_REGISTER (dw, dar.lsb, dir, ch), +CTX_REGISTER (dw, dar.msb, dir, ch), +CTX_REGISTER (dw, watermark_en, dir, ch), +CTX_REGISTER (dw, control1, dir, ch), +CTX_REGISTER (dw, func_num, dir, ch), +CTX_REGISTER (dw, qos, dir, ch), +CTX_REGISTER (dw, ch_stat, dir, ch), +CTX_REGISTER (dw, int_stat, dir, ch), +CTX_REGISTER (dw, int_setup, dir, ch), +CTX_REGISTER (dw, int_clear, dir, ch), +CTX_REGISTER (dw, msi_stop.lsb, dir, ch), +CTX_REGISTER (dw, msi_stop.msb, dir, ch), +CTX_REGISTER (dw, msi_watermark.lsb, dir, ch), +CTX_REGISTER (dw, msi_watermark.msb, dir, ch), +CTX_REGISTER (dw, msi_abort.lsb, dir, ch), +CTX_REGISTER (dw, msi_abort.msb, dir, ch), +CTX_REGISTER (dw, msi_msgdata, dir, ch), + }; +int nr_entries =ARRAY_SIZE (debugfs_regs); + +dw_hdma_debugfs_create_x32 (dw, debugfs_regs, nr_entries, dent); +} + +static void dw_hdma_debugfs_regs_wr (struct dw_edma *dw,struct dentry *dent) +{ +struct dentry *regs_dent, *ch_dent; +char name[16 ]; +int i; + + regs_dent =debugfs_create_dir (WRITE_STR , dent); + +for (i =0 ; i < dw->wr_ch_cnt; i++) { +snprintf (name,sizeof (name),"%s:%d" ,CHANNEL_STR , i); + + ch_dent =debugfs_create_dir (name, regs_dent); + +dw_hdma_debugfs_regs_ch (dw,EDMA_DIR_WRITE , i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs_rd (struct dw_edma *dw,struct dentry *dent) +{ +struct dentry *regs_dent, *ch_dent; +char name[16 ]; +int i; + + regs_dent =debugfs_create_dir (READ_STR , dent); + +for (i =0 ; i < dw->rd_ch_cnt; i++) { +snprintf (name,sizeof (name),"%s:%d" ,CHANNEL_STR , i); + + ch_dent =debugfs_create_dir (name, regs_dent); + +dw_hdma_debugfs_regs_ch (dw,EDMA_DIR_READ , i, ch_dent); + } +} + +static void dw_hdma_debugfs_regs (struct dw_edma *dw) +{ +struct dentry *regs_dent; + + regs_dent =debugfs_create_dir (REGISTERS_STR , dw->dma.dbg_dev_root); + +dw_hdma_debugfs_regs_wr (dw, regs_dent); +dw_hdma_debugfs_regs_rd (dw, regs_dent); +} + +void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +if (!debugfs_initialized ()) +return ; + +debugfs_create_u32 ("mf" ,0444 , dw->dma.dbg_dev_root, &dw->chip->mf); +debugfs_create_u16 ("wr_ch_cnt" ,0444 , dw->dma.dbg_dev_root, &dw->wr_ch_cnt); +debugfs_create_u16 ("rd_ch_cnt" ,0444 , dw->dma.dbg_dev_root, &dw->rd_ch_cnt); + +dw_hdma_debugfs_regs (dw); +}drivers/dma/dw-edma/dw-hdma-v0-debugfs.h new file +22
-0@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Copyright (c) 2023 Cai Huoqing +* Synopsys DesignWare HDMA v0 debugfs +* +* Author: Cai Huoqing <[email protected]> +*/ + +#ifndef _DW_HDMA_V0_DEBUG_FS_H +#define _DW_HDMA_V0_DEBUG_FS_H + +#include <linux/dma/edma.h> + +#ifdef CONFIG_DEBUG_FS +void dw_hdma_v0_debugfs_on (struct dw_edma *dw); +#else +static inline void dw_hdma_v0_debugfs_on (struct dw_edma *dw) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* _DW_HDMA_V0_DEBUG_FS_H */ Signature · 1 line
2.34.1
PATCH v7 5/5 dmaengine: dw-edma: Optimization in dw_edma_v0_core_handle_int
In reply to Cai HuoqingOptimization in dw_edma_v0_core_handle_int, remove some unnecessary wrapper function.
---
v6 link:
https://lore.kernel.org/lkml/[email protected]/
drivers/dma/dw-edma/dw-edma-v0-core.c | 38 +++++---------------------- 1 file changed, 6 insertions(+), 32 deletions(-)
drivers/dma/dw-edma/dw-edma-v0-core.c +6 -32
@@ -258,34 +258,6 @@ static enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)return DMA_ERROR ; } -static void dw_edma_v0_core_clear_done_int (struct dw_edma_chan *chan) -{ -struct dw_edma *dw = chan->dw; - -SET_RW_32 (dw, chan->dir, int_clear, -FIELD_PREP (EDMA_V0_DONE_INT_MASK ,BIT (chan->id))); -} - -static void dw_edma_v0_core_clear_abort_int (struct dw_edma_chan *chan) -{ -struct dw_edma *dw = chan->dw; - -SET_RW_32 (dw, chan->dir, int_clear, -FIELD_PREP (EDMA_V0_ABORT_INT_MASK ,BIT (chan->id))); -} - -static u32 dw_edma_v0_core_status_done_int (struct dw_edma *dw,enum dw_edma_dir dir) -{ -return FIELD_GET (EDMA_V0_DONE_INT_MASK , -GET_RW_32 (dw, dir, int_status)); -} - -static u32 dw_edma_v0_core_status_abort_int (struct dw_edma *dw,enum dw_edma_dir dir) -{ -return FIELD_GET (EDMA_V0_ABORT_INT_MASK , -GET_RW_32 (dw, dir, int_status)); -} -static irqreturn_t dw_edma_v0_core_handle_int (struct dw_edma_irq *dw_irq,enum dw_edma_dir dir,dw_edma_handler_t done,dw_edma_handler_t abort)
@@ -307,23 +279,25 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, mask = dw_irq->rd_mask; } - val =dw_edma_v0_core_status_done_int (dw, dir); + val =FIELD_GET (EDMA_V0_DONE_INT_MASK ,GET_RW_32 (dw, dir, int_status)); val &= mask;for_each_set_bit (pos, &val, total) { chan = &dw->chan[pos + off]; -dw_edma_v0_core_clear_done_int (chan); +SET_RW_32 (dw, chan->dir, int_clear, +FIELD_PREP (EDMA_V0_DONE_INT_MASK ,BIT (chan->id)));done (chan); ret =IRQ_HANDLED ; } - val =dw_edma_v0_core_status_abort_int (dw, dir); + val =FIELD_GET (EDMA_V0_ABORT_INT_MASK ,GET_RW_32 (dw, dir, int_status)); val &= mask;for_each_set_bit (pos, &val, total) { chan = &dw->chan[pos + off]; -dw_edma_v0_core_clear_abort_int (chan); +SET_RW_32 (dw, chan->dir, int_clear, +FIELD_PREP (EDMA_V0_ABORT_INT_MASK ,BIT (chan->id)));abort (chan); ret =IRQ_HANDLED ;
Signature · 1 line
2.34.1
Hi Cai
Quoted 15 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA,
so this patch add support for HDMA NATIVE mode.HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when youhave multiple write channels.
Quoted 4 lines
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
It seems like we are getting towards the series finalization. I'll test it out on my HW after v8 is submitted. Meanwhile could you please clarify whether you have a real device with DW HDMA engine on board? You keep submitting the DW eDMA driver core update, but there is no glue-driver or low-level device driver patch for a real device which would set the EDMA_MF_HDMA_NATIVE mapping.
-Serge(y)
Quoted 48 lines
Cai Huoqing (2):
dmaengine: dw-edma: Add support for native HDMA
dmaengine: dw-edma: Optimization indw_edma_v0_core_handle_intCai huoqing (3):
dmaengine: dw-edma: Renamedw_edma_core_opsstructure to
dw_edma_plat_ops
dmaengine: dw-edma: Create a newdw_edma_core_opsstructure to
abstract controller operation
dmaengine: dw-edma: Add HDMA DebugFS support
v6->v7:
[1/5]
1.Update the commit log.
[2/5]
2.Revertdw_edma_core_handle_intback todw-edma-core.h. 3.Fix code style.
[3/5]
4.Move the change of register file from patch[4/5] to patch[3/5]. 5.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 8 +- drivers/dma/dw-edma/dw-edma-core.c | 86 ++---- drivers/dma/dw-edma/dw-edma-core.h | 58 ++++ drivers/dma/dw-edma/dw-edma-pcie.c | 4 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 91 ++++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 277 +++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 ++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 +++++++++ drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 7 +- 13 files changed, 785 insertions(+), 107 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hSignature · 1 line
2.34.1
Quoted 18 lines · Serge Semin
Hi Cai
Quoted 15 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA,
so this patch add support for HDMA NATIVE mode.HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when youhave multiple write channels.
Quoted 8 lines
Quoted 4 lines
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
It seems like we are getting towards the series finalization. I'll test it out on my HW after v8 is submitted. Meanwhile could you please clarify whether you have a real device with DW HDMA engine on board?
Our hardware is an AI Accelerartor(PCIE Card).
The device pci.ids is 1d22:3864
in https://github.com/pciutils/pciids/blob/master/pci.ids
line 24737,
"1d22 Baidu Technology
3684 Kunlun AI Accelerator
3685 Kunlun2 AI Accelerator [VF]"
And our device driver is not ready to upstream(will cost serveral
months to port DRM etc.),
but I have taken this DW eDMA core into our driver test.
Thanks
Cai-
Quoted 54 lines
You keep submitting the DW eDMA driver core update, but there is no glue-driver or low-level device driver patch for a real device which would set the
EDMA_MF_HDMA_NATIVEmapping.-Serge(y)
Quoted 48 lines
Cai Huoqing (2):
dmaengine: dw-edma: Add support for native HDMA
dmaengine: dw-edma: Optimization indw_edma_v0_core_handle_intCai huoqing (3):
dmaengine: dw-edma: Renamedw_edma_core_opsstructure to
dw_edma_plat_ops
dmaengine: dw-edma: Create a newdw_edma_core_opsstructure to
abstract controller operation
dmaengine: dw-edma: Add HDMA DebugFS support
v6->v7:
[1/5]
1.Update the commit log.
[2/5]
2.Revertdw_edma_core_handle_intback todw-edma-core.h. 3.Fix code style.
[3/5]
4.Move the change of register file from patch[4/5] to patch[3/5]. 5.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 8 +- drivers/dma/dw-edma/dw-edma-core.c | 86 ++---- drivers/dma/dw-edma/dw-edma-core.h | 58 ++++ drivers/dma/dw-edma/dw-edma-pcie.c | 4 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 91 ++++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 277 +++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 ++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 +++++++++ drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 7 +- 13 files changed, 785 insertions(+), 107 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hSignature · 1 line
2.34.1
Quoted 35 lines · Cai Huoqing
Quoted 18 lines · Serge Semin
Hi Cai
Quoted 15 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA,
so this patch add support for HDMA NATIVE mode.HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when youhave multiple write channels.
Quoted 8 lines
Quoted 4 lines
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
It seems like we are getting towards the series finalization. I'll test it out on my HW after v8 is submitted. Meanwhile could you please clarify whether you have a real device with DW HDMA engine on board?
Our hardware is an AI Accelerartor(PCIE Card).
The device pci.ids is 1d22:3864
in https://github.com/pciutils/pciids/blob/master/pci.ids
line 24737,
Quoted 7 lines
"1d22 Baidu Technology
3684 Kunlun AI Accelerator
3685 Kunlun2 AI Accelerator [VF]"And our device driver is not ready to upstream(will cost serveral
months to port DRM etc.),
Ok. Thanks for clarification. Could you please add me to the Cc-list of the AI-accelerator patch when it's ready to be submitted for review. I am not that familiar with the DRM-part, but would like to have a look at the DMA-related code.
-Serge(y)
Quoted 60 lines
but I have taken this DW eDMA core into our driver test.
Thanks
Cai-Quoted 54 lines
You keep submitting the DW eDMA driver core update, but there is no glue-driver or low-level device driver patch for a real device which would set the
EDMA_MF_HDMA_NATIVEmapping.-Serge(y)
Quoted 48 lines
Cai Huoqing (2):
dmaengine: dw-edma: Add support for native HDMA
dmaengine: dw-edma: Optimization indw_edma_v0_core_handle_intCai huoqing (3):
dmaengine: dw-edma: Renamedw_edma_core_opsstructure to
dw_edma_plat_ops
dmaengine: dw-edma: Create a newdw_edma_core_opsstructure to
abstract controller operation
dmaengine: dw-edma: Add HDMA DebugFS support
v6->v7:
[1/5]
1.Update the commit log.
[2/5]
2.Revertdw_edma_core_handle_intback todw-edma-core.h. 3.Fix code style.
[3/5]
4.Move the change of register file from patch[4/5] to patch[3/5]. 5.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 8 +- drivers/dma/dw-edma/dw-edma-core.c | 86 ++---- drivers/dma/dw-edma/dw-edma-core.h | 58 ++++ drivers/dma/dw-edma/dw-edma-pcie.c | 4 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 91 ++++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 277 +++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 ++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 +++++++++ drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 7 +- 13 files changed, 785 insertions(+), 107 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hSignature · 1 line
2.34.1
Quoted 40 lines · Serge Semin
Quoted 39 lines · Cai Huoqing
Quoted 18 lines · Serge Semin
Hi Cai
Quoted 15 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA,
so this patch add support for HDMA NATIVE mode.HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when youhave multiple write channels.
Quoted 8 lines
Quoted 4 lines
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
It seems like we are getting towards the series finalization. I'll test it out on my HW after v8 is submitted. Meanwhile could you please clarify whether you have a real device with DW HDMA engine on board?
Our hardware is an AI Accelerartor(PCIE Card).
The device pci.ids is 1d22:3864
in https://github.com/pciutils/pciids/blob/master/pci.ids
line 24737,"1d22 Baidu Technology
3684 Kunlun AI Accelerator
3685 Kunlun2 AI Accelerator [VF]"
Quoted 8 lines
Quoted 3 lines
And our device driver is not ready to upstream(will cost serveral
months to port DRM etc.),
Ok. Thanks for clarification. Could you please add me to the Cc-list of the AI-accelerator patch when it's ready to be submitted for review. I am not that familiar with the DRM-part, but would like to have a look at the DMA-related code.
Sure, I'll Cc you if I send the patches.
By the way, Why use native hdma:
Our device v1 also use dw-edma. But we find that navtive HDMA work better
in SRIOV on, channel CSR can be map to every VF instead of some global
regiter must in PF. So v2 use native hdma.
Thanks,
-Cai
Quoted 63 lines
-Serge(y)
Quoted 60 lines
but I have taken this DW eDMA core into our driver test.
Thanks
Cai-Quoted 54 lines
You keep submitting the DW eDMA driver core update, but there is no glue-driver or low-level device driver patch for a real device which would set the
EDMA_MF_HDMA_NATIVEmapping.-Serge(y)
Quoted 48 lines
Cai Huoqing (2):
dmaengine: dw-edma: Add support for native HDMA
dmaengine: dw-edma: Optimization indw_edma_v0_core_handle_intCai huoqing (3):
dmaengine: dw-edma: Renamedw_edma_core_opsstructure to
dw_edma_plat_ops
dmaengine: dw-edma: Create a newdw_edma_core_opsstructure to
abstract controller operation
dmaengine: dw-edma: Add HDMA DebugFS support
v6->v7:
[1/5]
1.Update the commit log.
[2/5]
2.Revertdw_edma_core_handle_intback todw-edma-core.h. 3.Fix code style.
[3/5]
4.Move the change of register file from patch[4/5] to patch[3/5]. 5.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 8 +- drivers/dma/dw-edma/dw-edma-core.c | 86 ++---- drivers/dma/dw-edma/dw-edma-core.h | 58 ++++ drivers/dma/dw-edma/dw-edma-pcie.c | 4 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 91 ++++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 277 +++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 ++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 +++++++++ drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 7 +- 13 files changed, 785 insertions(+), 107 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hSignature · 1 line
2.34.1
Quoted 43 lines · Cai Huoqing
Quoted 42 lines · Serge Semin
Quoted 41 lines · Cai Huoqing
Quoted 18 lines · Serge Semin
Hi Cai
Quoted 15 lines · Cai Huoqing
Add support for HDMA NATIVE, as long the IP design has set the compatible register map parameter-HDMA_NATIVE, which allows compatibility for native HDMA register configuration.
The HDMA Hyper-DMA IP is an enhancement of the eDMA embedded-DMA IP. And the native HDMA registers are different from eDMA,
so this patch add support for HDMA NATIVE mode.HDMA write and read channels operate independently to maximize the performance of the HDMA read and write data transfer over the link When you configure the HDMA with multiple read channels, then it uses a round robin (RR) arbitration scheme to select the next read channel to be serviced.The same applies when youhave multiple write channels.
Quoted 8 lines
Quoted 4 lines
The native HDMA driver also supports a maximum of 16 independent channels (8 write + 8 read), which can run simultaneously. Both SAR (Source Address Register) and DAR (Destination Address Register) are aligned to byte.
It seems like we are getting towards the series finalization. I'll test it out on my HW after v8 is submitted. Meanwhile could you please clarify whether you have a real device with DW HDMA engine on board?
Our hardware is an AI Accelerartor(PCIE Card).
The device pci.ids is 1d22:3864
in https://github.com/pciutils/pciids/blob/master/pci.ids
line 24737,"1d22 Baidu Technology
3684 Kunlun AI Accelerator
3685 Kunlun2 AI Accelerator [VF]"And our device driver is not ready to upstream(will cost serveral
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
months to port DRM etc.),
Ok. Thanks for clarification. Could you please add me to the Cc-list of the AI-accelerator patch when it's ready to be submitted for review. I am not that familiar with the DRM-part, but would like to have a look at the DMA-related code.
Sure, I'll Cc you if I send the patches.
Great! Thanks in advance.
Quoted 8 lines
By the way, Why use native hdma:
Our device v1 also use dw-edma. But we find that navtive HDMA work better
in SRIOV on, channel CSR can be map to every VF instead of some global
regiter must in PF. So v2 use native hdma.
Good to know. Thanks.
-Serge(y)
Quoted 67 lines
Thanks,
-CaiQuoted 63 lines
-Serge(y)
Quoted 60 lines
but I have taken this DW eDMA core into our driver test.
Thanks
Cai-Quoted 54 lines
You keep submitting the DW eDMA driver core update, but there is no glue-driver or low-level device driver patch for a real device which would set the
EDMA_MF_HDMA_NATIVEmapping.-Serge(y)
Quoted 48 lines
Cai Huoqing (2):
dmaengine: dw-edma: Add support for native HDMA
dmaengine: dw-edma: Optimization indw_edma_v0_core_handle_intCai huoqing (3):
dmaengine: dw-edma: Renamedw_edma_core_opsstructure to
dw_edma_plat_ops
dmaengine: dw-edma: Create a newdw_edma_core_opsstructure to
abstract controller operation
dmaengine: dw-edma: Add HDMA DebugFS support
v6->v7:
[1/5]
1.Update the commit log.
[2/5]
2.Revertdw_edma_core_handle_intback todw-edma-core.h. 3.Fix code style.
[3/5]
4.Move the change of register file from patch[4/5] to patch[3/5]. 5.Fix code style.v6 link:
https://lore.kernel.org/lkml/[email protected]/drivers/dma/dw-edma/Makefile | 8 +- drivers/dma/dw-edma/dw-edma-core.c | 86 ++---- drivers/dma/dw-edma/dw-edma-core.h | 58 ++++ drivers/dma/dw-edma/dw-edma-pcie.c | 4 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 91 ++++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 14 +- drivers/dma/dw-edma/dw-hdma-v0-core.c | 277 +++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.h | 17 ++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 176 ++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-debugfs.h | 22 ++ drivers/dma/dw-edma/dw-hdma-v0-regs.h | 130 +++++++++ drivers/pci/controller/dwc/pcie-designware.c | 2 +- include/linux/dma/edma.h | 7 +- 13 files changed, 785 insertions(+), 107 deletions(-) create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-core.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.c create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-debugfs.h create mode 100644 drivers/dma/dw-edma/dw-hdma-v0-regs.hSignature · 1 line
2.34.1