Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'add-driver-support-for-eswin-eic7700-soc-ethernet-controller'

Shangjuan Wei says:

====================
Add driver support for Eswin eic7700 SoC ethernet controller
====================

Link: https://patch.msgid.link/20251015113751.1114-1-weishangjuan@eswincomputing.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+372
+127
Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/net/eswin,eic7700-eth.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Eswin EIC7700 SOC Eth Controller 8 + 9 + maintainers: 10 + - Shuang Liang <liangshuang@eswincomputing.com> 11 + - Zhi Li <lizhi2@eswincomputing.com> 12 + - Shangjuan Wei <weishangjuan@eswincomputing.com> 13 + 14 + description: 15 + Platform glue layer implementation for STMMAC Ethernet driver. 16 + 17 + select: 18 + properties: 19 + compatible: 20 + contains: 21 + enum: 22 + - eswin,eic7700-qos-eth 23 + required: 24 + - compatible 25 + 26 + allOf: 27 + - $ref: snps,dwmac.yaml# 28 + 29 + properties: 30 + compatible: 31 + items: 32 + - const: eswin,eic7700-qos-eth 33 + - const: snps,dwmac-5.20 34 + 35 + reg: 36 + maxItems: 1 37 + 38 + interrupts: 39 + maxItems: 1 40 + 41 + interrupt-names: 42 + const: macirq 43 + 44 + clocks: 45 + items: 46 + - description: AXI clock 47 + - description: Configuration clock 48 + - description: GMAC main clock 49 + - description: Tx clock 50 + 51 + clock-names: 52 + items: 53 + - const: axi 54 + - const: cfg 55 + - const: stmmaceth 56 + - const: tx 57 + 58 + resets: 59 + maxItems: 1 60 + 61 + reset-names: 62 + items: 63 + - const: stmmaceth 64 + 65 + rx-internal-delay-ps: 66 + enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400] 67 + 68 + tx-internal-delay-ps: 69 + enum: [0, 200, 600, 1200, 1600, 1800, 2000, 2200, 2400] 70 + 71 + eswin,hsp-sp-csr: 72 + $ref: /schemas/types.yaml#/definitions/phandle-array 73 + items: 74 + - description: Phandle to HSP(High-Speed Peripheral) device 75 + - description: Offset of phy control register for internal 76 + or external clock selection 77 + - description: Offset of AXI clock controller Low-Power request 78 + register 79 + - description: Offset of register controlling TX/RX clock delay 80 + description: | 81 + High-Speed Peripheral device needed to configure clock selection, 82 + clock low-power mode and clock delay. 83 + 84 + required: 85 + - compatible 86 + - reg 87 + - clocks 88 + - clock-names 89 + - interrupts 90 + - interrupt-names 91 + - phy-mode 92 + - resets 93 + - reset-names 94 + - rx-internal-delay-ps 95 + - tx-internal-delay-ps 96 + - eswin,hsp-sp-csr 97 + 98 + unevaluatedProperties: false 99 + 100 + examples: 101 + - | 102 + ethernet@50400000 { 103 + compatible = "eswin,eic7700-qos-eth", "snps,dwmac-5.20"; 104 + reg = <0x50400000 0x10000>; 105 + clocks = <&d0_clock 186>, <&d0_clock 171>, <&d0_clock 40>, 106 + <&d0_clock 193>; 107 + clock-names = "axi", "cfg", "stmmaceth", "tx"; 108 + interrupt-parent = <&plic>; 109 + interrupts = <61>; 110 + interrupt-names = "macirq"; 111 + phy-mode = "rgmii-id"; 112 + phy-handle = <&phy0>; 113 + resets = <&reset 95>; 114 + reset-names = "stmmaceth"; 115 + rx-internal-delay-ps = <200>; 116 + tx-internal-delay-ps = <200>; 117 + eswin,hsp-sp-csr = <&hsp_sp_csr 0x100 0x108 0x118>; 118 + snps,axi-config = <&stmmac_axi_setup>; 119 + snps,aal; 120 + snps,fixed-burst; 121 + snps,tso; 122 + stmmac_axi_setup: stmmac-axi-config { 123 + snps,blen = <0 0 0 0 16 8 4>; 124 + snps,rd_osr_lmt = <2>; 125 + snps,wr_osr_lmt = <2>; 126 + }; 127 + };
+9
drivers/net/ethernet/stmicro/stmmac/Kconfig
··· 67 67 68 68 This selects the Anarion SoC glue layer support for the stmmac driver. 69 69 70 + config DWMAC_EIC7700 71 + tristate "Support for Eswin eic7700 ethernet driver" 72 + depends on OF && HAS_DMA && ARCH_ESWIN || COMPILE_TEST 73 + help 74 + This driver supports the Eswin EIC7700 Ethernet controller, 75 + which integrates Synopsys DesignWare QoS features. It enables 76 + high-speed networking with DMA acceleration and is optimized 77 + for embedded systems. 78 + 70 79 config DWMAC_INGENIC 71 80 tristate "Ingenic MAC support" 72 81 default MACH_INGENIC
+1
drivers/net/ethernet/stmicro/stmmac/Makefile
··· 14 14 # Ordering matters. Generic driver must be last. 15 15 obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o 16 16 obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o 17 + obj-$(CONFIG_DWMAC_EIC7700) += dwmac-eic7700.o 17 18 obj-$(CONFIG_DWMAC_INGENIC) += dwmac-ingenic.o 18 19 obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o 19 20 obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
+235
drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Eswin DWC Ethernet linux driver 4 + * 5 + * Copyright 2025, Beijing ESWIN Computing Technology Co., Ltd. 6 + * 7 + * Authors: 8 + * Zhi Li <lizhi2@eswincomputing.com> 9 + * Shuang Liang <liangshuang@eswincomputing.com> 10 + * Shangjuan Wei <weishangjuan@eswincomputing.com> 11 + */ 12 + 13 + #include <linux/platform_device.h> 14 + #include <linux/mfd/syscon.h> 15 + #include <linux/pm_runtime.h> 16 + #include <linux/stmmac.h> 17 + #include <linux/regmap.h> 18 + #include <linux/of.h> 19 + 20 + #include "stmmac_platform.h" 21 + 22 + /* eth_phy_ctrl_offset eth0:0x100 */ 23 + #define EIC7700_ETH_TX_CLK_SEL BIT(16) 24 + #define EIC7700_ETH_PHY_INTF_SELI BIT(0) 25 + 26 + /* eth_axi_lp_ctrl_offset eth0:0x108 */ 27 + #define EIC7700_ETH_CSYSREQ_VAL BIT(0) 28 + 29 + /* 30 + * TX/RX Clock Delay Bit Masks: 31 + * - TX Delay: bits [14:8] — TX_CLK delay (unit: 0.1ns per bit) 32 + * - RX Delay: bits [30:24] — RX_CLK delay (unit: 0.1ns per bit) 33 + */ 34 + #define EIC7700_ETH_TX_ADJ_DELAY GENMASK(14, 8) 35 + #define EIC7700_ETH_RX_ADJ_DELAY GENMASK(30, 24) 36 + 37 + #define EIC7700_MAX_DELAY_UNIT 0x7F 38 + 39 + static const char * const eic7700_clk_names[] = { 40 + "tx", "axi", "cfg", 41 + }; 42 + 43 + struct eic7700_qos_priv { 44 + struct plat_stmmacenet_data *plat_dat; 45 + }; 46 + 47 + static int eic7700_clks_config(void *priv, bool enabled) 48 + { 49 + struct eic7700_qos_priv *dwc = (struct eic7700_qos_priv *)priv; 50 + struct plat_stmmacenet_data *plat = dwc->plat_dat; 51 + int ret = 0; 52 + 53 + if (enabled) 54 + ret = clk_bulk_prepare_enable(plat->num_clks, plat->clks); 55 + else 56 + clk_bulk_disable_unprepare(plat->num_clks, plat->clks); 57 + 58 + return ret; 59 + } 60 + 61 + static int eic7700_dwmac_init(struct platform_device *pdev, void *priv) 62 + { 63 + struct eic7700_qos_priv *dwc = priv; 64 + 65 + return eic7700_clks_config(dwc, true); 66 + } 67 + 68 + static void eic7700_dwmac_exit(struct platform_device *pdev, void *priv) 69 + { 70 + struct eic7700_qos_priv *dwc = priv; 71 + 72 + eic7700_clks_config(dwc, false); 73 + } 74 + 75 + static int eic7700_dwmac_suspend(struct device *dev, void *priv) 76 + { 77 + return pm_runtime_force_suspend(dev); 78 + } 79 + 80 + static int eic7700_dwmac_resume(struct device *dev, void *priv) 81 + { 82 + int ret; 83 + 84 + ret = pm_runtime_force_resume(dev); 85 + if (ret) 86 + dev_err(dev, "%s failed: %d\n", __func__, ret); 87 + 88 + return ret; 89 + } 90 + 91 + static int eic7700_dwmac_probe(struct platform_device *pdev) 92 + { 93 + struct plat_stmmacenet_data *plat_dat; 94 + struct stmmac_resources stmmac_res; 95 + struct eic7700_qos_priv *dwc_priv; 96 + struct regmap *eic7700_hsp_regmap; 97 + u32 eth_axi_lp_ctrl_offset; 98 + u32 eth_phy_ctrl_offset; 99 + u32 eth_phy_ctrl_regset; 100 + u32 eth_rxd_dly_offset; 101 + u32 eth_dly_param = 0; 102 + u32 delay_ps; 103 + int i, ret; 104 + 105 + ret = stmmac_get_platform_resources(pdev, &stmmac_res); 106 + if (ret) 107 + return dev_err_probe(&pdev->dev, ret, 108 + "failed to get resources\n"); 109 + 110 + plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); 111 + if (IS_ERR(plat_dat)) 112 + return dev_err_probe(&pdev->dev, PTR_ERR(plat_dat), 113 + "dt configuration failed\n"); 114 + 115 + dwc_priv = devm_kzalloc(&pdev->dev, sizeof(*dwc_priv), GFP_KERNEL); 116 + if (!dwc_priv) 117 + return -ENOMEM; 118 + 119 + /* Read rx-internal-delay-ps and update rx_clk delay */ 120 + if (!of_property_read_u32(pdev->dev.of_node, 121 + "rx-internal-delay-ps", &delay_ps)) { 122 + u32 val = min(delay_ps / 100, EIC7700_MAX_DELAY_UNIT); 123 + 124 + eth_dly_param &= ~EIC7700_ETH_RX_ADJ_DELAY; 125 + eth_dly_param |= FIELD_PREP(EIC7700_ETH_RX_ADJ_DELAY, val); 126 + } else { 127 + return dev_err_probe(&pdev->dev, -EINVAL, 128 + "missing required property rx-internal-delay-ps\n"); 129 + } 130 + 131 + /* Read tx-internal-delay-ps and update tx_clk delay */ 132 + if (!of_property_read_u32(pdev->dev.of_node, 133 + "tx-internal-delay-ps", &delay_ps)) { 134 + u32 val = min(delay_ps / 100, EIC7700_MAX_DELAY_UNIT); 135 + 136 + eth_dly_param &= ~EIC7700_ETH_TX_ADJ_DELAY; 137 + eth_dly_param |= FIELD_PREP(EIC7700_ETH_TX_ADJ_DELAY, val); 138 + } else { 139 + return dev_err_probe(&pdev->dev, -EINVAL, 140 + "missing required property tx-internal-delay-ps\n"); 141 + } 142 + 143 + eic7700_hsp_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 144 + "eswin,hsp-sp-csr"); 145 + if (IS_ERR(eic7700_hsp_regmap)) 146 + return dev_err_probe(&pdev->dev, 147 + PTR_ERR(eic7700_hsp_regmap), 148 + "Failed to get hsp-sp-csr regmap\n"); 149 + 150 + ret = of_property_read_u32_index(pdev->dev.of_node, 151 + "eswin,hsp-sp-csr", 152 + 1, &eth_phy_ctrl_offset); 153 + if (ret) 154 + return dev_err_probe(&pdev->dev, ret, 155 + "can't get eth_phy_ctrl_offset\n"); 156 + 157 + regmap_read(eic7700_hsp_regmap, eth_phy_ctrl_offset, 158 + &eth_phy_ctrl_regset); 159 + eth_phy_ctrl_regset |= 160 + (EIC7700_ETH_TX_CLK_SEL | EIC7700_ETH_PHY_INTF_SELI); 161 + regmap_write(eic7700_hsp_regmap, eth_phy_ctrl_offset, 162 + eth_phy_ctrl_regset); 163 + 164 + ret = of_property_read_u32_index(pdev->dev.of_node, 165 + "eswin,hsp-sp-csr", 166 + 2, &eth_axi_lp_ctrl_offset); 167 + if (ret) 168 + return dev_err_probe(&pdev->dev, ret, 169 + "can't get eth_axi_lp_ctrl_offset\n"); 170 + 171 + regmap_write(eic7700_hsp_regmap, eth_axi_lp_ctrl_offset, 172 + EIC7700_ETH_CSYSREQ_VAL); 173 + 174 + ret = of_property_read_u32_index(pdev->dev.of_node, 175 + "eswin,hsp-sp-csr", 176 + 3, &eth_rxd_dly_offset); 177 + if (ret) 178 + return dev_err_probe(&pdev->dev, ret, 179 + "can't get eth_rxd_dly_offset\n"); 180 + 181 + regmap_write(eic7700_hsp_regmap, eth_rxd_dly_offset, 182 + eth_dly_param); 183 + 184 + plat_dat->num_clks = ARRAY_SIZE(eic7700_clk_names); 185 + plat_dat->clks = devm_kcalloc(&pdev->dev, 186 + plat_dat->num_clks, 187 + sizeof(*plat_dat->clks), 188 + GFP_KERNEL); 189 + if (!plat_dat->clks) 190 + return -ENOMEM; 191 + 192 + for (i = 0; i < ARRAY_SIZE(eic7700_clk_names); i++) 193 + plat_dat->clks[i].id = eic7700_clk_names[i]; 194 + 195 + ret = devm_clk_bulk_get_optional(&pdev->dev, 196 + plat_dat->num_clks, 197 + plat_dat->clks); 198 + if (ret) 199 + return dev_err_probe(&pdev->dev, ret, 200 + "Failed to get clocks\n"); 201 + 202 + plat_dat->clk_tx_i = stmmac_pltfr_find_clk(plat_dat, "tx"); 203 + plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate; 204 + plat_dat->clks_config = eic7700_clks_config; 205 + plat_dat->bsp_priv = dwc_priv; 206 + dwc_priv->plat_dat = plat_dat; 207 + plat_dat->init = eic7700_dwmac_init; 208 + plat_dat->exit = eic7700_dwmac_exit; 209 + plat_dat->suspend = eic7700_dwmac_suspend; 210 + plat_dat->resume = eic7700_dwmac_resume; 211 + 212 + return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); 213 + } 214 + 215 + static const struct of_device_id eic7700_dwmac_match[] = { 216 + { .compatible = "eswin,eic7700-qos-eth" }, 217 + { } 218 + }; 219 + MODULE_DEVICE_TABLE(of, eic7700_dwmac_match); 220 + 221 + static struct platform_driver eic7700_dwmac_driver = { 222 + .probe = eic7700_dwmac_probe, 223 + .driver = { 224 + .name = "eic7700-eth-dwmac", 225 + .pm = &stmmac_pltfr_pm_ops, 226 + .of_match_table = eic7700_dwmac_match, 227 + }, 228 + }; 229 + module_platform_driver(eic7700_dwmac_driver); 230 + 231 + MODULE_AUTHOR("Zhi Li <lizhi2@eswincomputing.com>"); 232 + MODULE_AUTHOR("Shuang Liang <liangshuang@eswincomputing.com>"); 233 + MODULE_AUTHOR("Shangjuan Wei <weishangjuan@eswincomputing.com>"); 234 + MODULE_DESCRIPTION("Eswin eic7700 qos ethernet driver"); 235 + MODULE_LICENSE("GPL");