VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
author: andy.hu <andy.hu@starfivetech.com> 2023-08-30 06:55:45 +0000 committer: andy.hu <andy.hu@starfivetech.com> 2023-08-30 06:55:45 +0000 commit: ed81ac47b0a4ca45533cfb3cc2ce7a67cce6708a parent: 33ffd33d08f5cb6dbf3598634f40735c21035c8b
Commit Summary:
Merge branch 'CR_5740_DMA_unable_transfer_270KB_data_walker.chen' into 'jh7110-5.15.y-devel'
Diffstat:
5 files changed, 229 insertions, 337 deletions
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
old mode 100755
new mode 100644
index 8b0e8d1bb6c4..527b9ab2d8b7
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -628,7 +628,7 @@
 		};
 
 		dma: dma-controller@16050000 {
-			compatible = "starfive,jh7110-dma", "snps,axi-dma-1.01a";
+			compatible = "starfive,jh7110-axi-dma";
 			dma-coherent;
 			reg = <0x0 0x16050000 0x0 0x10000>;
 			clocks = <&clkgen JH7110_DMA1P_CLK_AXI>,
@@ -638,13 +638,11 @@
 			resets = <&rstgen RSTN_U0_DW_DMA1P_AXI>,
 				 <&rstgen RSTN_U0_DW_DMA1P_AHB>,
 				 <&rstgen RSTN_U0_NOC_BUS_STG_AXI_N>;
-			reset-names = "rst_axi", "rst_ahb", "rst_stg";
 			interrupts = <73>;
-			#dma-cells = <2>;
+			#dma-cells = <1>;
 			dma-channels = <4>;
 			snps,dma-masters = <1>;
 			snps,data-width = <3>;
-			snps,num-hs-if = <56>;
 			snps,block-size = <65536 65536 65536 65536>;
 			snps,priority = <0 1 2 3>;
 			snps,axi-max-burst-len = <15>;
@@ -1203,7 +1201,7 @@
 				 <&rstgen RSTN_U0_TDM16SLOT_APB>,
 				 <&rstgen RSTN_U0_TDM16SLOT_TDM>;
 			reset-names = "tdm_ahb", "tdm_apb", "tdm_rst";
-			dmas = <&dma 20 1>, <&dma 21 1>;
+			dmas = <&dma 20>, <&dma 21>;
 			dma-names = "rx","tx";
 			#sound-dai-cells = <0>;
 			status = "disabled";
@@ -1237,7 +1235,7 @@
 			clock-names = "apb0", "pwmdac-apb", "pwmdac-core";
 			resets = <&rstgen RSTN_U0_PWMDAC_APB>;
 			reset-names = "rst-apb";
-			dmas = <&dma 22 1>;
+			dmas = <&dma 22>;
 			dma-names = "tx";
 			#sound-dai-cells = <0>;
 			status = "disabled";
@@ -1248,7 +1246,7 @@
 			reg = <0x0 0x100c0000 0x0 0x1000>;
 			interrupt-names = "tx";
 			#sound-dai-cells = <0>;
-			dmas = <&dma 28 1>;
+			dmas = <&dma 28>;
 			dma-names = "rx";
 			status = "disabled";
 		};
@@ -1288,7 +1286,7 @@
 			resets = <&rstgen RSTN_U0_I2SRX_3CH_APB>,
 				 <&rstgen RSTN_U0_I2SRX_3CH_BCLK>;
 			reset-names = "rst_apb_rx", "rst_bclk_rx";
-			dmas = <&dma 24 1>;
+			dmas = <&dma 24>;
 			dma-names = "rx";
 			starfive,sys-syscon = <&sys_syscon 0x18 0x34>;
 			#sound-dai-cells = <0>;
@@ -1318,7 +1316,7 @@
 				      "bclk-ext", "lrck-ext";
 			resets = <&rstgen RSTN_U0_I2SRX_3CH_APB>,
 				 <&rstgen RSTN_U0_I2SRX_3CH_BCLK>;
-			dmas = <&dma 24 1>;
+			dmas = <&dma 24>;
 			dma-names = "rx";
 			starfive,sys-syscon = <&sys_syscon 0x18 0x34>;
 			#sound-dai-cells = <0>;
@@ -1343,7 +1341,7 @@
 			resets = <&rstgen RSTN_U0_I2STX_4CH_APB>,
 				 <&rstgen RSTN_U0_I2STX_4CH_BCLK>;
 			reset-names = "rst_apb", "rst_bclk";
-			dmas = <&dma 47 1>;
+			dmas = <&dma 47>;
 			dma-names = "tx";
 			#sound-dai-cells = <0>;
 			status = "disabled";
@@ -1372,7 +1370,7 @@
 				      "mclk_ext", "bclk_ext", "lrck_ext";
 			resets = <&rstgen RSTN_U1_I2STX_4CH_APB>,
 				 <&rstgen RSTN_U1_I2STX_4CH_BCLK>;
-			dmas = <&dma 48 1>;
+			dmas = <&dma 48>;
 			dma-names = "tx";
 			#sound-dai-cells = <0>;
 			status = "disabled";
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index a4e690ecbe1b..0d4d6130c427 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier:  GPL-2.0
+// SPDX-License-Identifier: GPL-2.0
 // (C) 2017-2018 Synopsys, Inc. (www.synopsys.com)
 
 /*
@@ -21,24 +21,23 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_dma.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/reset.h>
 
 #include "dw-axi-dmac.h"
 #include "../dmaengine.h"
 #include "../virt-dma.h"
 
-#include <soc/starfive/vic7100.h>
-
 /*
  * The set of bus widths supported by the DMA controller. DW AXI DMAC supports
  * master data bus width up to 512 bits (for both AXI master interfaces), but
- * it depends on IP block configurarion.
+ * it depends on IP block configuration.
  */
 #define AXI_DMA_BUSWIDTHS		  \
 	(DMA_SLAVE_BUSWIDTH_1_BYTE	| \
@@ -49,6 +48,10 @@
 	DMA_SLAVE_BUSWIDTH_32_BYTES	| \
 	DMA_SLAVE_BUSWIDTH_64_BYTES)
 
