--- /dev/null
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/starfive,dwmac-plat.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive DWMAC glue layer Device Tree Bindings
+
+maintainers:
+ - Tan Chun Hau <chunhau.tan@starfivetech.com>
+
+select:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - starfive,dwmac
+ required:
+ - compatible
+
+allOf:
+ - $ref: "snps,dwmac.yaml#"
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - starfive,dwmac
+ - const: snps,dwmac-5.10a
+
+ clocks:
+ items:
+ - description: Gtx clock
+ - description: Tx clock
+ - description: PTP reference clock
+ - description: GMAC main clock
+ - description: PTP reference clock
+ - description: Gtxc clock
+
+ clock-names:
+ items:
+ - const: gtx
+ - const: tx
+ - const: ptp_ref
+ - const: stmmaceth
+ - const: pclk
+ - const: gtxc
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+Example:
+ - |
+ #include <dt-bindings/reset/starfive-jh7110.h>
+ #include <dt-bindings/clock/starfive-jh7110-clkgen.h>
+
+ /* gmac device configuration */
+ stmmac_axi_setup: stmmac-axi-config {
+ snps,wr_osr_lmt = <0xf>;
+ snps,rd_osr_lmt = <0xf>;
+ snps,blen = <256 128 64 32 0 0 0>;
+ };
+
+ gmac0: gmac@17020000 {
+ compatible = "starfive,dwmac","snps,dwmac-5.10a";
+ reg = <0x0 0x17020000 0x0 0x10000>;
+ interrupts = <7>, <6>, <5>;
+ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+ phy-reset-gpios = <&gpio 63 0>;
+ clock-names = "gtx",
+ "tx",
+ "ptp_ref",
+ "stmmaceth",
+ "pclk",
+ "gtxc";
+ clocks = <&clkgen JH7110_GMAC0_GTXCLK>,
+ <&clkgen JH7110_U0_GMAC5_CLK_TX>,
+ <&clkgen JH7110_GMAC0_PTP>,
+ <&clkgen JH7110_U0_GMAC5_CLK_AHB>,
+ <&clkgen JH7110_U0_GMAC5_CLK_AXI>,
+ <&clkgen JH7110_GMAC0_GTXC>;
+ resets = <&rstgen RSTN_U0_DW_GMAC5_AXI64_AHB>,
+ <&rstgen RSTN_U0_DW_GMAC5_AXI64_AXI>;
+ reset-names = "ahb", "stmmaceth";
+ max-frame-size = <1500>;
+ phy-mode = "rgmii-id";
+ snps,multicast-filter-bins = <64>;
+ snps,perfect-filter-entries = <128>;
+ rx-fifo-depth = <2048>;
+ tx-fifo-depth = <2048>;
+ snps,fixed-burst;
+ snps,no-pbl-x8;
+ snps,force_thresh_dma_mode;
+ snps,axi-config = <&stmmac_axi_setup>;
+ snps,tso;
+ snps,en-tx-lpi-clockgating;
+ snps,txpbl = <4>;
+ snps,rxpbl = <4>;
+ };
+
};
gmac0: ethernet@16030000 {
- compatible = "starfive,jh7110-eqos-5.20";
+ compatible = "starfive,dwmac","snps,dwmac-5.10a";
reg = <0x0 0x16030000 0x0 0x10000>;
clock-names = "gtx",
"tx",
};
gmac1: ethernet@16040000 {
- compatible = "starfive,jh7110-eqos-5.20";
+ compatible = "starfive,dwmac","snps,dwmac-5.10a";
reg = <0x0 0x16040000 0x0 0x10000>;
clock-names = "gtx",
"tx",
# CONFIG_NET_VENDOR_SOCIONEXT is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_SELFTESTS=y
-CONFIG_DWMAC_DWC_QOS_ETH=y
+CONFIG_DWMAC_STARFIVE_PLAT=y
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
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
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
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)
{
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,
.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;
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);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* StarFive DWMAC platform driver
+ *
+ * Copyright(C) 2022 StarFive Technology Co., Ltd.
+ */
+
+#include <linux/of_device.h>
+#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");
+