From 32519cb1ea57f0d3db9e06fb5208fbd59fac685a Mon Sep 17 00:00:00 2001 From: weishangjuan Date: Thu, 8 May 2025 16:10:24 +0800 Subject: [PATCH 1/5] DT binding for the Eswin eic7700 eth driver Adds Device Tree binding documentation for the ESWIN EIC7700 reset controller module. This files describe the required properties, compatible strings and usage examples for integrating this hardware block into device tree configurations. Co-developed-by: Shuang Liang Signed-off-by: Shuang Liang Signed-off-by: Shangjuan Wei --- .../bindings/net/eswin,eic7700-eth.yaml | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml new file mode 100644 index 0000000000000..3cdb277cb9c5c --- /dev/null +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml @@ -0,0 +1,145 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/eswin,eic7700-eth.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Eswin EIC7700 SOC Eth Controller + +maintainers: + - weishangjuan + +description: | + The eth controller registers are part of the syscrg block on + the EIC7700 SoC. + +properties: + compatible: + const: eswin,eic7700-qos-eth + + reg: + minItems: 1 + items: + - description: Base address and size + - description: Extension region (optional) + + numa-node-id: + $ref: /schemas/types.yaml#/definitions/uint32 + + interrupt-names: + const: macirq + + interrupts: + maxItems: 1 + + phy-mode: + $ref: /schemas/types.yaml#/definitions/string + enum: [mii, gmii, rgmii, rmii, sgmii] + + id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Controller instance ID + + clocks: + minItems: 3 + maxItems: 7 + + clock-names: + minItems: 3 + items: + - const: app + - const: stmmaceth + - const: tx + - const: slave_bus + - const: master_bus + - const: ptp_ref + - const: phy_ref_clk + + resets: + maxItems: 1 + + reset-names: + items: + - const: ethrst + + dma-noncoherent: true + + # Custom properties + eswin,hsp_sp_csr: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: HSP SP control registers + + eswin,syscrg_csr: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: System clock registers + + eswin,dly_hsp_reg: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: HSP delay control registers + + snps,axi-config: + $ref: /schemas/types.yaml#/definitions/phandle + description: AXI bus configuration + + stmmac-axi-config: + type: object + unevaluatedProperties: false + properties: + snps,lpi_en: + type: boolean + # $ref: /schemas/types.yaml#/definitions/flag + description: Low Power Interface enable flag (true/false) + +required: + - compatible + - reg + - numa-node-id + - interrupt-names + - interrupts + - phy-mode + - id + - clocks + - clock-names + - resets + - reset-names + - eswin,hsp_sp_csr + - eswin,syscrg_csr + - eswin,dly_hsp_reg + - snps,axi-config + - snps,blen + - snps,rd_osr_lmt + - snps,wr_osr_lmt + - snps,lpi_en + +additionalProperties: false + +examples: + - | + d0_gmac0: ethernet@50400000 { + compatible = "eswin,eic7700-qos-eth"; + reg = <0x0 0x50400000 0x0 0x10000>; + interrupt-parent = <&plic0>; + interrupt-names = "macirq"; + interrupts = <61>; + phy-mode = "rgmii"; + numa-node-id = <0>; + id = <0>; + status = "disabled"; + clocks = <&d0_clock 550>, + <&d0_clock 551>, + <&d0_clock 552>; + clock-names = "app", "stmmaceth", "tx"; + resets = <&d0_reset 0x07 (1 << 26)>; + reset-names = "ethrst"; + dma-noncoherent; + eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1030 0x100 0x108>; + eswin,syscrg_csr = <&d0_sys_crg 0x148 0x14c>; + eswin,dly_hsp_reg = <0x114 0x118 0x11c>; + snps,axi-config = <&d0_stmmac_axi_setup>; + d0_stmmac_axi_setup: stmmac-axi-config { + snps,blen = <0 0 0 0 16 8 4>; + snps,rd_osr_lmt = <2>; + snps,wr_osr_lmt = <2>; + snps,lpi_en; + }; + }; From 6aec33b14b76e6719f5b0e6236b82b452ca5b60a Mon Sep 17 00:00:00 2001 From: weishangjuan Date: Thu, 8 May 2025 16:23:55 +0800 Subject: [PATCH 2/5] eth driver for the Eswin eic7700 Soc Add Ethernet controller support for Eswin's eic7700 SoC. The driver provides management and control of Ethernet signals for the eiC7700 series chips. Co-developed-by: Shuang Liang Signed-off-by: Shuang Liang Signed-off-by: Shangjuan Wei --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../ethernet/stmicro/stmmac/dwmac-eic7700.c | 535 ++++++++++++++++++ 3 files changed, 547 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 3c820ef567759..e75a0acd500a5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -66,6 +66,17 @@ config DWMAC_ANARION This selects the Anarion SoC glue layer support for the stmmac driver. +config DWMAC_EIC7700 + tristate "Support for Eswin eic7700 ethernet driver" + select CRC32 + select MII + depends on OF && HAS_DMA && ARCH_ESWIN + help + This driver supports the Eswin EIC7700 Ethernet controller, + which integrates Synopsys DesignWare QoS features. It enables + high-speed networking with DMA acceleration and is optimized + for embedded systems. + config DWMAC_INGENIC tristate "Ingenic MAC support" default MACH_INGENIC diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 594883fb41644..c9279bafdbb19 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -14,6 +14,7 @@ stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o # Ordering matters. Generic driver must be last. obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o +obj-$(CONFIG_DWMAC_EIC7700) += dwmac-eic7700.o obj-$(CONFIG_DWMAC_INGENIC) += dwmac-ingenic.o obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c new file mode 100644 index 0000000000000..f370e20225063 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Eswin DWC Ethernet linux driver + * + * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authors: Shuang Liang + * Shangjuan Wei + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stmmac_platform.h" +#include "dwmac4.h" +#include +#include +#include +#include + +/* eth_phy_ctrl_offset eth0:0x100; eth1:0x200 */ +#define ETH_TX_CLK_SEL BIT(16) +#define ETH_PHY_INTF_SELI BIT(0) + +/* eth_axi_lp_ctrl_offset eth0:0x108; eth1:0x208 */ +#define ETH_CSYSREQ_VAL BIT(0) + +/* hsp_aclk_ctrl_offset (0x148) */ +#define HSP_ACLK_CLKEN BIT(31) +#define HSP_ACLK_DIVSOR (0x2 << 4) + +/* hsp_cfg_ctrl_offset (0x14c) */ +#define HSP_CFG_CLKEN BIT(31) +#define SCU_HSP_PCLK_EN BIT(30) +#define HSP_CFG_CTRL_REGSET (HSP_CFG_CLKEN | SCU_HSP_PCLK_EN) + +/* RTL8211F PHY Configurations for LEDs */ +#define PHY_ADDR 0 +#define PHY_PAGE_SWITCH_REG 31 +#define PHY_LED_CFG_REG 16 +#define PHY_LED_PAGE_CFG 0xd04 + +struct dwc_qos_priv { + struct device *dev; + int dev_id; + struct regmap *crg_regmap; + struct regmap *hsp_regmap; + struct reset_control *rst; + struct clk *clk_app; + struct clk *clk_tx; + struct gpio_desc *phy_reset; + struct stmmac_priv *stmpriv; + int phyled_cfgs[3]; + int phyaddr; + unsigned int dly_hsp_reg[3]; + unsigned int dly_param_1000m[3]; + unsigned int dly_param_100m[3]; + unsigned int dly_param_10m[3]; +}; + +static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat) +{ + struct device *dev = &pdev->dev; + u32 burst_map = 0; + u32 bit_index = 0; + u32 a_index = 0; + + if (!plat_dat->axi) { + plat_dat->axi = kzalloc(sizeof(*plat_dat->axi), GFP_KERNEL); + + if (!plat_dat->axi) + return -ENOMEM; + } + + plat_dat->axi->axi_lpi_en = device_property_read_bool(dev, + "snps,en-lpi"); + if (device_property_read_u32(dev, "snps,write-requests", + &plat_dat->axi->axi_wr_osr_lmt)) { + /** + * Since the register has a reset value of 1, if property + * is missing, default to 1. + */ + plat_dat->axi->axi_wr_osr_lmt = 1; + } else { + /** + * If property exists, to keep the behavior from dwc_eth_qos, + * subtract one after parsing. + */ + plat_dat->axi->axi_wr_osr_lmt--; + } + + if (device_property_read_u32(dev, "snps,read-requests", + &plat_dat->axi->axi_rd_osr_lmt)) { + /** + * Since the register has a reset value of 1, if property + * is missing, default to 1. + */ + plat_dat->axi->axi_rd_osr_lmt = 1; + } else { + /** + * If property exists, to keep the behavior from dwc_eth_qos, + * subtract one after parsing. + */ + plat_dat->axi->axi_rd_osr_lmt--; + } + device_property_read_u32(dev, "snps,burst-map", &burst_map); + + /* converts burst-map bitmask to burst array */ + for (bit_index = 0; bit_index < 7; bit_index++) { + if (burst_map & (1 << bit_index)) { + switch (bit_index) { + case 0: + plat_dat->axi->axi_blen[a_index] = 4; break; + case 1: + plat_dat->axi->axi_blen[a_index] = 8; break; + case 2: + plat_dat->axi->axi_blen[a_index] = 16; break; + case 3: + plat_dat->axi->axi_blen[a_index] = 32; break; + case 4: + plat_dat->axi->axi_blen[a_index] = 64; break; + case 5: + plat_dat->axi->axi_blen[a_index] = 128; break; + case 6: + plat_dat->axi->axi_blen[a_index] = 256; break; + default: + break; + } + a_index++; + } + } + + /* dwc-qos needs GMAC4, AAL, TSO and PMT */ + plat_dat->has_gmac4 = 1; + plat_dat->dma_cfg->aal = 1; + plat_dat->flags |= STMMAC_FLAG_TSO_EN; + plat_dat->pmt = 1; + + return 0; +} + +static void dwc_qos_fix_speed(void *priv, int speed, unsigned int mode) +{ + unsigned long rate = 125000000; + int i, err, data = 0; + struct dwc_qos_priv *dwc_priv = (struct dwc_qos_priv *)priv; + + switch (speed) { + case SPEED_1000: + rate = 125000000; + + for (i = 0; i < 3; i++) + regmap_write(dwc_priv->hsp_regmap, + dwc_priv->dly_hsp_reg[i], + dwc_priv->dly_param_1000m[i]); + + if (dwc_priv->stmpriv) { + data = mdiobus_read(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG, PHY_LED_PAGE_CFG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_LED_CFG_REG, dwc_priv->phyled_cfgs[0]); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG, data); + } + + break; + case SPEED_100: + rate = 25000000; + + for (i = 0; i < 3; i++) { + regmap_write(dwc_priv->hsp_regmap, + dwc_priv->dly_hsp_reg[i], + dwc_priv->dly_param_100m[i]); + } + + if (dwc_priv->stmpriv) { + data = mdiobus_read(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG, PHY_LED_PAGE_CFG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_LED_CFG_REG, dwc_priv->phyled_cfgs[1]); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG, data); + } + + break; + case SPEED_10: + rate = 2500000; + + for (i = 0; i < 3; i++) { + regmap_write(dwc_priv->hsp_regmap, + dwc_priv->dly_hsp_reg[i], + dwc_priv->dly_param_10m[i]); + } + + if (dwc_priv->stmpriv) { + data = mdiobus_read(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG, PHY_LED_PAGE_CFG); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_LED_CFG_REG, dwc_priv->phyled_cfgs[2]); + mdiobus_write(dwc_priv->stmpriv->mii, PHY_ADDR, + PHY_PAGE_SWITCH_REG, data); + } + + break; + default: + dev_err(dwc_priv->dev, "invalid speed %u\n", speed); + break; + } + + err = clk_set_rate(dwc_priv->clk_tx, rate); + if (err < 0) + dev_err(dwc_priv->dev, "failed to set TX rate: %d\n", err); +} + +static int dwc_qos_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat, + struct stmmac_resources *stmmac_res) +{ + struct dwc_qos_priv *dwc_priv; + int ret; + int err; + u32 hsp_aclk_ctrl_offset; + u32 hsp_aclk_ctrl_regset; + u32 hsp_cfg_ctrl_offset; + u32 eth_axi_lp_ctrl_offset; + u32 eth_phy_ctrl_offset; + u32 eth_phy_ctrl_regset; + + dwc_priv = devm_kzalloc(&pdev->dev, sizeof(*dwc_priv), GFP_KERNEL); + if (!dwc_priv) + return -ENOMEM; + + if (device_property_read_u32(&pdev->dev, "id", &dwc_priv->dev_id)) { + dev_err(&pdev->dev, "Can not read device id!\n"); + return -EINVAL; + } + + dwc_priv->dev = &pdev->dev; + dwc_priv->phy_reset = devm_gpiod_get(&pdev->dev, "rst", GPIOD_OUT_LOW); + if (IS_ERR(dwc_priv->phy_reset)) { + dev_err(&pdev->dev, "Reset gpio not specified\n"); + return -EINVAL; + } + + gpiod_set_value(dwc_priv->phy_reset, 0); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 0, + &dwc_priv->phyled_cfgs[0]); + if (ret) + dev_warn(&pdev->dev, "can't get phyaddr (%d)\n", ret); + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 0, + &dwc_priv->phyled_cfgs[0]); + if (ret) + dev_warn(&pdev->dev, "can't get led cfgs for 1Gbps mode (%d)\n", ret); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 1, + &dwc_priv->phyled_cfgs[1]); + if (ret) + dev_warn(&pdev->dev, "can't get led cfgs for 100Mbps mode (%d)\n", ret); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,led-cfgs", 2, + &dwc_priv->phyled_cfgs[2]); + if (ret) + dev_warn(&pdev->dev, "can't get led cfgs for 10Mbps mode (%d)\n", ret); + + ret = of_property_read_variable_u32_array(pdev->dev.of_node, "eswin,dly_hsp_reg", + &dwc_priv->dly_hsp_reg[0], 3, 0); + if (ret != 3) { + dev_err(&pdev->dev, "can't get delay hsp reg.ret(%d)\n", ret); + return ret; + } + + ret = of_property_read_variable_u32_array(pdev->dev.of_node, "dly-param-1000m", + &dwc_priv->dly_param_1000m[0], 3, 0); + if (ret != 3) { + dev_err(&pdev->dev, "can't get delay param for 1Gbps mode (%d)\n", ret); + return ret; + } + + ret = of_property_read_variable_u32_array(pdev->dev.of_node, "dly-param-100m", + &dwc_priv->dly_param_100m[0], 3, 0); + if (ret != 3) { + dev_err(&pdev->dev, "can't get delay param for 100Mbps mode (%d)\n", ret); + return ret; + } + + ret = of_property_read_variable_u32_array(pdev->dev.of_node, "dly-param-10m", + &dwc_priv->dly_param_10m[0], 3, 0); + if (ret != 3) { + dev_err(&pdev->dev, "can't get delay param for 10Mbps mode (%d)\n", ret); + return ret; + } + + dwc_priv->crg_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "eswin,syscrg_csr"); + if (IS_ERR(dwc_priv->crg_regmap)) { + dev_dbg(&pdev->dev, "No syscrg_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,syscrg_csr", 1, + &hsp_aclk_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get hsp_aclk_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_read(dwc_priv->crg_regmap, hsp_aclk_ctrl_offset, &hsp_aclk_ctrl_regset); + hsp_aclk_ctrl_regset |= (HSP_ACLK_CLKEN | HSP_ACLK_DIVSOR); + regmap_write(dwc_priv->crg_regmap, hsp_aclk_ctrl_offset, hsp_aclk_ctrl_regset); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,syscrg_csr", 2, + &hsp_cfg_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get hsp_cfg_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_write(dwc_priv->crg_regmap, hsp_cfg_ctrl_offset, HSP_CFG_CTRL_REGSET); + + dwc_priv->hsp_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "eswin,hsp_sp_csr"); + if (IS_ERR(dwc_priv->hsp_regmap)) { + dev_dbg(&pdev->dev, "No hsp_sp_csr phandle specified\n"); + return 0; + } + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,hsp_sp_csr", 2, + ð_phy_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get eth_phy_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_read(dwc_priv->hsp_regmap, eth_phy_ctrl_offset, ð_phy_ctrl_regset); + eth_phy_ctrl_regset |= (ETH_TX_CLK_SEL | ETH_PHY_INTF_SELI); + regmap_write(dwc_priv->hsp_regmap, eth_phy_ctrl_offset, eth_phy_ctrl_regset); + + ret = of_property_read_u32_index(pdev->dev.of_node, "eswin,hsp_sp_csr", 3, + ð_axi_lp_ctrl_offset); + if (ret) { + dev_err(&pdev->dev, "can't get eth_axi_lp_ctrl_offset (%d)\n", ret); + return ret; + } + regmap_write(dwc_priv->hsp_regmap, eth_axi_lp_ctrl_offset, ETH_CSYSREQ_VAL); + + dwc_priv->clk_app = devm_clk_get(&pdev->dev, "app"); + if (IS_ERR(dwc_priv->clk_app)) { + dev_err(&pdev->dev, "app clock not found.\n"); + return PTR_ERR(dwc_priv->clk_app); + } + + err = clk_prepare_enable(dwc_priv->clk_app); + if (err < 0) { + dev_err(&pdev->dev, "failed to enable app clock: %d\n", + err); + return err; + } + + dwc_priv->clk_tx = devm_clk_get(&pdev->dev, "tx"); + if (IS_ERR(plat_dat->pclk)) { + dev_err(&pdev->dev, "tx clock not found.\n"); + return PTR_ERR(dwc_priv->clk_tx); + } + + err = clk_prepare_enable(dwc_priv->clk_tx); + if (err < 0) { + dev_err(&pdev->dev, "failed to enable tx clock: %d\n", err); + return err; + } + dwc_priv->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "ethrst"); + if (IS_ERR(dwc_priv->rst)) + return PTR_ERR(dwc_priv->rst); + + ret = reset_control_assert(dwc_priv->rst); + WARN_ON(ret != 0); + ret = reset_control_deassert(dwc_priv->rst); + WARN_ON(ret != 0); + + plat_dat->fix_mac_speed = dwc_qos_fix_speed; + plat_dat->bsp_priv = dwc_priv; + plat_dat->phy_addr = PHY_ADDR; + + return 0; +} + +static int dwc_qos_remove(struct platform_device *pdev) +{ + struct dwc_qos_priv *dwc_priv = get_stmmac_bsp_priv(&pdev->dev); + + reset_control_assert(dwc_priv->rst); + clk_disable_unprepare(dwc_priv->clk_tx); + clk_disable_unprepare(dwc_priv->clk_app); + + devm_gpiod_put(&pdev->dev, dwc_priv->phy_reset); + + return 0; +} + +struct dwc_eth_dwmac_data { + int (*probe)(struct platform_device *pdev, + struct plat_stmmacenet_data *data, + struct stmmac_resources *res); + int (*remove)(struct platform_device *pdev); +}; + +static const struct dwc_eth_dwmac_data dwc_qos_data = { + .probe = dwc_qos_probe, + .remove = dwc_qos_remove, +}; + +static int dwc_eth_dwmac_probe(struct platform_device *pdev) +{ + const struct dwc_eth_dwmac_data *data; + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct net_device *ndev = NULL; + struct stmmac_priv *stmpriv = NULL; + struct dwc_qos_priv *dwc_priv = NULL; + int ret; + + data = device_get_match_data(&pdev->dev); + + memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); + + /** + * Since stmmac_platform supports name IRQ only, basic platform + * resource initialization is done in the glue logic. + */ + stmmac_res.irq = platform_get_irq(pdev, 0); + if (stmmac_res.irq < 0) + return stmmac_res.irq; + stmmac_res.wol_irq = stmmac_res.irq; + stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(stmmac_res.addr)) + return PTR_ERR(stmmac_res.addr); + + plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) + return PTR_ERR(plat_dat); + + ret = data->probe(pdev, plat_dat, &stmmac_res); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to probe subdriver: %d\n", + ret); + + return ret; + } + + ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); + if (ret) + goto remove; + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto remove; + + ndev = dev_get_drvdata(&pdev->dev); + stmpriv = netdev_priv(ndev); + dwc_priv = (struct dwc_qos_priv *)plat_dat->bsp_priv; + dwc_priv->stmpriv = stmpriv; + + return ret; + +remove: + data->remove(pdev); + + return ret; +} + +static void dwc_eth_dwmac_remove(struct platform_device *pdev) +{ + const struct dwc_eth_dwmac_data *data; + int err; + + data = device_get_match_data(&pdev->dev); + + stmmac_dvr_remove(&pdev->dev); + + err = data->remove(pdev); + if (err < 0) + dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err); +} + +static const struct of_device_id dwc_eth_dwmac_match[] = { + { .compatible = "eswin,eic7700-qos-eth", .data = &dwc_qos_data }, + { } +}; +MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); + +static struct platform_driver eic7700_eth_dwmac_driver = { + .probe = dwc_eth_dwmac_probe, + .remove = dwc_eth_dwmac_remove, + .driver = { + .name = "eic7700-eth-dwmac", + .pm = &stmmac_pltfr_pm_ops, + .of_match_table = dwc_eth_dwmac_match, + }, +}; +module_platform_driver(eic7700_eth_dwmac_driver); + +MODULE_AUTHOR("Eswin"); +MODULE_AUTHOR("Shuang Liang "); +MODULE_AUTHOR("Shangjuan Wei "); +MODULE_DESCRIPTION("Eswin eic7700 qos ethernet driver"); +MODULE_LICENSE("GPL"); From 9da9e03dcf977b53396522b0a610625e904cf4a8 Mon Sep 17 00:00:00 2001 From: weishangjuan Date: Tue, 13 May 2025 14:32:16 +0800 Subject: [PATCH 3/5] remove comments from driver code and modify yaml Add Ethernet controller support for Eswin's eic7700 SoC. The driver provides management and control of Ethernet signals for the eiC7700 series chips. Co-developed-by: Shuang Liang Signed-off-by: Shuang Liang Signed-off-by: Shangjuan Wei --- .../bindings/net/eswin,eic7700-eth.yaml | 28 +++++++++---------- drivers/net/ethernet/stmicro/stmmac/Kconfig | 2 +- .../ethernet/stmicro/stmmac/dwmac-eic7700.c | 14 ---------- 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml index 3cdb277cb9c5c..b38683907e52c 100644 --- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml @@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Eswin EIC7700 SOC Eth Controller maintainers: - - weishangjuan + - Shangjuan Wei + - Shuang Liang description: | The eth controller registers are part of the syscrg block on @@ -23,9 +24,6 @@ properties: - description: Base address and size - description: Extension region (optional) - numa-node-id: - $ref: /schemas/types.yaml#/definitions/uint32 - interrupt-names: const: macirq @@ -87,7 +85,7 @@ properties: properties: snps,lpi_en: type: boolean - # $ref: /schemas/types.yaml#/definitions/flag + $ref: /schemas/types.yaml#/definitions/flag description: Low Power Interface enable flag (true/false) required: @@ -115,28 +113,28 @@ additionalProperties: false examples: - | - d0_gmac0: ethernet@50400000 { + gmac0: ethernet@50400000 { compatible = "eswin,eic7700-qos-eth"; reg = <0x0 0x50400000 0x0 0x10000>; - interrupt-parent = <&plic0>; + interrupt-parent = <&plic>; interrupt-names = "macirq"; interrupts = <61>; phy-mode = "rgmii"; numa-node-id = <0>; id = <0>; status = "disabled"; - clocks = <&d0_clock 550>, - <&d0_clock 551>, - <&d0_clock 552>; + clocks = <&clock 550>, + <&clock 551>, + <&clock 552>; clock-names = "app", "stmmaceth", "tx"; - resets = <&d0_reset 0x07 (1 << 26)>; + resets = <&reset 0x07 (1 << 26)>; reset-names = "ethrst"; dma-noncoherent; - eswin,hsp_sp_csr = <&d0_hsp_sp_csr 0x1030 0x100 0x108>; - eswin,syscrg_csr = <&d0_sys_crg 0x148 0x14c>; + eswin,hsp_sp_csr = <&hsp_sp_csr 0x1030 0x100 0x108>; + eswin,syscrg_csr = <&sys_crg 0x148 0x14c>; eswin,dly_hsp_reg = <0x114 0x118 0x11c>; - snps,axi-config = <&d0_stmmac_axi_setup>; - d0_stmmac_axi_setup: stmmac-axi-config { + snps,axi-config = <&stmmac_axi_setup>; + stmmac_axi_setup: stmmac-axi-config { snps,blen = <0 0 0 0 16 8 4>; snps,rd_osr_lmt = <2>; snps,wr_osr_lmt = <2>; diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index e75a0acd500a5..6a3970c92db73 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -70,7 +70,7 @@ config DWMAC_EIC7700 tristate "Support for Eswin eic7700 ethernet driver" select CRC32 select MII - depends on OF && HAS_DMA && ARCH_ESWIN + depends on OF && HAS_DMA && ARCH_ESWIN || COMPILE_TEST help This driver supports the Eswin EIC7700 Ethernet controller, which integrates Synopsys DesignWare QoS features. It enables diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c index f370e20225063..3483827e5652f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-eic7700.c @@ -2,20 +2,6 @@ /* * Eswin DWC Ethernet linux driver * - * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * * Authors: Shuang Liang * Shangjuan Wei */ From 493751cf63436c51370aec7c1c20ca35192a9b5f Mon Sep 17 00:00:00 2001 From: weishangjuan Date: Wed, 14 May 2025 17:32:44 +0800 Subject: [PATCH 4/5] modify eth yaml --- Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml index b38683907e52c..e835999fe140c 100644 --- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml @@ -7,8 +7,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Eswin EIC7700 SOC Eth Controller maintainers: - - Shangjuan Wei - Shuang Liang + - Zhi Li + - Shangjuan Wei description: | The eth controller registers are part of the syscrg block on From 62b4b91296eec2f3ee86fb2e11f6354454efaea4 Mon Sep 17 00:00:00 2001 From: weishangjuan Date: Thu, 15 May 2025 11:04:16 +0800 Subject: [PATCH 5/5] remove numa-node-id for eth yaml --- Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml index e835999fe140c..6cb9c109c036e 100644 --- a/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml +++ b/Documentation/devicetree/bindings/net/eswin,eic7700-eth.yaml @@ -92,7 +92,6 @@ properties: required: - compatible - reg - - numa-node-id - interrupt-names - interrupts - phy-mode @@ -121,7 +120,6 @@ examples: interrupt-names = "macirq"; interrupts = <61>; phy-mode = "rgmii"; - numa-node-id = <0>; id = <0>; status = "disabled"; clocks = <&clock 550>,