+#define AXI_DMA_FLAG_HAS_APB_REGS	BIT(0)
+#define AXI_DMA_FLAG_HAS_RESETS		BIT(1)
+#define AXI_DMA_FLAG_USE_CFG2		BIT(2)
+
 static inline void
 axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val)
 {
@@ -82,6 +85,36 @@ axi_chan_iowrite64(struct axi_dma_chan *chan, u32 reg, u64 val)
 	iowrite32(upper_32_bits(val), chan->chan_regs + reg + 4);
 }
 
+static inline void axi_chan_config_write(struct axi_dma_chan *chan,
+					 struct axi_dma_chan_config *config)
+{
+	u32 cfg_lo, cfg_hi;
+
+	cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS |
+		  config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
+	if (chan->chip->dw->hdata->reg_map_8_channels &&
+	    !chan->chip->dw->hdata->use_cfg2) {
+		cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS |
+			 config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS |
+			 config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS |
+			 config->src_per << CH_CFG_H_SRC_PER_POS |
+			 config->dst_per << CH_CFG_H_DST_PER_POS |
+			 config->prior << CH_CFG_H_PRIORITY_POS;
+	} else {
+		cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS |
+			  config->dst_per << CH_CFG2_L_DST_PER_POS;
+		cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS |
+			 config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS |
+			 config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS |
+			 config->prior << CH_CFG2_H_PRIORITY_POS;
+	}
+
+	cfg_hi |= CH_CFG_H_MAX_OSR_LMT << CH_CFG_H_SRC_OSR_LMT_POS |
+		  CH_CFG_H_MAX_OSR_LMT << CH_CFG_H_DST_OSR_LMT_POS;
+	axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo);
+	axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi);
+}
+
 static inline void axi_dma_disable(struct axi_dma_chip *chip)
 {
 	u32 val;
@@ -151,89 +184,54 @@ static inline u32 axi_chan_irq_read(struct axi_dma_chan *chan)
 	return axi_chan_ioread32(chan, CH_INTSTATUS);
 }
 
-static void axi_chan_set_multi_reg(struct axi_dma_chip *chip)
-{
-	struct dma_multi *multi = &chip->multi;
-
-	 /* cfg_2 Exists:  (DMAX_NUM_CHANNELS > 8 || DMAX_NUM_HS_IF > 16) */
-	if (multi->ch_cfg_2 == true) {
-		multi->cfg.ch_cfg_priority_pos = CH_CFG_H_PRIORITY_POS_2;
-		multi->cfg.ch_cfg_dst_per_pos = CH_CFG_L_DST_PER_POS_2;
-		multi->cfg.ch_cfg_src_per_pos = CH_CFG_L_SRC_PER_POS_2;
-	} else {
-		multi->cfg.ch_cfg_priority_pos = CH_CFG_H_PRIORITY_POS;
-		multi->cfg.ch_cfg_dst_per_pos = CH_CFG_H_DST_PER_POS;
-		multi->cfg.ch_cfg_src_per_pos = CH_CFG_H_SRC_PER_POS;
-	}
-
-	/* en_2 Exists: DMAX_NUM_CHANNELS > 8 */
-	if (multi->ch_enreg_2 == true) {
-		multi->en.ch_en = DMAC_CHEN_2;
-		multi->en.ch_en_shift = DMAC_CHAN_EN_SHIFT_2;
-		multi->en.ch_en_we_shift = DMAC_CHAN_EN_WE_SHIFT_2;
-
-		multi->en.ch_susp = DMAC_CHSUSP_2;
-		multi->en.ch_susp_shift = DMAC_CHAN_SUSP_SHIFT_2;
-		multi->en.ch_susp_we_shift = DMAC_CHAN_SUSP_WE_SHIFT_2;
-
-		multi->en.ch_abort = DMAC_CHABORT_2;
-		multi->en.ch_abort_shift = DMAC_CHAN_ABORT_SHIFT_2;
-		multi->en.ch_abort_we_shfit = DMAC_CHAN_ABORT_WE_SHIFT_2;
-	} else {
-		multi->en.ch_en = DMAC_CHEN;
-		multi->en.ch_en_shift = DMAC_CHAN_EN_SHIFT;
-		multi->en.ch_en_we_shift = DMAC_CHAN_EN_WE_SHIFT;
-
-		multi->en.ch_susp = DMAC_CHSUSP;
-		multi->en.ch_susp_shift = DMAC_CHAN_SUSP_SHIFT;
-		multi->en.ch_susp_we_shift = DMAC_CHAN_SUSP_WE_SHIFT;
-
-		multi->en.ch_abort = DMAC_CHABORT;
-		multi->en.ch_abort_shift = DMAC_CHAN_ABORT_SHIFT;
-		multi->en.ch_abort_we_shfit = DMAC_CHAN_ABORT_WE_SHIFT;
-	}
-}
-
 static inline void axi_chan_disable(struct axi_dma_chan *chan)
 {
-	struct dma_multi *multi = &chan->chip->multi;
 	u32 val;
 
-	val = axi_dma_ioread32(chan->chip, multi->en.ch_en);
-	val &= ~(BIT(chan->id) << multi->en.ch_en_shift);
-	val |= BIT(chan->id) << multi->en.ch_en_we_shift;
-	axi_dma_iowrite32(chan->chip, multi->en.ch_en, val);
+	val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+	val &= ~(BIT(chan->id) << DMAC_CHAN_EN_SHIFT);
+	if (chan->chip->dw->hdata->reg_map_8_channels)
+		val |=   BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+	else
+		val |=   BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+	axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
 }
 
 static inline void axi_chan_enable(struct axi_dma_chan *chan)
 {
-	struct dma_multi *multi = &chan->chip->multi;
 	u32 val;
 
-	val = axi_dma_ioread32(chan->chip, multi->en.ch_en);
-	val |= BIT(chan->id) << multi->en.ch_en_shift |
-	       BIT(chan->id) << multi->en.ch_en_we_shift;
-	axi_dma_iowrite32(chan->chip, multi->en.ch_en, val);
+	val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+	if (chan->chip->dw->hdata->reg_map_8_channels)
+		val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+			BIT(chan->id) << DMAC_CHAN_EN_WE_SHIFT;
+	else
+		val |= BIT(chan->id) << DMAC_CHAN_EN_SHIFT |
+			BIT(chan->id) << DMAC_CHAN_EN2_WE_SHIFT;
+	axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
 }
 
 static inline bool axi_chan_is_hw_enable(struct axi_dma_chan *chan)
 {
-	struct dma_multi *multi = &chan->chip->multi;
 	u32 val;
 
-	val = axi_dma_ioread32(chan->chip, multi->en.ch_en);
+	val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
 
-	return !!(val & (BIT(chan->id) << multi->en.ch_en_shift));
+	return !!(val & (BIT(chan->id) << DMAC_CHAN_EN_SHIFT));
 }
 
 static void axi_dma_hw_init(struct axi_dma_chip *chip)
 {
+	int ret;
 	u32 i;
 
 	for (i = 0; i < chip->dw->hdata->nr_channels; i++) {
 		axi_chan_irq_disable(&chip->dw->chan[i], DWAXIDMAC_IRQ_ALL);
 		axi_chan_disable(&chip->dw->chan[i]);
 	}
+	ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64));
+	if (ret)
+		dev_warn(chip->dev, "Unable to set coherent mask\n");
 }
 
 static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src,
