Merge pull request #8132 from jernejsk/aw-eth

[LE12] Allwinner: rework OrangePi 3 network patches
This commit is contained in:
CvH 2023-09-12 16:44:07 +02:00 committed by GitHub
commit 3f2d90708d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 201 additions and 309 deletions

View File

@ -1,22 +0,0 @@
From 89a2da7c8bae95cf9225015489736e2fc434f4d9 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Sat, 2 Jan 2021 16:35:31 +0100
Subject: [PATCH] sunxi: Don't enable referenced regulators
This break certain devices which need appropriate power on sequence.
---
drivers/allwinner/axp/common.c | 3 ---
1 file changed, 3 deletions(-)
--- a/drivers/allwinner/axp/common.c
+++ b/drivers/allwinner/axp/common.c
@@ -112,9 +112,6 @@ static bool should_enable_regulator(const void *fdt,
if (is_node_disabled(fdt, node)) {
return false;
}
- if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) {
- return true;
- }
if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) {
return true;
}

View File

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Wed, 27 Mar 2019 13:21:06 +0100
Subject: [PATCH] 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 <megous@megous.com>
---
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++-----------
1 file changed, 10 insertions(+), 13 deletions(-)
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -571,12 +571,10 @@ static int sun8i_dwmac_init(struct platf
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;
}
ret = clk_prepare_enable(gmac->tx_clk);
@@ -1045,8 +1043,7 @@ static void sun8i_dwmac_exit(struct plat
clk_disable_unprepare(gmac->tx_clk);
- if (gmac->regulator)
- regulator_disable(gmac->regulator);
+ regulator_disable(gmac->regulator);
}
static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable)
@@ -1174,12 +1171,12 @@ static int sun8i_dwmac_probe(struct plat
}
/* 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

View File

@ -0,0 +1,145 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Corentin Labbe <clabbe.montjoie@gmail.com>
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 <clabbe.montjoie@gmail.com>
---
drivers/net/mdio/fwnode_mdio.c | 31 ++++++++++++++++++++++++++++++-
drivers/net/phy/phy_device.c | 13 +++++++++++++
include/linux/phy.h | 3 +++
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
index 1183ef5e203e..7ef42098df6e 100644
--- a/drivers/net/mdio/fwnode_mdio.c
+++ b/drivers/net/mdio/fwnode_mdio.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/pse-pd/pse.h>
+#include <linux/regulator/consumer.h>
MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
MODULE_LICENSE("GPL");
@@ -117,7 +118,9 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
struct phy_device *phy;
bool is_c45;
u32 phy_id;
- int rc;
+ struct device_node __maybe_unused *nchild = NULL;
+ struct regulator_bulk_data *consumers = NULL;
+ int rc, reg_cnt = 0;
psec = fwnode_find_pse_control(child);
if (IS_ERR(psec))
@@ -129,6 +132,25 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
goto clean_pse;
}
+ for_each_child_of_node(bus->dev.of_node, nchild) {
+ u32 reg;
+
+ of_property_read_u32(nchild, "reg", &reg);
+ if (reg != addr)
+ continue;
+ reg_cnt = of_regulator_bulk_get_all(&bus->dev, nchild, &consumers);
+ if (reg_cnt > 0) {
+ rc = regulator_bulk_enable(reg_cnt, consumers);
+ if (rc)
+ goto clean_kfree;
+ }
+ if (reg_cnt < 0) {
+ dev_err(&bus->dev, "Fail to regulator_bulk_get_all err=%d\n", reg_cnt);
+ rc = reg_cnt;
+ goto clean_kfree;
+ }
+ }
+
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);
@@ -139,6 +161,9 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
goto clean_mii_ts;
}
+ phy->regulator_cnt = reg_cnt;
+ phy->consumers = consumers;
+
if (is_acpi_node(child)) {
phy->irq = bus->irq[addr];
@@ -178,6 +203,10 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
clean_pse:
pse_control_put(psec);
+ if (reg_cnt > 0)
+ regulator_bulk_disable(reg_cnt, consumers);
+clean_kfree:
+ kfree(consumers);
return rc;
}
EXPORT_SYMBOL(fwnode_mdiobus_register_phy);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c7cf61fe41cf..3bfe9bf6b3ac 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -30,6 +30,7 @@
#include <linux/phy_led_triggers.h>
#include <linux/pse-pd/pse.h>
#include <linux/property.h>
+#include <linux/regulator/consumer.h>
#include <linux/sfp.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
@@ -1871,6 +1872,9 @@ int phy_suspend(struct phy_device *phydev)
if (!ret)
phydev->suspended = true;
+ if (phydev->regulator_cnt > 0)
+ regulator_bulk_disable(phydev->regulator_cnt, phydev->consumers);
+
return ret;
}
EXPORT_SYMBOL(phy_suspend);
@@ -1897,6 +1901,12 @@ int phy_resume(struct phy_device *phydev)
{
int ret;
+ if (phydev->regulator_cnt > 0) {
+ ret = regulator_bulk_enable(phydev->regulator_cnt, phydev->consumers);
+ if (ret)
+ return ret;
+ }
+
mutex_lock(&phydev->lock);
ret = __phy_resume(phydev);
mutex_unlock(&phydev->lock);
@@ -3332,6 +3342,9 @@ static int phy_remove(struct device *dev)
phydev->drv = NULL;
+ if (phydev->consumers)
+ kfree(phydev->consumers);
+
return 0;
}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 11c1e91563d4..2d058595d1a1 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -752,6 +752,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;

View File

@ -1,12 +1,12 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
Date: Tue, 20 Aug 2019 14:54:48 +0200
Subject: [PATCH] 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 "phy" regulator.
than "ephy" regulator.
RTL8211E/RTL8211EG datasheet says:
@ -14,32 +14,27 @@ 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.
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 <megous@megous.com>
Signed-off-by: Ondrej Jirman <megi@xff.cz>
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
.../dts/allwinner/sun50i-h6-orangepi-3.dts | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
.../dts/allwinner/sun50i-h6-orangepi-3.dts | 39 +++++++++++++++++++
1 file changed, 39 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
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
@@ -15,6 +15,7 @@
@@ -13,6 +13,7 @@ / {
compatible = "xunlong,orangepi-3", "allwinner,sun50i-h6";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
+ ethernet0 = &emac;
};
chosen {
@@ -64,6 +65,15 @@
regulator-always-on;
@@ -55,6 +56,16 @@ led-1 {
};
};
+ reg_gmac_2v5: gmac-2v5 {
@ -49,30 +44,21 @@ Signed-off-by: Ondrej Jirman <megous@megous.com>
+ regulator-max-microvolt = <2500000>;
+ enable-active-high;
+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */
+ off-on-delay-us = <100000>;
+ };
+
reg_vcc33_wifi: vcc33-wifi {
/* Always on 3.3V regulator for WiFi and BT */
reg_vcc5v: vcc5v {
/* board wide 5V supply directly from the DC jack */
compatible = "regulator-fixed";
@@ -128,6 +138,35 @@
};
@@ -113,6 +124,33 @@ &ehci3 {
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii-txid";
+ phy-mode = "rgmii-id";
+ 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 = <&reg_aldo2>;
+ phy-io-supply = <&reg_gmac_2v5>;
+ allwinner,rx-delay-ps = <1500>;
+ allwinner,tx-delay-ps = <700>;
+ status = "okay";
+};
+
@ -80,6 +66,14 @@ Signed-off-by: Ondrej Jirman <megous@megous.com>
+ 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 = <&reg_gmac_2v5>;
+ ephy-supply = <&reg_aldo2>;
+
+ reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */
+ reset-assert-us = <15000>;
@ -87,10 +81,10 @@ Signed-off-by: Ondrej Jirman <megous@megous.com>
+ };
+};
+
&mmc0 {
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
@@ -211,6 +250,7 @@
&gpu {
mali-supply = <&reg_dcdcc>;
status = "okay";
@@ -211,6 +249,7 @@ reg_aldo2: aldo2 {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc33-audio-tv-ephy-mac";

View File

@ -1,92 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 20 Aug 2019 14:29:29 +0200
Subject: [PATCH] net: stmmac: sun8i: Rename PHY regulator variable to
regulator_phy
We'll be adding further optional regulators, and this makes it clearer
what the regulator is for.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 39 +++++++++----------
1 file changed, 19 insertions(+), 20 deletions(-)
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -57,18 +57,20 @@ 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
- * @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
- * @internal_phy_powered: Does the internal PHY is enabled
- * @use_internal_phy: Is the internal PHY selected for use
- * @mux_handle: Internal pointer used by mdio-mux lib
+ * @ephy_clk: reference to the optional EPHY clock for
+ * the internal PHY
+ * @regulator_phy: reference to the optional regulator
+ * @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
+ * @internal_phy_powered: Does the internal PHY is enabled
+ * @use_internal_phy: Is the internal PHY selected for use
+ * @mux_handle: Internal pointer used by mdio-mux lib
*/
struct sunxi_priv_data {
struct clk *ephy_clk;
- struct regulator *regulator;
+ struct regulator *regulator_phy;
struct reset_control *rst_ephy;
const struct emac_variant *variant;
struct regmap_field *regmap_field;
@@ -571,9 +573,9 @@ static int sun8i_dwmac_init(struct platf
struct sunxi_priv_data *gmac = priv;
int ret;
- ret = regulator_enable(gmac->regulator);
+ ret = regulator_enable(gmac->regulator_phy);
if (ret) {
- dev_err(&pdev->dev, "Fail to enable regulator\n");
+ dev_err(&pdev->dev, "Fail to enable PHY regulator\n");
return ret;
}
@@ -594,8 +596,7 @@ static int sun8i_dwmac_init(struct platf
err_disable_clk:
clk_disable_unprepare(gmac->tx_clk);
err_disable_regulator:
- if (gmac->regulator)
- regulator_disable(gmac->regulator);
+ regulator_disable(gmac->regulator_phy);
return ret;
}
@@ -1043,7 +1044,7 @@ static void sun8i_dwmac_exit(struct plat
clk_disable_unprepare(gmac->tx_clk);
- regulator_disable(gmac->regulator);
+ regulator_disable(gmac->regulator_phy);
}
static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable)
@@ -1171,11 +1172,9 @@ static int sun8i_dwmac_probe(struct plat
}
/* Optional regulator for PHY */
- gmac->regulator = devm_regulator_get(dev, "phy");
- if (IS_ERR(gmac->regulator)) {
- ret = PTR_ERR(gmac->regulator);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get PHY regulator (%d)\n", ret);
+ gmac->regulator_phy = devm_regulator_get(dev, "phy");
+ if (IS_ERR(gmac->regulator_phy)) {
+ dev_err_probe(dev, ret, "Failed to get PHY regulator\n");
return ret;
}

View File

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sun, 10 Sep 2023 12:08:31 +0200
Subject: [PATCH] HACK: regulator: lower power off delay to 1 second
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
drivers/regulator/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d8e1caaf207e..b8d9409b77b8 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -6285,7 +6285,7 @@ static int __init regulator_init_complete(void)
* command line option might be useful.
*/
schedule_delayed_work(&regulator_init_complete_work,
- msecs_to_jiffies(30000));
+ msecs_to_jiffies(1000));
return 0;
}

View File

@ -1,87 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 20 Aug 2019 14:31:38 +0200
Subject: [PATCH] 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 <megous@megous.com>
---
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
--- 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 {
* @ephy_clk: reference to the optional EPHY clock for
* the internal PHY
* @regulator_phy: 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
@@ -73,6 +75,7 @@
struct sunxi_priv_data {
struct clk *ephy_clk;
struct regulator *regulator_phy;
+ struct regulator *regulator_phy_io;
struct reset_control *rst_ephy;
const struct emac_variant *variant;
struct regmap_field *regmap_field;
@@ -573,10 +576,16 @@ static int sun8i_dwmac_init(struct platf
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_phy);
if (ret) {
dev_err(&pdev->dev, "Fail to enable PHY regulator\n");
- return ret;
+ goto err_disable_regulator_phy_io;
}
ret = clk_prepare_enable(gmac->tx_clk);
@@ -597,6 +606,8 @@ err_disable_clk:
clk_disable_unprepare(gmac->tx_clk);
err_disable_regulator:
regulator_disable(gmac->regulator_phy);
+err_disable_regulator_phy_io:
+ regulator_disable(gmac->regulator_phy_io);
return ret;
}
@@ -1045,6 +1056,7 @@ static void sun8i_dwmac_exit(struct plat
clk_disable_unprepare(gmac->tx_clk);
regulator_disable(gmac->regulator_phy);
+ regulator_disable(gmac->regulator_phy_io);
}
static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable)
@@ -1178,6 +1190,15 @@ static int sun8i_dwmac_probe(struct plat
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).