From bd706a44dc2b386c02f2d21dc3d0d42a39c466ba Mon Sep 17 00:00:00 2001 From: xuxiang Date: Thu, 23 May 2024 10:01:46 +0800 Subject: [PATCH 020/222] feat:Add dma driver. Changelogs: 1.Add dma driver for linux-6.6. --- .../dts/eswin/eswin-win2030-die0-soc.dtsi | 20 ++- .../dts/eswin/eswin-win2030-die1-soc.dtsi | 10 +- drivers/clk/eswin/clk-win2030.c | 4 + .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 169 ++++++++++++++++-- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 5 +- include/dt-bindings/clock/win2030-clock.h | 2 + 6 files changed, 182 insertions(+), 28 deletions(-) diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi index 1e813abf0819..a9f269bd9325 100644 --- a/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi +++ b/arch/riscv/boot/dts/eswin/eswin-win2030-die0-soc.dtsi @@ -375,13 +375,14 @@ d0_pmu_dsp3: win2030-pmu-controller-port@240 { }; d0_dmac0: dma-controller-hsp@0x50430000 { - compatible = "snps,axi-dma-1.01a"; + compatible = "eswin,eic770x-axi-dma"; reg = <0x0 0x50430000 0x0 0x10000>; interrupt-parent = <&plic0>; interrupts = <57>; #dma-cells = <2>; // change dma-cells value <1> to <2>, to support peripheral selection dma-controller,See the parameter dmas for details; - clocks = <&d0_clock WIN2030_CLK_HSP_DMA0_CLK>; - clock-names = "core-clk"; + clocks = <&d0_clock WIN2030_CLK_HSP_DMA0_CLK>, + <&d0_clock WIN2030_CLK_HSP_DMA0_CLK_TEST>; + clock-names = "core-clk", "cfgr-clk"; resets = <&d0_reset HSPDMA_RST_CTRL SW_HSP_DMA0_RSTN>, <&d0_reset HSPDMA_RST_CTRL SW_HSP_DMA_PRSTN>; reset-names = "arst", "prst"; @@ -401,13 +402,14 @@ d0_dmac0: dma-controller-hsp@0x50430000 { }; d0_aon_dmac: dma-controller-aon@0x518c0000 { - compatible = "snps,axi-dma-1.01a"; + compatible = "eswin,eic770x-axi-dma"; reg = <0x0 0x518c0000 0x0 0x10000>; interrupt-parent = <&plic0>; interrupts = <289>; #dma-cells = <2>; // change dma-cells value <1> to <2>, to support peripheral selection dma-controller,See the parameter dmas for details; - clocks = <&d0_clock WIN2030_CLK_AONDMA_ACLK>; - clock-names = "core-clk"; + clocks = <&d0_clock WIN2030_CLK_AONDMA_ACLK>, + <&d0_clock WIN2030_CLK_AONDMA_CFG>; + clock-names = "core-clk", "cfgr-clk"; resets = <&d0_reset DMA1_RST_CTRL SW_DMA1_ARSTN>, <&d0_reset DMA1_RST_CTRL SW_DMA1_HRSTN>; reset-names = "arst", "prst"; @@ -417,7 +419,7 @@ d0_aon_dmac: dma-controller-aon@0x518c0000 { snps,data-width = <3>; snps,block-size = <0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000 0x80000>; snps,axi-max-burst-len = <32>; - snps,max-msize = <64>; + // snps,max-msize = <64>; #size-cells = <2>; #address-cells = <2>; dma-ranges = <0x0 0x80000000 0x0 0x80000000 0x100 0x0>; @@ -806,7 +808,7 @@ msi_ctrl_int : 220 }; ssi0: spi@50810000 { - compatible = "snps,win2030-spi"; + compatible = "snps,eic770x-spi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x50810000 0x0 0x4000>; @@ -826,7 +828,7 @@ ssi0: spi@50810000 { }; ssi1: spi@50814000 { - compatible = "snps,win2030-spi"; + compatible = "snps,eic770x-spi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x50814000 0x0 0x4000>; diff --git a/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi b/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi index 5a55de6c7b2a..9e12379cc7d3 100644 --- a/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi +++ b/arch/riscv/boot/dts/eswin/eswin-win2030-die1-soc.dtsi @@ -323,7 +323,8 @@ d1_dmac0: dma-controller-hsp@0x70430000 { interrupts = <57>; #dma-cells = <2>; // change dma-cells value <1> to <2>, to support peripheral selection dma-controller,See the parameter dmas for details; clocks = <&d1_clock WIN2030_CLK_HSP_DMA0_CLK>; - clock-names = "core-clk"; + <&d1_clock WIN2030_CLK_HSP_DMA0_CLK_TEST>; + clock-names = "core-clk", "cfgr-clk"; resets = <&d1_reset HSPDMA_RST_CTRL SW_HSP_DMA0_RSTN>, <&d1_reset HSPDMA_RST_CTRL SW_HSP_DMA_PRSTN>; reset-names = "arst", "prst"; @@ -348,8 +349,9 @@ d1_aon_dmac: dma-controller-aon@0x718c0000 { interrupt-parent = <&plic1>; interrupts = <289>; #dma-cells = <2>; // change dma-cells value <1> to <2>, to support peripheral selection dma-controller,See the parameter dmas for details; - clocks = <&d1_clock WIN2030_CLK_AONDMA_ACLK>; - clock-names = "core-clk"; + clocks = <&d1_clock WIN2030_CLK_AONDMA_ACLK>, + <&d1_clock WIN2030_CLK_AONDMA_CFG>; + clock-names = "core-clk", "cfgr-clk"; resets = <&d1_reset DMA1_RST_CTRL SW_DMA1_ARSTN>, <&d1_reset DMA1_RST_CTRL SW_DMA1_HRSTN>; reset-names = "arst", "prst"; @@ -1620,7 +1622,7 @@ d1_sdio1: mmc@0x70470000{ }; d1_ssi0: spi1@70810000 { - compatible = "snps,win2030-spi"; + compatible = "snps,eic770x-spi"; #address-cells = <2>; #size-cells = <2>; reg = <0x0 0x70810000 0x0 0x5000>; diff --git a/drivers/clk/eswin/clk-win2030.c b/drivers/clk/eswin/clk-win2030.c index 2ff82f4feba1..64bf0476b4bc 100755 --- a/drivers/clk/eswin/clk-win2030.c +++ b/drivers/clk/eswin/clk-win2030.c @@ -906,6 +906,9 @@ static struct eswin_gate_clock win2030_gate_clks[] = { { WIN2030_GATE_HSP_SATA_OOB_CLK ,"gate_hsp_sata_oob_clk", "mux_u_sata_phy_2mux1", CLK_SET_RATE_PARENT, WIN2030_REG_OFFSET_SATA_OOB_CTRL, 31, 0, }, + { WIN2030_GATE_HSP_DMA0_CLK_TEST ,"gate_hsp_dma0_clk_test", "gate_clk_hsp_aclk", CLK_SET_RATE_PARENT, + WIN2030_REG_OFFSET_HSP_ACLK_CTRL, 1, 0, }, + { WIN2030_GATE_HSP_DMA0_CLK ,"gate_hsp_dma0_clk", "gate_clk_hsp_aclk", CLK_SET_RATE_PARENT, WIN2030_REG_OFFSET_HSP_ACLK_CTRL, 0, 0, }, @@ -1110,6 +1113,7 @@ static struct eswin_clock win2030_clks[] = { { WIN2030_CLK_VC_MON_PCLK ,"clk_vc_mon_pclk", "gate_vc_mon_pclk", CLK_SET_RATE_PARENT,}, { WIN2030_CLK_HSP_DMA0_CLK ,"clk_hsp_dma0_clk", "gate_hsp_dma0_clk", CLK_SET_RATE_PARENT,}, + { WIN2030_CLK_HSP_DMA0_CLK_TEST ,"clk_hsp_dma0_clk_TEST", "gate_hsp_dma0_clk", CLK_SET_RATE_PARENT,}, { WIN2030_CLK_HSP_RMII_REF_0 ,"clk_hsp_rmii_ref_0", "gate_hsp_rmii_ref_0", CLK_SET_RATE_PARENT,}, { WIN2030_CLK_HSP_RMII_REF_1 ,"clk_hsp_rmii_ref_1", "gate_hsp_rmii_ref_1", CLK_SET_RATE_PARENT,}, 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 72fb40de58b3..dd98cce3dad8 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -28,10 +28,15 @@ #include #include #include +#include #include "dw-axi-dmac.h" #include "../dmaengine.h" #include "../virt-dma.h" +#include +#include +#include +#include /* * The set of bus widths supported by the DMA controller. DW AXI DMAC supports @@ -50,6 +55,14 @@ #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) +#define AXI_DMA_FLAG_HAS_2RESETS BIT(3) + +#define AWSMMUSID GENMASK(31, 24) // The sid of write operation +#define AWSMMUSSID GENMASK(23, 16) // The ssid of write operation +#define ARSMMUSID GENMASK(15, 8) // The sid of read operation +#define ARSMMUSSID GENMASK(7, 0) // The ssid of read operation + +static int eswin_dma_sid_cfg(struct device *dev); static inline void axi_dma_iowrite32(struct axi_dma_chip *chip, u32 reg, u32 val) @@ -228,6 +241,16 @@ static void axi_dma_hw_init(struct axi_dma_chip *chip) ret = dma_set_mask_and_coherent(chip->dev, DMA_BIT_MASK(64)); if (ret) dev_warn(chip->dev, "Unable to set coherent mask\n"); + + if (of_node_name_prefix(chip->dev->of_node, "dma-controller-hsp")) { + eswin_dma_sid_cfg(chip->dev); + } + else { + win2030_aon_sid_cfg(chip->dev); + } + + /* TBU power up */ + win2030_tbu_power(chip->dev, true); } static u32 axi_chan_get_xfer_width(struct axi_dma_chan *chan, dma_addr_t src, @@ -575,25 +598,43 @@ static void write_desc_dar(struct axi_dma_hw_desc *desc, dma_addr_t adr) desc->lli->dar = cpu_to_le64(adr); } -static void set_desc_src_master(struct axi_dma_hw_desc *desc) +static void set_desc_src_master(struct axi_dma_hw_desc *hw_desc, + struct axi_dma_chan *chan) { u32 val; /* Select AXI0 for source master */ - val = le32_to_cpu(desc->lli->ctl_lo); - val &= ~CH_CTL_L_SRC_MAST; - desc->lli->ctl_lo = cpu_to_le32(val); + val = le32_to_cpu(hw_desc->lli->ctl_lo); + if (chan->chip->dw->hdata->nr_masters > 1) + { + if(DMA_DEV_TO_MEM == chan->direction || DMA_DEV_TO_DEV == chan->direction) { + val |= CH_CTL_L_SRC_MAST; + } + else + { + val &= ~CH_CTL_L_SRC_MAST; + } + } + else + val &= ~CH_CTL_L_SRC_MAST; + hw_desc->lli->ctl_lo = cpu_to_le32(val); } static void set_desc_dest_master(struct axi_dma_hw_desc *hw_desc, - struct axi_dma_desc *desc) + struct axi_dma_chan *chan) { u32 val; /* Select AXI1 for source master if available */ val = le32_to_cpu(hw_desc->lli->ctl_lo); - if (desc->chan->chip->dw->hdata->nr_masters > 1) - val |= CH_CTL_L_DST_MAST; + if (chan->chip->dw->hdata->nr_masters > 1) + { + if(DMA_MEM_TO_DEV == chan->direction || DMA_DEV_TO_DEV == chan->direction) { + val |= CH_CTL_L_DST_MAST; + } + else + val &= ~CH_CTL_L_DST_MAST; + } else val &= ~CH_CTL_L_DST_MAST; @@ -676,11 +717,11 @@ 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); ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_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); - + set_desc_src_master(hw_desc, chan); + set_desc_dest_master(hw_desc, chan); hw_desc->len = len; return 0; } @@ -945,8 +986,8 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS); hw_desc->lli->ctl_lo = cpu_to_le32(reg); - set_desc_src_master(hw_desc); - set_desc_dest_master(hw_desc, desc); + set_desc_src_master(hw_desc, chan); + set_desc_dest_master(hw_desc, chan); hw_desc->len = xfer_len; desc->length += hw_desc->len; @@ -1283,6 +1324,41 @@ static int __maybe_unused axi_dma_runtime_resume(struct device *dev) return axi_dma_resume(chip); } +int win2030_dma_sel_cfg(struct axi_dma_chan *chan, u32 val) +{ + struct axi_dma_chip *chip = chan->chip; + struct device *dev = chan->chip->dev; + int ret = 0; + struct regmap *regmap; + int dma_sel_reg; + u32 dma_sel = 0; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,syscfg"); + if (IS_ERR(regmap)) { + dev_err(dev, "No eswin,syscfg phandle specified\n"); + return -1; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,syscfg", 2, + &dma_sel_reg); + if (ret) { + dev_err(dev, "can't get sid cfg reg offset in sys_con(errno:%d)\n", ret); + return ret; + } + regmap_read(regmap, dma_sel_reg, &dma_sel); + + if (of_node_name_prefix(chip->dev->of_node, "dma-controller-hsp")) { + if (val < 32) + dma_sel &= ~(1 << val); + } + else { + if (val < 32) + dma_sel |= (1 << val); + } + regmap_write(regmap, dma_sel_reg, dma_sel); + return 0; +} + static struct dma_chan *dw_axi_dma_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { @@ -1296,6 +1372,8 @@ 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]; + if (dma_spec->args_count > 1) + win2030_dma_sel_cfg(chan, dma_spec->args[1]); return dchan; } @@ -1419,6 +1497,23 @@ static int dw_probe(struct platform_device *pdev) if (ret) return ret; } + if (flags & AXI_DMA_FLAG_HAS_2RESETS) { + resets = devm_reset_control_get_optional(&pdev->dev, "arst"); + if (IS_ERR(resets)) + return PTR_ERR(resets); + + ret = reset_control_deassert(resets); + if (ret) + return ret; + + resets = devm_reset_control_get_optional(&pdev->dev, "prst"); + 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); @@ -1533,6 +1628,51 @@ static int dw_probe(struct platform_device *pdev) return ret; } +static int eswin_dma_sid_cfg(struct device *dev) +{ + int ret; + struct regmap *regmap; + int hsp_mmu_dma_reg; + u32 rdwr_sid_ssid; + u32 sid; + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + + /* not behind smmu, use the default reset value(0x0) of the reg as streamID*/ + if (fwspec == NULL) { + dev_dbg(dev, "dev is not behind smmu, skip configuration of sid\n"); + return 0; + } + sid = fwspec->ids[0]; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "eswin,hsp_sp_csr"); + if (IS_ERR(regmap)) { + dev_dbg(dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1, + &hsp_mmu_dma_reg); + if (ret) { + dev_err(dev, "can't get dma sid cfg reg offset (%d)\n", ret); + return ret; + } + + /* make the reading sid the same as writing sid, ssid is fixed to zero */ + rdwr_sid_ssid = FIELD_PREP(AWSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSID, sid); + rdwr_sid_ssid |= FIELD_PREP(AWSMMUSSID, 0); + rdwr_sid_ssid |= FIELD_PREP(ARSMMUSSID, 0); + regmap_write(regmap, hsp_mmu_dma_reg, rdwr_sid_ssid); + + ret = win2030_dynm_sid_enable(dev_to_node(dev)); + if (ret < 0) + dev_err(dev, "failed to config dma streamID(%d)!\n", sid); + else + dev_dbg(dev, "success to config dma streamID(%d)!\n", sid); + + return ret; +} + static int dw_remove(struct platform_device *pdev) { struct axi_dma_chip *chip = platform_get_drvdata(pdev); @@ -1562,6 +1702,8 @@ static int dw_remove(struct platform_device *pdev) list_del(&chan->vc.chan.device_node); tasklet_kill(&chan->vc.task); } + /* TBU power down before reset */ + win2030_tbu_power(chip->dev, false); return 0; } @@ -1579,6 +1721,9 @@ static const struct of_device_id dw_dma_of_id_table[] = { }, { .compatible = "starfive,jh7110-axi-dma", .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2), + }, { + .compatible = "eswin,eic770x-axi-dma", + .data = (void *)(AXI_DMA_FLAG_HAS_2RESETS | AXI_DMA_FLAG_USE_CFG2), }, {} }; diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index 8521530a34ec..cc09abf15aad 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -203,7 +203,7 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan) #define UNUSED_CHANNEL 0x3F /* Set unused DMA channel to 0x3F */ #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 MAX_BLOCK_SIZE 0x1000 /* 1024 blocks * 512 bytes data width */ #define DMA_REG_MAP_CH_REF 0x08 /* Channel count to choose register map */ /* DMAC_CFG */ @@ -322,8 +322,7 @@ enum { #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 - +#define CH_CFG2_H_PRIORITY_POS 15 /** * DW AXI DMA channel interrupts * diff --git a/include/dt-bindings/clock/win2030-clock.h b/include/dt-bindings/clock/win2030-clock.h index 6c85b4b980f2..7793f3925932 100755 --- a/include/dt-bindings/clock/win2030-clock.h +++ b/include/dt-bindings/clock/win2030-clock.h @@ -378,6 +378,7 @@ #define WIN2030_GATE_VC_VD_PCLK 411 #define WIN2030_GATE_VC_MON_PCLK 412 #define WIN2030_GATE_HSP_DMA0_CLK 413 +#define WIN2030_GATE_HSP_DMA0_CLK_TEST 414 /*fixed factor clocks*/ #define WIN2030_FIXED_FACTOR_U_CPU_DIV2 450 @@ -596,6 +597,7 @@ #define WIN2030_CLK_VC_MON_PCLK 689 #define WIN2030_CLK_HSP_DMA0_CLK 690 +#define WIN2030_CLK_HSP_DMA0_CLK_TEST 691 #define WIN2030_NR_CLKS 700 -- 2.47.0