@@ -337,12 +335,11 @@ dma_chan_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
 		len = vd_to_axi_desc(vdesc)->hw_desc[0].len;
 		completed_length = completed_blocks * len;
 		bytes = length - completed_length;
-		spin_unlock_irqrestore(&chan->vc.lock, flags);
-		dma_set_residue(txstate, bytes);
-	} else {
-		spin_unlock_irqrestore(&chan->vc.lock, flags);
 	}
 
+	spin_unlock_irqrestore(&chan->vc.lock, flags);
+	dma_set_residue(txstate, bytes);
+
 	return status;
 }
 
@@ -379,14 +376,13 @@ static void dw_axi_dma_set_byte_halfword(struct axi_dma_chan *chan, bool set)
 
 	iowrite32(val, chan->chip->apb_regs + offset);
 }
-
 /* Called in chan locked context */
 static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
 				      struct axi_dma_desc *first)
 {
-	struct dma_multi *multi = &chan->chip->multi;
 	u32 priority = chan->chip->dw->hdata->priority[chan->id];
-	u32 reg_lo, reg_hi, irq_mask;
+	struct axi_dma_chan_config config = {};
+	u32 irq_mask;
 	u8 lms = 0; /* Select AXI0 master for LLI fetching */
 
 	if (unlikely(axi_chan_is_hw_enable(chan))) {
@@ -398,65 +394,36 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
 
 	axi_dma_enable(chan->chip);
 
-	reg_lo = (DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_DST_MULTBLK_TYPE_POS |
-	       DWAXIDMAC_MBLK_TYPE_LL << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
-
-	reg_hi = (DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC << CH_CFG_H_TT_FC_POS |
-	       priority << multi->cfg.ch_cfg_priority_pos |
-	       DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_DST_POS |
-	       DWAXIDMAC_HS_SEL_HW << CH_CFG_H_HS_SEL_SRC_POS);
+	config.dst_multblk_type = DWAXIDMAC_MBLK_TYPE_LL;
+	config.src_multblk_type = DWAXIDMAC_MBLK_TYPE_LL;
+	config.tt_fc = DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC;
+	config.prior = priority;
+	config.hs_sel_dst = DWAXIDMAC_HS_SEL_HW;
+	config.hs_sel_src = DWAXIDMAC_HS_SEL_HW;
 	switch (chan->direction) {
 	case DMA_MEM_TO_DEV:
 		dw_axi_dma_set_byte_halfword(chan, true);
-		reg_hi |= (chan->config.device_fc ?
-			DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
-			DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC)
-			<< CH_CFG_H_TT_FC_POS;
+		config.tt_fc = chan->config.device_fc ?
+				DWAXIDMAC_TT_FC_MEM_TO_PER_DST :
+				DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC;
 		if (chan->chip->apb_regs)
-			reg_hi |= (chan->id << CH_CFG_H_DST_PER_POS);
+			config.dst_per = chan->id;
+		else
+			config.dst_per = chan->hw_handshake_num;
 		break;
 	case DMA_DEV_TO_MEM:
-		reg_hi |= (chan->config.device_fc ?
-			DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
-			DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC)
-			<< CH_CFG_H_TT_FC_POS;
+		config.tt_fc = chan->config.device_fc ?
+				DWAXIDMAC_TT_FC_PER_TO_MEM_SRC :
+				DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC;
 		if (chan->chip->apb_regs)
-			reg_hi |= (chan->id << CH_CFG_H_SRC_PER_POS);
+			config.src_per = chan->id;
+		else
+			config.src_per = chan->hw_handshake_num;
 		break;
 	default:
 		break;
 	}
-
-	reg_hi |= CH_CFG_H_MAX_OSR_LMT << CH_CFG_H_SRC_OSR_LMT_POS |
-		CH_CFG_H_MAX_OSR_LMT << CH_CFG_H_DST_OSR_LMT_POS;
-
-	if (chan->hw_handshake_num) {
-		switch (chan->direction) {
-		case DMA_MEM_TO_DEV:
-			if (multi->ch_cfg_2 == true)
-				reg_lo |= chan->hw_handshake_num
-					<< multi->cfg.ch_cfg_dst_per_pos;
-			else
-				reg_hi |= chan->hw_handshake_num
-					<< multi->cfg.ch_cfg_dst_per_pos;
-
-			break;
-		case DMA_DEV_TO_MEM:
-			if (multi->ch_cfg_2 == true)
-				reg_lo |= chan->hw_handshake_num
-					<< multi->cfg.ch_cfg_src_per_pos;
-			else
-				reg_hi |= chan->hw_handshake_num
-					<< multi->cfg.ch_cfg_src_per_pos;
-
-			break;
-		default:
-			break;
-		}
-	}
-
-	axi_chan_iowrite32(chan, CH_CFG_L, reg_lo);
-	axi_chan_iowrite32(chan, CH_CFG_H, reg_hi);
+	axi_chan_config_write(chan, &config);
 
 	write_chan_llp(chan, first->hw_desc[0].llp | lms);
 
@@ -467,17 +434,6 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan,
 	irq_mask |= DWAXIDMAC_IRQ_SUSPENDED;
 	axi_chan_irq_set(chan, irq_mask);
 
-	/*flush all the desc */
-#ifdef CONFIG_SOC_STARFIVE_VIC7100
-	if (chan->chip->multi.need_flush == true) {
-		int count = atomic_read(&chan->descs_allocated);
-		int i;
-
-		for (i = 0; i < count; i++) {
-			starfive_flush_dcache(first->hw_desc[i].llp,
-				sizeof(*first->hw_desc[i].lli));
-	}
-#endif
 	axi_chan_enable(chan);
 }
 
@@ -593,6 +549,8 @@ static void dw_axi_dma_set_hw_channel(struct axi_dma_chan *chan, bool set)
 			(chan->id * DMA_APB_HS_SEL_BIT_SIZE));
 	reg_value |= (val << (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
 	lo_hi_writeq(reg_value, chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
+
+	return;
 }
 
 /*
@@ -657,7 +615,6 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
 	size_t block_ts;
 	u32 ctllo, ctlhi;
 	u32 burst_len;
-	u32 burst_trans_len;
 
 	axi_block_ts = chan->chip->dw->hdata->block_size[chan->id];
 
@@ -721,14 +678,8 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
 
 	hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
 
-	if (chan->fixed_burst_trans_len == true)
-		burst_trans_len = chan->burst_trans_len;
-	else
-		burst_trans_len = DWAXIDMAC_BURST_TRANS_LEN_4;
-
-	ctllo |= burst_trans_len << CH_CTL_L_DST_MSIZE_POS |
-		 burst_trans_len << CH_CTL_L_SRC_MSIZE_POS;
-
+	ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
+		 DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
 	hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
 
 	set_desc_src_master(hw_desc);
@@ -793,10 +744,6 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr,
 
 	num_segments = DIV_ROUND_UP(period_len, axi_block_len);
 	segment_len = DIV_ROUND_UP(period_len, num_segments);
-	if (!IS_ALIGNED(segment_len, 4)) {
-		segment_len = ALIGN(segment_len, 4);
-		period_len = segment_len * num_segments;
-	}
 
 	total_segments = num_periods * num_segments;
 
@@ -1043,6 +990,11 @@ static int dw_axi_dma_chan_slave_config(struct dma_chan *dchan,
 static void axi_chan_dump_lli(struct axi_dma_chan *chan,
 			      struct axi_dma_hw_desc *desc)
 {
+	if (!desc->lli) {
+		dev_err(dchan2dev(&chan->vc.chan), "NULL LLI\n");
+		return;
+	}
+
 	dev_err(dchan2dev(&chan->vc.chan),
 		"SAR: 0x%llx DAR: 0x%llx LLP: 0x%llx BTS 0x%x CTL: 0x%x:%08x",
 		le64_to_cpu(desc->lli->sar),
@@ -1074,6 +1026,11 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
 
 	/* The bad descriptor currently is in the head of vc list */
 	vd = vchan_next_desc(&chan->vc);
+	if (!vd) {
+		dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n",
+			axi_chan_name(chan));
+		goto out;
+	}
 	/* Remove the completed descriptor from issued list */
 	list_del(&vd->node);
 
@@ -1088,6 +1045,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status)
 	/* Try to restart the controller */
 	axi_chan_start_first_queued(chan);
 
+out:
 	spin_unlock_irqrestore(&chan->vc.lock, flags);
 }
 
@@ -1103,14 +1061,18 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
 
 	spin_lock_irqsave(&chan->vc.lock, flags);
 	if (unlikely(axi_chan_is_hw_enable(chan))) {
-		dev_err(chan2dev(chan),
-			"BUG: %s caught DWAXIDMAC_IRQ_DMA_TRF, but channel not idle!\n",
+		dev_err(chan2dev(chan), "BUG: %s caught DWAXIDMAC_IRQ_DMA_TRF, but channel not idle!\n",
 			axi_chan_name(chan));
 		axi_chan_disable(chan);
 	}
 
 	/* The completed descriptor currently is in the head of vc list */
 	vd = vchan_next_desc(&chan->vc);
+	if (!vd) {
+		dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n",
+			axi_chan_name(chan));
+		goto out;
+	}
 
 	if (chan->cyclic) {
 		desc = vd_to_axi_desc(vd);
@@ -1121,9 +1083,6 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
 				if (hw_desc->llp == llp) {
 					axi_chan_irq_clear(chan, hw_desc->lli->status_lo);
 					hw_desc->lli->ctl_hi |= CH_CTL_H_LLI_VALID;
-					#ifdef CONFIG_SOC_STARFIVE_VIC7100
-					starfive_flush_dcache(hw_desc->llp, sizeof(*hw_desc->lli));
-					#endif
 					desc->completed_blocks = i;
 
 					if (((hw_desc->len * (i + 1)) % desc->period_len) == 0)
@@ -1143,6 +1102,7 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan)
 		axi_chan_start_first_queued(chan);
 	}
 
+out:
 	spin_unlock_irqrestore(&chan->vc.lock, flags);
 }
 
