diff --git a/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch b/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch deleted file mode 100644 index ed9cf3f055..0000000000 --- a/projects/Allwinner/patches/linux/0026-phy-handle-optional-regulator-for-PHY.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 25b44143ea8162209beb02759ca3ea3bd3be7a74 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Fri, 14 Oct 2022 12:54:21 +0200 -Subject: [PATCH] phy: handle optional regulator for PHY - -Add handling of optional regulators for PHY. - -Regulators need to be enabled before PHY scanning, so MDIO bus -initiate this task. - -Signed-off-by: Corentin Labbe -Signed-off-by: Jernej Skrabec ---- - drivers/net/mdio/fwnode_mdio.c | 53 ++++++++++++++++++++++++++++++++-- - drivers/net/phy/phy_device.c | 6 ++++ - include/linux/phy.h | 3 ++ - 3 files changed, 60 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c -index fd02f5cbc853..bd5a27eaf40c 100644 ---- a/drivers/net/mdio/fwnode_mdio.c -+++ b/drivers/net/mdio/fwnode_mdio.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - MODULE_AUTHOR("Calvin Johnson "); - MODULE_LICENSE("GPL"); -@@ -58,6 +59,40 @@ fwnode_find_mii_timestamper(struct fwnode_handle *fwnode) - return register_mii_timestamper(arg.np, arg.args[0]); - } - -+static int -+fwnode_regulator_get_bulk_enabled(struct device *dev, -+ struct fwnode_handle *fwnode, -+ struct regulator_bulk_data **consumers) -+{ -+ struct device_node *np; -+ int ret, reg_cnt; -+ -+ np = to_of_node(fwnode); -+ if (!np) -+ return 0; -+ -+ reg_cnt = of_regulator_bulk_get_all(dev, np, consumers); -+ if (reg_cnt < 0) { -+ ret = reg_cnt; -+ goto clean_consumers; -+ } -+ -+ if (reg_cnt == 0) -+ return 0; -+ -+ ret = regulator_bulk_enable(reg_cnt, *consumers); -+ if (ret) -+ goto clean_consumers; -+ -+ return reg_cnt; -+ -+clean_consumers: -+ kfree(*consumers); -+ *consumers = NULL; -+ -+ return ret; -+} -+ - int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio, - struct phy_device *phy, - struct fwnode_handle *child, u32 addr) -@@ -113,12 +148,13 @@ EXPORT_SYMBOL(fwnode_mdiobus_phy_device_register); - int fwnode_mdiobus_register_phy(struct mii_bus *bus, - struct fwnode_handle *child, u32 addr) - { -+ struct regulator_bulk_data *consumers = NULL; - struct mii_timestamper *mii_ts = NULL; - struct pse_control *psec = NULL; - struct phy_device *phy; -+ int rc, reg_cnt; - bool is_c45; - u32 phy_id; -- int rc; - - psec = fwnode_find_pse_control(child); - if (IS_ERR(psec)) -@@ -130,6 +166,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, - goto clean_pse; - } - -+ reg_cnt = fwnode_regulator_get_bulk_enabled(&bus->dev, child, &consumers); -+ if (reg_cnt < 0) { -+ rc = reg_cnt; -+ goto clean_mii_ts; -+ } -+ - is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); - if (is_c45 || fwnode_get_phy_id(child, &phy_id)) - phy = get_phy_device(bus, addr, is_c45); -@@ -137,9 +179,12 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, - phy = phy_device_create(bus, addr, phy_id, 0, NULL); - if (IS_ERR(phy)) { - rc = PTR_ERR(phy); -- goto clean_mii_ts; -+ goto clean_regulators; - } - -+ phy->regulator_cnt = reg_cnt; -+ phy->consumers = consumers; -+ - if (is_acpi_node(child)) { - phy->irq = bus->irq[addr]; - -@@ -174,6 +219,10 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus, - - clean_phy: - phy_device_free(phy); -+clean_regulators: -+ if (reg_cnt > 0) -+ regulator_bulk_disable(reg_cnt, consumers); -+ kfree(consumers); - clean_mii_ts: - unregister_mii_timestamper(mii_ts); - clean_pse: -diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c -index 2ce74593d6e4..31b6913ceed1 100644 ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -3400,6 +3401,11 @@ static int phy_remove(struct device *dev) - - phydev->drv = NULL; - -+ if (phydev->regulator_cnt > 0) -+ regulator_bulk_disable(phydev->regulator_cnt, phydev->consumers); -+ -+ kfree(phydev->consumers); -+ - return 0; - } - -diff --git a/include/linux/phy.h b/include/linux/phy.h -index 3cc52826f18e..832cb2d4f76a 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -757,6 +757,9 @@ struct phy_device { - void (*phy_link_change)(struct phy_device *phydev, bool up); - void (*adjust_link)(struct net_device *dev); - -+ int regulator_cnt; -+ struct regulator_bulk_data *consumers; -+ - #if IS_ENABLED(CONFIG_MACSEC) - /* MACsec management functions */ - const struct macsec_ops *macsec_ops; --- -2.43.0 - diff --git a/projects/Allwinner/patches/linux/0074-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regu.patch b/projects/Allwinner/patches/linux/0074-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regu.patch new file mode 100644 index 0000000000..09189a3155 --- /dev/null +++ b/projects/Allwinner/patches/linux/0074-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regu.patch @@ -0,0 +1,75 @@ +From 1877122b4d0fef204f7076f4c28761cae9fcd807 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sat, 15 Mar 2025 17:38:35 +0100 +Subject: [PATCH 1/3] net: stmmac: sun8i: Use devm_regulator_get for PHY + regulator + +Use devm_regulator_get instead of devm_regulator_get_optional and rely +on dummy supply. This avoids NULL checks before regulator_enable/disable +calls. + +This path also improves error reporting, because we now report both +use of dummy supply and error during registration with more detail, +instead of generic info level message "No regulator found" that +was reported previously on errors and lack of regulator property in DT. + +Finally, we'll be adding further optional regulators, and the overall +code will be simpler. + +Signed-off-by: Ondrej Jirman +--- + .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++----------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +index 4b7b2582a120..94a4898260b0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -588,12 +588,10 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) + struct sunxi_priv_data *gmac = priv; + int ret; + +- if (gmac->regulator) { +- ret = regulator_enable(gmac->regulator); +- if (ret) { +- dev_err(&pdev->dev, "Fail to enable regulator\n"); +- return ret; +- } ++ ret = regulator_enable(gmac->regulator); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to enable regulator\n"); ++ return ret; + } + + if (gmac->use_internal_phy) { +@@ -1051,8 +1049,7 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) + if (gmac->variant->soc_has_internal_phy) + sun8i_dwmac_unpower_internal_phy(gmac); + +- if (gmac->regulator) +- regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1176,12 +1173,12 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) + } + + /* Optional regulator for PHY */ +- gmac->regulator = devm_regulator_get_optional(dev, "phy"); ++ gmac->regulator = devm_regulator_get(dev, "phy"); + if (IS_ERR(gmac->regulator)) { +- if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- dev_info(dev, "No regulator found\n"); +- gmac->regulator = NULL; ++ ret = PTR_ERR(gmac->regulator); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); ++ return ret; + } + + /* The "GMAC clock control" register might be located in the +-- +2.48.1 + diff --git a/projects/Allwinner/patches/linux/0075-net-stmmac-sun8i-Add-support-for-enabling-a-regulato.patch b/projects/Allwinner/patches/linux/0075-net-stmmac-sun8i-Add-support-for-enabling-a-regulato.patch new file mode 100644 index 0000000000..38f27a452e --- /dev/null +++ b/projects/Allwinner/patches/linux/0075-net-stmmac-sun8i-Add-support-for-enabling-a-regulato.patch @@ -0,0 +1,92 @@ +From a46ed6e8213c96d0905de691620cd473b0a2e45e Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sat, 15 Mar 2025 17:49:23 +0100 +Subject: [PATCH 2/3] net: stmmac: sun8i: Add support for enabling a regulator + for PHY I/O pins + +Orange Pi 3 has two regulators that power the Realtek RTL8211E. According +to the phy datasheet, both regulators need to be enabled at the same time. + +Add support for the second optional regulator, "phy-io", to the glue +driver. + +Signed-off-by: Ondrej Jirman +--- + .../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +index 94a4898260b0..da77e82f06d2 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -61,6 +61,8 @@ struct emac_variant { + /* struct sunxi_priv_data - hold all sunxi private data + * @ephy_clk: reference to the optional EPHY clock for the internal PHY + * @regulator: reference to the optional regulator ++ * @regulator_phy_io: reference to the optional regulator for ++ * PHY I/O pins + * @rst_ephy: reference to the optional EPHY reset for the internal PHY + * @variant: reference to the current board variant + * @regmap: regmap for using the syscon +@@ -71,6 +73,7 @@ struct emac_variant { + struct sunxi_priv_data { + struct clk *ephy_clk; + struct regulator *regulator; ++ struct regulator *regulator_phy_io; + struct reset_control *rst_ephy; + const struct emac_variant *variant; + struct regmap_field *regmap_field; +@@ -588,10 +591,16 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) + struct sunxi_priv_data *gmac = priv; + int ret; + ++ ret = regulator_enable(gmac->regulator_phy_io); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to enable PHY I/O regulator\n"); ++ return ret; ++ } ++ + ret = regulator_enable(gmac->regulator); + if (ret) { + dev_err(&pdev->dev, "Fail to enable regulator\n"); +- return ret; ++ goto err_disable_regulator_phy_io; + } + + if (gmac->use_internal_phy) { +@@ -605,6 +614,8 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) + err_disable_regulator: + if (gmac->regulator) + regulator_disable(gmac->regulator); ++err_disable_regulator_phy_io: ++ regulator_disable(gmac->regulator_phy_io); + + return ret; + } +@@ -1050,6 +1061,7 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) + sun8i_dwmac_unpower_internal_phy(gmac); + + regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator_phy_io); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1181,6 +1193,15 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) + return ret; + } + ++ /* Optional regulator for PHY I/O pins */ ++ gmac->regulator_phy_io = devm_regulator_get(dev, "phy-io"); ++ if (IS_ERR(gmac->regulator_phy_io)) { ++ ret = PTR_ERR(gmac->regulator_phy_io); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get PHY I/O regulator (%d)\n", ret); ++ return ret; ++ } ++ + /* The "GMAC clock control" register might be located in the + * CCU address range (on the R40), or the system control address + * range (on most other sun8i and later SoCs). +-- +2.48.1 + diff --git a/projects/Allwinner/patches/linux/0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch b/projects/Allwinner/patches/linux/0076-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch similarity index 55% rename from projects/Allwinner/patches/linux/0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch rename to projects/Allwinner/patches/linux/0076-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch index 05788ef492..16d540f9f8 100644 --- a/projects/Allwinner/patches/linux/0027-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch +++ b/projects/Allwinner/patches/linux/0076-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch @@ -1,12 +1,12 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= -Date: Tue, 20 Aug 2019 14:54:48 +0200 -Subject: [PATCH] arm64: dts: allwinner: orange-pi-3: Enable ethernet +From 2409d598b229dee9036f9ea2f14dde2647e8c114 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sat, 15 Mar 2025 18:00:20 +0100 +Subject: [PATCH 3/3] arm64: dts: allwinner: orange-pi-3: Enable ethernet Orange Pi 3 has two regulators that power the Realtek RTL8211E PHY. According to the datasheet, both regulators need to be enabled at the same time, or that "phy-io" should be enabled slightly earlier -than "ephy" regulator. +than "phy" regulator. RTL8211E/RTL8211EG datasheet says: @@ -14,26 +14,33 @@ RTL8211E/RTL8211EG datasheet says: or slightly earlier than 3.3V power. Rising 2.5V (or 1.8/1.5V) power later than 3.3V power may lead to errors. -Signed-off-by: Ondrej Jirman -Signed-off-by: Corentin Labbe -Signed-off-by: Jernej Skrabec +The driver ensures the regulator enable ordering. The timing is set +in DT via startup-delay-us. + +We also need to wait at least 30ms after power-up/reset, before +accessing the PHY registers. + +All values of RX/TX delay were tested exhaustively and a middle one +of the range of working values was chosen. + +Signed-off-by: Ondrej Jirman --- - .../dts/allwinner/sun50i-h6-orangepi-3.dts | 39 +++++++++++++++++++ - 1 file changed, 39 insertions(+) + .../dts/allwinner/sun50i-h6-orangepi-3.dts | 40 +++++++++++++++++++ + 1 file changed, 40 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts -index 6fc65e8db220..df8b6de2b4d2 100644 +index d01a318653a3..89049a7c0473 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts -@@ -13,6 +13,7 @@ / { - compatible = "xunlong,orangepi-3", "allwinner,sun50i-h6"; - +@@ -15,6 +15,7 @@ / { aliases { -+ ethernet0 = &emac; serial0 = &uart0; serial1 = &uart1; ++ ethernet0 = &emac; }; -@@ -55,6 +56,16 @@ led-1 { + + chosen { +@@ -55,6 +56,15 @@ led-1 { }; }; @@ -44,21 +51,30 @@ index 6fc65e8db220..df8b6de2b4d2 100644 + regulator-max-microvolt = <2500000>; + enable-active-high; + gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ -+ off-on-delay-us = <100000>; + }; + reg_vcc5v: vcc5v { /* board wide 5V supply directly from the DC jack */ compatible = "regulator-fixed"; -@@ -113,6 +124,33 @@ &ehci3 { - status = "okay"; +@@ -108,6 +118,35 @@ hdmi_out_con: endpoint { + }; }; +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; -+ phy-mode = "rgmii-id"; ++ phy-mode = "rgmii-txid"; + phy-handle = <&ext_rgmii_phy>; ++ /* ++ * The board uses 2.5V RGMII signalling. Power sequence to enable ++ * the phy is to enable GMAC-2V5 and GMAC-3V (aldo2) power rails ++ * at the same time and to wait 100ms. The driver enables phy-io ++ * first. Delay is achieved with enable-ramp-delay on reg_aldo2. ++ */ ++ phy-supply = <®_aldo2>; ++ phy-io-supply = <®_gmac_2v5>; ++ allwinner,rx-delay-ps = <1500>; ++ allwinner,tx-delay-ps = <700>; + status = "okay"; +}; + @@ -66,14 +82,6 @@ index 6fc65e8db220..df8b6de2b4d2 100644 + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; -+ /* -+ * The board uses 2.5V RGMII signalling. Power sequence to enable -+ * the phy is to enable GMAC-2V5 and GMAC-3V (aldo2) power rails -+ * at the same time and to wait 100ms. The driver enables phy-io -+ * first. Delay is achieved with enable-ramp-delay on reg_aldo2. -+ */ -+ phy-io-supply = <®_gmac_2v5>; -+ ephy-supply = <®_aldo2>; + + reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ + reset-assert-us = <15000>; @@ -81,10 +89,10 @@ index 6fc65e8db220..df8b6de2b4d2 100644 + }; +}; + - &gpu { - mali-supply = <®_dcdcc>; - status = "okay"; -@@ -211,6 +249,7 @@ reg_aldo2: aldo2 { + &mmc0 { + vmmc-supply = <®_cldo1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ +@@ -188,6 +227,7 @@ reg_aldo2: aldo2 { regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcc33-audio-tv-ephy-mac"; @@ -92,3 +100,6 @@ index 6fc65e8db220..df8b6de2b4d2 100644 }; /* ALDO3 is shorted to CLDO1 */ +-- +2.48.1 +