From c9c850326b2e05cc034a3c3add45842f3ffc5232 Mon Sep 17 00:00:00 2001 From: "yanhong.wang" Date: Wed, 24 Aug 2022 18:23:42 +0800 Subject: [PATCH] net: stmmac: Add StarFive dwmac support Remove the gmac driver in dwmac-dwc-qos-eth.c for JH7110 SoC, and add StarFive dwmac driver to replace. Signed-off-by: yanhong.wang --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 ++ drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 143 ------------------- .../ethernet/stmicro/stmmac/dwmac-starfive-plat.c | 151 +++++++++++++++++++++ 4 files changed, 162 insertions(+), 143 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-starfive-plat.c diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 929cfc2..b7e1133 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -232,6 +232,16 @@ config DWMAC_INTEL_PLAT the stmmac device driver. This driver is used for the Intel Keem Bay SoC. +config DWMAC_STARFIVE_PLAT + tristate "StarFive dwmac support" + depends on OF && COMMON_CLK + depends on STMMAC_ETH + help + Support for ethernet controllers on StarFive SoCs + + This selects the StarFive platform specific glue layer support for + the stmmac device driver. This driver is used for StarFive SoCs. + config DWMAC_VISCONTI tristate "Toshiba Visconti DWMAC support" default ARCH_VISCONTI diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index d4e12e9..1df002c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o obj-$(CONFIG_DWMAC_INTEL_PLAT) += dwmac-intel-plat.o +obj-$(CONFIG_DWMAC_STARFIVE_PLAT) += dwmac-starfive-plat.o obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index f8b4246..bc91fd8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -37,14 +37,6 @@ struct tegra_eqos { struct gpio_desc *reset; }; -struct starfive_eqos { - struct device *dev; - void __iomem *regs; - struct clk *clk_tx; - struct clk *clk_gtx; - struct clk *clk_gtxc; -}; - static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, struct plat_stmmacenet_data *plat_dat) { @@ -405,135 +397,6 @@ static int tegra_eqos_remove(struct platform_device *pdev) return 0; } -static void starfive_eqos_fix_speed(void *priv, unsigned int speed) -{ - struct starfive_eqos *eqos = priv; - unsigned long rate; - int err; - - switch (speed) { - case SPEED_1000: - rate = 125000000; - break; - case SPEED_100: - rate = 25000000; - break; - case SPEED_10: - rate = 2500000; - break; - default: - dev_err(eqos->dev, "invalid speed %u\n", speed); - return; - } - - err = clk_set_rate(eqos->clk_gtx, rate); - if (err < 0) - dev_err(eqos->dev, "failed to set tx rate %lu\n", rate); -} - -static int starfive_eqos_probe(struct platform_device *pdev, - struct plat_stmmacenet_data *data, - struct stmmac_resources *res) -{ - struct device *dev = &pdev->dev; - struct starfive_eqos *eqos; - int err; - - /* Get IRQ information early to have an ability to ask for deferred - * probe if needed before we went too far with resource allocation. - */ - res->irq = platform_get_irq_byname(pdev, "macirq"); - if (res->irq < 0) - return res->irq; - - /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq - * The external wake up irq can be passed through the platform code - * named as "eth_wake_irq" - * - * In case the wake up interrupt is not passed from the platform - * so the driver will continue to use the mac irq (ndev->irq) - */ - res->wol_irq = - platform_get_irq_byname_optional(pdev, "eth_wake_irq"); - if (res->wol_irq < 0) { - if (res->wol_irq == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n"); - res->wol_irq = res->irq; - } - - res->lpi_irq = - platform_get_irq_byname_optional(pdev, "eth_lpi"); - if (res->lpi_irq < 0) { - if (res->lpi_irq == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_info(&pdev->dev, "IRQ eth_lpi not found\n"); - } - - eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL); - if (!eqos) - return -ENOMEM; - - eqos->dev = &pdev->dev; - eqos->regs = res->addr; - - if (!is_of_node(dev->fwnode)) - goto bypass_clk_reset_gpio; - - eqos->clk_tx = devm_clk_get(&pdev->dev, "tx"); - if (IS_ERR(eqos->clk_tx)) { - err = PTR_ERR(eqos->clk_tx); - goto err; - } - - err = clk_prepare_enable(eqos->clk_tx); - if (err < 0) - goto err; - - eqos->clk_gtx = devm_clk_get(&pdev->dev, "gtx"); - if (IS_ERR(eqos->clk_gtx)) { - err = PTR_ERR(eqos->clk_gtx); - goto disable_tx; - } - - err = clk_prepare_enable(eqos->clk_gtx); - if (err < 0) - goto disable_tx; - - eqos->clk_gtxc = devm_clk_get(&pdev->dev, "gtxc"); - if (IS_ERR(eqos->clk_gtxc)) { - err = PTR_ERR(eqos->clk_gtxc); - goto disable_gtx; - } - - err = clk_prepare_enable(eqos->clk_gtxc); - if (err < 0) - goto disable_gtx; - -bypass_clk_reset_gpio: - data->fix_mac_speed = starfive_eqos_fix_speed; - data->init = NULL; - data->bsp_priv = eqos; - return 0; - -disable_gtx: - clk_disable_unprepare(eqos->clk_gtx); -disable_tx: - clk_disable_unprepare(eqos->clk_tx); -err: - return err; -} - -static int starfive_eqos_remove(struct platform_device *pdev) -{ - struct starfive_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev); - - clk_disable_unprepare(eqos->clk_tx); - clk_disable_unprepare(eqos->clk_gtx); - - return 0; -} - struct dwc_eth_dwmac_data { int (*probe)(struct platform_device *pdev, struct plat_stmmacenet_data *data, @@ -551,11 +414,6 @@ static const struct dwc_eth_dwmac_data tegra_eqos_data = { .remove = tegra_eqos_remove, }; -static const struct dwc_eth_dwmac_data starfive_eqos_data = { - .probe = starfive_eqos_probe, - .remove = starfive_eqos_remove, -}; - static int dwc_eth_dwmac_probe(struct platform_device *pdev) { const struct dwc_eth_dwmac_data *data; @@ -636,7 +494,6 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev) static const struct of_device_id dwc_eth_dwmac_match[] = { { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data }, { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data }, - { .compatible = "starfive,jh7110-eqos-5.20", .data = &starfive_eqos_data }, { } }; MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive-plat.c new file mode 100644 index 0000000..c563582 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive-plat.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +/* StarFive DWMAC platform driver + * + * Copyright(C) 2022 StarFive Technology Co., Ltd. + */ + +#include +#include "stmmac_platform.h" + +struct starfive_dwmac { + struct device *dev; + void __iomem *regs; + struct clk *clk_tx; + struct clk *clk_gtx; + struct clk *clk_gtxc; +}; + +static void starfive_eth_fix_mac_speed(void *priv, unsigned int speed) +{ + struct starfive_dwmac *dwmac = priv; + unsigned long rate; + int err; + + switch (speed) { + case SPEED_1000: + rate = 125000000; + break; + case SPEED_100: + rate = 25000000; + break; + case SPEED_10: + rate = 2500000; + break; + default: + dev_err(dwmac->dev, "invalid speed %u\n", speed); + return; + } + + err = clk_set_rate(dwmac->clk_gtx, rate); + if (err < 0) + dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); +} + +static const struct of_device_id starfive_eth_plat_match[] = { + {.compatible = "starfive,dwmac"}, + { } +}; + +static int starfive_eth_plat_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct starfive_dwmac *dwmac; + int err; + + err = stmmac_get_platform_resources(pdev, &stmmac_res); + if (err) + return err; + + plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac); + if (IS_ERR(plat_dat)) { + dev_err(&pdev->dev, "dt configuration failed\n"); + return PTR_ERR(plat_dat); + } + + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); + if (!dwmac) + return -ENOMEM; + + dwmac->dev = &pdev->dev; + dwmac->regs = stmmac_res.addr; + + if (!is_of_node(dev->fwnode)) + goto bypass_clk_reset_gpio; + + dwmac->clk_tx = devm_clk_get(&pdev->dev, "tx"); + if (IS_ERR(dwmac->clk_tx)) { + err = PTR_ERR(dwmac->clk_tx); + goto err; + } + + err = clk_prepare_enable(dwmac->clk_tx); + if (err < 0) + goto err; + + dwmac->clk_gtx = devm_clk_get(&pdev->dev, "gtx"); + if (IS_ERR(dwmac->clk_gtx)) { + err = PTR_ERR(dwmac->clk_gtx); + goto disable_tx; + } + + err = clk_prepare_enable(dwmac->clk_gtx); + if (err < 0) + goto disable_tx; + + dwmac->clk_gtxc = devm_clk_get(&pdev->dev, "gtxc"); + if (IS_ERR(dwmac->clk_gtxc)) { + err = PTR_ERR(dwmac->clk_gtxc); + goto disable_gtx; + } + + err = clk_prepare_enable(dwmac->clk_gtxc); + if (err < 0) + goto disable_gtx; + + err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (err) + goto err; + +bypass_clk_reset_gpio: + plat_dat->fix_mac_speed = starfive_eth_fix_mac_speed; + plat_dat->init = NULL; + plat_dat->bsp_priv = dwmac; + return 0; + +disable_gtx: + clk_disable_unprepare(dwmac->clk_gtx); +disable_tx: + clk_disable_unprepare(dwmac->clk_tx); +err: + stmmac_remove_config_dt(pdev, plat_dat); + return err; +} + +static int starfive_eth_plat_remove(struct platform_device *pdev) +{ + struct starfive_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev); + + clk_disable_unprepare(dwmac->clk_gtxc); + clk_disable_unprepare(dwmac->clk_gtx); + clk_disable_unprepare(dwmac->clk_tx); + + return 0; +} + +static struct platform_driver starfive_eth_plat_driver = { + .probe = starfive_eth_plat_probe, + .remove = starfive_eth_plat_remove, + .driver = { + .name = "starfive-eth-plat", + .pm = &stmmac_pltfr_pm_ops, + .of_match_table = starfive_eth_plat_match, + }, +}; + +module_platform_driver(starfive_eth_plat_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("StarFive DWMAC platform driver"); + -- 2.7.4