@@ -1154,10 +1114,10 @@ static irqreturn_t dw_axi_dma_interrupt(int irq, void *dev_id)
 
 	u32 status, i;
 
-	/* Disable DMAC inerrupts. We'll enable them after processing chanels */
+	/* Disable DMAC interrupts. We'll enable them after processing channels */
 	axi_dma_irq_disable(chip);
 
-	/* Poll, clear and process every chanel interrupt status */
+	/* Poll, clear and process every channel interrupt status */
 	for (i = 0; i < dw->hdata->nr_channels; i++) {
 		chan = &dw->chan[i];
 		status = axi_chan_irq_read(chan);
@@ -1190,7 +1150,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
 	axi_chan_disable(chan);
 
 	ret = readl_poll_timeout_atomic(chan->chip->regs + DMAC_CHEN, val,
-					!(val & chan_active), 1000, TIMEOUT_US);
+					!(val & chan_active), 1000, 100000);
 	if (ret == -ETIMEDOUT)
 		dev_warn(dchan2dev(dchan),
 			 "%s failed to stop\n", axi_chan_name(chan));
@@ -1217,17 +1177,23 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
 static int dma_chan_pause(struct dma_chan *dchan)
 {
 	struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
-	struct dma_multi *multi = &chan->chip->multi;
 	unsigned long flags;
 	unsigned int timeout = 20; /* timeout iterations */
 	u32 val;
 
 	spin_lock_irqsave(&chan->vc.lock, flags);
 
-	val = axi_dma_ioread32(chan->chip, multi->en.ch_susp);
-	val |= BIT(chan->id) << multi->en.ch_susp_shift |
-	       BIT(chan->id) << multi->en.ch_susp_we_shift;
-	axi_dma_iowrite32(chan->chip, multi->en.ch_susp, val);
+	if (chan->chip->dw->hdata->reg_map_8_channels) {
+		val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+		val |= BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT |
+			BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
+		axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+	} else {
+		val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+		val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
+			BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
+		axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+	}
 
 	do  {
 		if (axi_chan_irq_read(chan) & DWAXIDMAC_IRQ_SUSPENDED)
@@ -1248,13 +1214,19 @@ static int dma_chan_pause(struct dma_chan *dchan)
 /* Called in chan locked context */
 static inline void axi_chan_resume(struct axi_dma_chan *chan)
 {
-	struct dma_multi *multi = &chan->chip->multi;
 	u32 val;
 
-	val = axi_dma_ioread32(chan->chip, multi->en.ch_susp);
-	val &= ~(BIT(chan->id) << multi->en.ch_susp_shift);
-	val |=  (BIT(chan->id) << multi->en.ch_susp_we_shift);
-	axi_dma_iowrite32(chan->chip, multi->en.ch_susp, val);
+	if (chan->chip->dw->hdata->reg_map_8_channels) {
+		val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
+		val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
+		val |=  (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
+		axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
+	} else {
+		val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
+		val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
+		val |=  (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
+		axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
+	}
 
 	chan->is_paused = false;
 }
@@ -1281,7 +1253,7 @@ static int axi_dma_suspend(struct axi_dma_chip *chip)
 
 	clk_disable_unprepare(chip->core_clk);
 	clk_disable_unprepare(chip->cfgr_clk);
-	clk_disable_unprepare(chip->axi_clk);
+	clk_disable_unprepare(chip->noc_clk);
 
 	return 0;
 }
@@ -1290,7 +1262,7 @@ static int axi_dma_resume(struct axi_dma_chip *chip)
 {
 	int ret;
 
-	ret = clk_prepare_enable(chip->axi_clk);
+	ret = clk_prepare_enable(chip->noc_clk);
 	if (ret < 0)
 		return ret;
 
@@ -1308,17 +1280,6 @@ static int axi_dma_resume(struct axi_dma_chip *chip)
 	return 0;
 }
 
-void axi_dma_cyclic_stop(struct dma_chan *dchan)
-{
-	struct axi_dma_chan *chan = dchan_to_axi_dma_chan(dchan);
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->vc.lock, flags);
-	axi_chan_disable(chan);
-	spin_unlock_irqrestore(&chan->vc.lock, flags);
-}
-EXPORT_SYMBOL(axi_dma_cyclic_stop);
-
 static int __maybe_unused axi_dma_runtime_suspend(struct device *dev)
 {
 	struct axi_dma_chip *chip = dev_get_drvdata(dev);
@@ -1346,13 +1307,6 @@ static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec,
 
 	chan = dchan_to_axi_dma_chan(dchan);
 	chan->hw_handshake_num = dma_spec->args[0];
-
-	/*some per may need fixed-burst_trans_len*/
-	if (dma_spec->args_count == 2  && dma_spec->args[1] > 0) {
-		chan->fixed_burst_trans_len = true;
-		chan->burst_trans_len = dma_spec->args[1];
-	}
-
 	return dchan;
 }
 
@@ -1369,6 +1323,8 @@ static int parse_device_properties(struct axi_dma_chip *chip)
 		return -EINVAL;
 
 	chip->dw->hdata->nr_channels = tmp;
+	if (tmp <= DMA_REG_MAP_CH_REF)
+		chip->dw->hdata->reg_map_8_channels = true;
 
 	ret = device_property_read_u32(dev, "snps,dma-masters", &tmp);
 	if (ret)
@@ -1421,34 +1377,16 @@ static int parse_device_properties(struct axi_dma_chip *chip)
 		chip->dw->hdata->axi_rw_burst_len = tmp;
 	}
 
-
-	/* get number of handshak interface and configure multi reg */
-	ret = device_property_read_u32(dev, "snps,num-hs-if", &tmp);
-	if (!ret)
-		chip->dw->hdata->nr_hs_if = tmp;
-
-	if (chip->dw->hdata->nr_channels > 8) {
-#ifdef CONFIG_SOC_STARFIVE_VIC7100
-		chip->multi.need_flush = true;
-#endif
-		chip->multi.ch_enreg_2 = true;
-	}
-
-	if (chip->dw->hdata->nr_channels > 8 || chip->dw->hdata->nr_hs_if > 16)
-		chip->multi.ch_cfg_2 = true;
-
-	axi_chan_set_multi_reg(chip);
-
 	return 0;
 }
 
 static int dw_probe(struct platform_device *pdev)
 {
-	struct device_node *node = pdev->dev.of_node;
 	struct axi_dma_chip *chip;
-	struct resource *mem;
 	struct dw_axi_dma *dw;
 	struct dw_axi_dma_hcfg *hdata;
+	struct reset_control *resets;
+	unsigned int flags;
 	u32 i;
 	int ret;
 
@@ -1472,20 +1410,28 @@ static int dw_probe(struct platform_device *pdev)
 	if (chip->irq < 0)
 		return chip->irq;
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	chip->regs = devm_ioremap_resource(chip->dev, mem);
+	chip->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(chip->regs))
 		return PTR_ERR(chip->regs);
 
-	if (of_device_is_compatible(node, "intel,kmb-axi-dma")) {
+	flags = (uintptr_t)of_device_get_match_data(&pdev->dev);
+	if (flags & AXI_DMA_FLAG_HAS_APB_REGS) {
 		chip->apb_regs = devm_platform_ioremap_resource(pdev, 1);
 		if (IS_ERR(chip->apb_regs))
 			return PTR_ERR(chip->apb_regs);
 	}
 
-	chip->axi_clk = devm_clk_get(chip->dev, "stg_clk");
-	if (IS_ERR(chip->axi_clk))
-		return PTR_ERR(chip->axi_clk);
+	if (flags & AXI_DMA_FLAG_HAS_RESETS) {
+		resets = devm_reset_control_array_get_exclusive(&pdev->dev);
+		if (IS_ERR(resets))
+			return PTR_ERR(resets);
+
+		ret = reset_control_deassert(resets);
+		if (ret)
+			return ret;
+	}
+
+	chip->dw->hdata->use_cfg2 = !!(flags & AXI_DMA_FLAG_USE_CFG2);
 
 	chip->core_clk = devm_clk_get(chip->dev, "core-clk");
 	if (IS_ERR(chip->core_clk))
@@ -1495,25 +1441,9 @@ static int dw_probe(struct platform_device *pdev)
 	if (IS_ERR(chip->cfgr_clk))
 		return PTR_ERR(chip->cfgr_clk);
 
-	chip->rst_axi = devm_reset_control_get_exclusive(&pdev->dev, "rst_stg");
-	if (IS_ERR(chip->rst_axi)) {
-		dev_err(&pdev->dev, "%s: failed to get rst_stg reset control\n", __func__);
-		return PTR_ERR(chip->rst_axi);
-	}
-	chip->rst_core = devm_reset_control_get_exclusive(&pdev->dev, "rst_axi");
-	if (IS_ERR(chip->rst_core)) {
-		dev_err(&pdev->dev, "%s: failed to get rst_core reset control\n", __func__);
-		return PTR_ERR(chip->rst_core);
-	}
-	chip->rst_cfgr = devm_reset_control_get_exclusive(&pdev->dev, "rst_ahb");
-	if (IS_ERR(chip->rst_cfgr)) {
-		dev_err(&pdev->dev, "%s: failed to get rst_cfgr reset control\n", __func__);
-		return PTR_ERR(chip->rst_cfgr);
-	}
-
-	reset_control_deassert(chip->rst_axi);
-	reset_control_deassert(chip->rst_core);
-	reset_control_deassert(chip->rst_cfgr);
+	chip->noc_clk = devm_clk_get(chip->dev, "noc-clk");
+	if (IS_ERR(chip->noc_clk))
+		return PTR_ERR(chip->noc_clk);
 
 	ret = parse_device_properties(chip);
 	if (ret)
@@ -1627,9 +1557,9 @@ static int dw_remove(struct platform_device *pdev)
 	u32 i;
 
 	/* Enable clk before accessing to registers */
-	clk_prepare_enable(chip->axi_clk);
 	clk_prepare_enable(chip->cfgr_clk);
 	clk_prepare_enable(chip->core_clk);
+	clk_prepare_enable(chip->noc_clk);
 	axi_dma_irq_disable(chip);
 	for (i = 0; i < dw->hdata->nr_channels; i++) {
 		axi_chan_disable(&chip->dw->chan[i]);
@@ -1658,9 +1588,15 @@ static const struct dev_pm_ops dw_axi_dma_pm_ops = {
 };
 
 static const struct of_device_id dw_dma_of_id_table[] = {
-	{ .compatible = "snps,axi-dma-1.01a" },
-	{ .compatible = "intel,kmb-axi-dma" },
-	{ .compatible = "starfive,jh7110-dma" },
+	{
+		.compatible = "snps,axi-dma-1.01a"
+	}, {
+		.compatible = "intel,kmb-axi-dma",
+		.data = (void *)AXI_DMA_FLAG_HAS_APB_REGS,
+	}, {
+		.compatible = "starfive,jh7110-axi-dma",
+		.data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2),
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
index 416cc4b52f13..1e6ce776a32c 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
@@ -1,11 +1,10 @@
-// SPDX-License-Identifier:  GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 // (C) 2017-2018 Synopsys, Inc. (www.synopsys.com)
 
 /*
  * Synopsys DesignWare AXI DMA Controller driver.
  *
  * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
- *         Samin.guo <samin.guo@starfivetech.com>
  */
 
 #ifndef _AXI_DMA_PLATFORM_H
@@ -23,44 +22,18 @@
 #define DMAC_MAX_MASTERS	2
 #define DMAC_MAX_BLK_SIZE	0x200000
 
-#define TIMEOUT_US		200000
-
-struct dma_ch_en {
-	u8 ch_en;
-	u8 ch_en_shift;
-	u8 ch_en_we_shift;
-	u8 ch_susp;
-	u8 ch_susp_shift;
-	u8 ch_susp_we_shift;
-	u8 ch_abort;
-	u8 ch_abort_shift;
-	u8 ch_abort_we_shfit;
-};
-
-struct dma_ch_cfg {
-	u8 ch_cfg_priority_pos;
-	u8 ch_cfg_dst_per_pos;
-	u8 ch_cfg_src_per_pos;
-};
-
-struct dma_multi {
-	bool ch_cfg_2;
-	bool ch_enreg_2;
-	struct dma_ch_cfg cfg;
-	struct dma_ch_en en;
-	bool need_flush;
-};
-
 struct dw_axi_dma_hcfg {
 	u32	nr_channels;
 	u32	nr_masters;
-	u32	nr_hs_if;
 	u32	m_data_width;
 	u32	block_size[DMAC_MAX_CHANNELS];
 	u32	priority[DMAC_MAX_CHANNELS];
 	/* maximum supported axi burst length */
 	u32	axi_rw_burst_len;
+	/* Register map for DMAX_NUM_CHANNELS <= 8 */
+	bool	reg_map_8_channels;
 	bool	restrict_axi_burst_len;
+	bool	use_cfg2;
 };
 
 struct axi_dma_chan {
@@ -68,7 +41,6 @@ struct axi_dma_chan {
 	void __iomem			*chan_regs;
 	u8				id;
 	u8				hw_handshake_num;
-	s8				burst_trans_len;
 	atomic_t			descs_allocated;
 
 	struct dma_pool			*desc_pool;
@@ -77,7 +49,6 @@ struct axi_dma_chan {
 	struct axi_dma_desc		*desc;
 	struct dma_slave_config		config;
 	enum dma_transfer_direction	direction;
-	bool 				fixed_burst_trans_len;
 	bool				cyclic;
 	/* these other elements are all protected by vc.lock */
 	bool				is_paused;
@@ -99,12 +70,8 @@ struct axi_dma_chip {
 	void __iomem		*apb_regs;
 	struct clk		*core_clk;
 	struct clk		*cfgr_clk;
-	struct clk		*axi_clk;
+	struct clk		*noc_clk;
 	struct dw_axi_dma	*dw;
-	struct dma_multi	multi;
-	struct reset_control	*rst_core;
-	struct reset_control	*rst_cfgr;
-	struct reset_control	*rst_axi;
 };
 
 /* LLI == Linked List Item */
@@ -133,11 +100,22 @@ struct axi_dma_hw_desc {
 struct axi_dma_desc {
 	struct axi_dma_hw_desc	*hw_desc;
 
-	struct virt_dma_desc	vd;
-	struct axi_dma_chan	*chan;
-	u32			completed_blocks;
-	u32			length;
-	u32			period_len;
+	struct virt_dma_desc		vd;
+	struct axi_dma_chan		*chan;
+	u32				completed_blocks;
+	u32				length;
+	u32				period_len;
+};
+
+struct axi_dma_chan_config {
+	u8 dst_multblk_type;
+	u8 src_multblk_type;
+	u8 dst_per;
+	u8 src_per;
+	u8 tt_fc;
+	u8 prior;
+	u8 hs_sel_dst;
+	u8 hs_sel_src;
 };
 
 static inline struct device *dchan2dev(struct dma_chan *dchan)
@@ -176,15 +154,8 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
 #define DMAC_CHEN		0x018 /* R/W DMAC Channel Enable */
 #define DMAC_CHEN_L		0x018 /* R/W DMAC Channel Enable 00-31 */
 #define DMAC_CHEN_H		0x01C /* R/W DMAC Channel Enable 32-63 */
-#define DMAC_CHSUSP		0x018 /* R/W DMAC Channel suspend */
-#define DMAC_CHABORT		0x018 /* R/W DMAC Channel Abort */
-
-#define DMAC_CHEN_2		0x018 /* R/W DMAC Channel Enable */
-#define DMAC_CHEN_L_2		0x018 /* R/W DMAC Channel Enable */
-#define DMAC_CHEN_H_2		0x01C /* R/W DMAC Channel Enable */
-#define DMAC_CHSUSP_2		0x020 /* R/W DMAC Channel Suspend */
-#define DMAC_CHABORT_2		0x028 /* R/W DMAC Channel Abort */
-
+#define DMAC_CHSUSPREG		0x020 /* R/W DMAC Channel Suspend */
+#define DMAC_CHABORTREG		0x028 /* R/W DMAC Channel Abort */
 #define DMAC_INTSTATUS		0x030 /* R DMAC Interrupt Status */
 #define DMAC_COMMON_INTCLEAR	0x038 /* W DMAC Interrupt Clear */
 #define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status Enable */
@@ -233,6 +204,7 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
 #define DMA_APB_HS_SEL_BIT_SIZE	0x08 /* HW handshake bits per channel */
 #define DMA_APB_HS_SEL_MASK	0xFF /* HW handshake select masks */
 #define MAX_BLOCK_SIZE		0x1000 /* 1024 blocks * 4 bytes data width */
+#define DMA_REG_MAP_CH_REF	0x08 /* Channel count to choose register map */
 
 /* DMAC_CFG */
 #define DMAC_EN_POS			0
@@ -241,23 +213,19 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
 #define INT_EN_POS			1
 #define INT_EN_MASK			BIT(INT_EN_POS)
 
+/* DMAC_CHEN */
 #define DMAC_CHAN_EN_SHIFT		0
 #define DMAC_CHAN_EN_WE_SHIFT		8
 
 #define DMAC_CHAN_SUSP_SHIFT		16
 #define DMAC_CHAN_SUSP_WE_SHIFT		24
 
-#define DMAC_CHAN_ABORT_SHIFT		32
-#define DMAC_CHAN_ABORT_WE_SHIFT	40
-
-#define DMAC_CHAN_EN_SHIFT_2		0
-#define DMAC_CHAN_EN_WE_SHIFT_2		16
+/* DMAC_CHEN2 */
+#define DMAC_CHAN_EN2_WE_SHIFT		16
 
-#define DMAC_CHAN_SUSP_SHIFT_2		0
-#define DMAC_CHAN_SUSP_WE_SHIFT_2	16
-
-#define DMAC_CHAN_ABORT_SHIFT_2		0
-#define DMAC_CHAN_ABORT_WE_SHIFT_2	16
+/* DMAC_CHSUSP */
+#define DMAC_CHAN_SUSP2_SHIFT		0
+#define DMAC_CHAN_SUSP2_WE_SHIFT	16
 
 /* CH_CTL_H */
 #define CH_CTL_H_ARLEN_EN		BIT(6)
@@ -321,7 +289,6 @@ enum {
 #define CH_CFG_H_PRIORITY_POS		17
 #define CH_CFG_H_DST_PER_POS		12
 #define CH_CFG_H_SRC_PER_POS		7
-#define CH_CFG_H_PRIORITY_POS_2		15
 #define CH_CFG_H_HS_SEL_DST_POS		4
 #define CH_CFG_H_HS_SEL_SRC_POS		3
 enum {
@@ -344,9 +311,6 @@ enum {
 /* CH_CFG_L */
 #define CH_CFG_L_DST_MULTBLK_TYPE_POS	2
 #define CH_CFG_L_SRC_MULTBLK_TYPE_POS	0
-
-#define CH_CFG_L_DST_PER_POS_2		11
-#define CH_CFG_L_SRC_PER_POS_2		4
 enum {
 	DWAXIDMAC_MBLK_TYPE_CONTIGUOUS	= 0,
 	DWAXIDMAC_MBLK_TYPE_RELOAD,
@@ -354,6 +318,15 @@ enum {
 	DWAXIDMAC_MBLK_TYPE_LL
 };
 
+/* CH_CFG2 */
+#define CH_CFG2_L_SRC_PER_POS		4
+#define CH_CFG2_L_DST_PER_POS		11
+
+#define CH_CFG2_H_TT_FC_POS		0
+#define CH_CFG2_H_HS_SEL_SRC_POS	3
+#define CH_CFG2_H_HS_SEL_DST_POS	4
+#define CH_CFG2_H_PRIORITY_POS		20
+
 /**
  * DW AXI DMA channel interrupts
  *
diff --git a/sound/soc/starfive/starfive_pwmdac.c b/sound/soc/starfive/starfive_pwmdac.c
index fba58e22d7ef..231bf192590c 100644
--- a/sound/soc/starfive/starfive_pwmdac.c
+++ b/sound/soc/starfive/starfive_pwmdac.c
@@ -495,6 +495,17 @@ static int pwmdac_config(struct sf_pwmdac_dev *dev)
 	return 0;
 }
 
+static int sf_pwmdac_startup(struct snd_pcm_substream *substream,
+			     struct snd_soc_dai *cpu_dai)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+	dai_link->stop_dma_first = 1;
+
+	return 0;
+}
+
 static int sf_pwmdac_prepare(struct snd_pcm_substream *substream,
 			  struct snd_soc_dai *dai)
 {
@@ -565,10 +576,6 @@ static int sf_pwmdac_hw_params(struct snd_pcm_substream *substream,
 	int ret = 0;
 	unsigned long mclk_dac_value;
 	struct sf_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
-	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-	struct snd_soc_dai_link *dai_link = rtd->dai_link;
-
-	dai_link->stop_dma_first = 1;
 
 	dev->play_dma_data.addr = dev->mapbase + PWMDAC_WDATA;
 
@@ -829,40 +836,15 @@ static int pwmdac_probe(struct snd_soc_component *component)
 }
 
 static const struct snd_soc_dai_ops sf_pwmdac_dai_ops = {
-	.hw_params  = sf_pwmdac_hw_params,
-	.prepare	= sf_pwmdac_prepare,
-	.trigger	= sf_pwmdac_trigger,
+	.startup = sf_pwmdac_startup,
+	.hw_params = sf_pwmdac_hw_params,
+	.prepare = sf_pwmdac_prepare,
+	.trigger = sf_pwmdac_trigger,
 };
 
-static int pwmdac_component_trigger(struct snd_soc_component *component,
-			      struct snd_pcm_substream *substream, int cmd)
-{
-	int ret = 0;
-	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		axi_dma_cyclic_stop(chan);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
 static const struct snd_soc_component_driver sf_pwmdac_component = {
-	.name		= "starfive-pwmdac",
-	.probe		= pwmdac_probe,
-	.trigger	= pwmdac_component_trigger,
+	.name = "starfive-pwmdac",
+	.probe = pwmdac_probe,
 };
 
 static struct snd_soc_dai_driver pwmdac_dai = {
diff --git a/sound/soc/starfive/starfive_tdm.c b/sound/soc/starfive/starfive_tdm.c
index 375e266046a2..42d369bc3af3 100644
--- a/sound/soc/starfive/starfive_tdm.c
+++ b/sound/soc/starfive/starfive_tdm.c
@@ -255,42 +255,23 @@ static int sf_tdm_resume(struct snd_soc_component *component)
 #define sf_tdm_resume	NULL
 #endif
 
-/* 
- * To stop dma first, we must implement this function, because it is
- * called before stopping the stream. 
- */
-static int sf_pcm_trigger(struct snd_soc_component *component,
-			      struct snd_pcm_substream *substream, int cmd)
-{
-	int ret = 0;
-	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_RESUME:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		axi_dma_cyclic_stop(chan);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
 static const struct snd_soc_component_driver sf_tdm_component = {
 	.name		= "jh7110-tdm",
 	.suspend	= sf_tdm_suspend,
 	.resume		= sf_tdm_resume,
-	.trigger	= sf_pcm_trigger,
 };
 
+static int sf_tdm_startup(struct snd_pcm_substream *substream,
+			      struct snd_soc_dai *cpu_dai)
+{
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+	dai_link->stop_dma_first = 1;
+
+	return 0;
+}
+
 static int sf_tdm_hw_params(struct snd_pcm_substream *substream,
 		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
@@ -302,10 +283,6 @@ static int sf_tdm_hw_params(struct snd_pcm_substream *substream,
 	int channels;
 	int ret;
 	struct snd_dmaengine_dai_dma_data *dma_data = NULL;
-	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-	struct snd_soc_dai_link *dai_link = rtd->dai_link;
-
-	dai_link->stop_dma_first = 1;
 
 	channels = params_channels(params);
 	data_width = params_width(params);
@@ -490,6 +467,7 @@ static int sf_tdm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 }
 
 static const struct snd_soc_dai_ops sf_tdm_dai_ops = {
+	.startup	= sf_tdm_startup,
 	.hw_params	= sf_tdm_hw_params,
 	.trigger	= sf_tdm_trigger,
 	.set_fmt	= sf_tdm_set_fmt,