Hello, Even if using arm-trusted-firmware with SUNXI_SETUP_REGULATORS=0, Ethernet of Orange Pi One Plus (and maybe 3, 3-LTS) works after cold-boot (no warm-boot).
This requires - proper power-up sequence - handle PHY(RTL8211E) reset signal and there is a proposal that posted to LKML. https://marc.info/?l=linux-kernel&m=170310454303820&w=2 We have to wait for release fixed DTS but we can prepare our driver. Any comments are welcomed. -- SASANO Takayoshi (JG1UAA) <u...@mx5.nisiq.net> Index: if_dwxe.c =================================================================== RCS file: /cvs/src/sys/dev/fdt/if_dwxe.c,v diff -u -p -r1.24 if_dwxe.c --- if_dwxe.c 27 Feb 2024 10:47:20 -0000 1.24 +++ if_dwxe.c 3 Mar 2024 00:34:04 -0000 @@ -41,6 +41,7 @@ #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_clock.h> +#include <dev/ofw/ofw_gpio.h> #include <dev/ofw/ofw_misc.h> #include <dev/ofw/ofw_pinctrl.h> #include <dev/ofw/ofw_regulator.h> @@ -308,6 +309,8 @@ struct dwxe_softc { int dwxe_match(struct device *, void *, void *); void dwxe_attach(struct device *, struct device *, void *); int dwxe_activate(struct device *, int); +void dwxe_enable_phy_supply(int); +void dwxe_reset_phy(int); void dwxe_init(struct dwxe_softc *sc); void dwxe_phy_setup_emac(struct dwxe_softc *); void dwxe_phy_setup_gmac(struct dwxe_softc *); @@ -487,9 +490,65 @@ dwxe_activate(struct device *self, int a } void +dwxe_enable_phy_supply(int node) +{ + int n; + uint32_t supply; + char name[OFMAXPARAM]; + const char supply_str[] = "-supply"; + const int s = strlen(supply_str); + + name[0] = '\0'; + + /* scan all properties in node */ + while (1) { + if (OF_nextprop(node, name, name) < 0 || name[0] == '\0') + break; + + /* check "-supply" suffix (no leading is rejected) */ + n = strlen(name); + if (n <= s || strcmp(name + n - s, supply_str)) + continue; + + /* turn on regulators that have the suffix */ + supply = OF_getpropint(node, name, 0); + if (supply) + regulator_enable(supply); + } +} + +void +dwxe_reset_phy(int node) +{ + int len; + uint32_t *gpio, t1, t2; + + len = OF_getproplen(node, "reset-gpios"); + if (len <= 0) + return; + + gpio = malloc(len, M_TEMP, M_WAITOK); + + /* gather information, fail-safe assert/deassert timing 100ms */ + OF_getpropintarray(node, "reset-gpios", gpio, len); + t1 = OF_getpropint(node, "reset-assert-us", 100 * 1000); + t2 = OF_getpropint(node, "reset-deassert-us", 100 * 1000); + + /* perform reset sequence */ + gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT); + gpio_controller_set_pin(gpio, 1); + delay(t1); + gpio_controller_set_pin(gpio, 0); + delay(t2); + + free(gpio, M_TEMP, len); +} + +void dwxe_init(struct dwxe_softc *sc) { - uint32_t phy_supply; + uint32_t phy_supply, phy; + int node; pinctrl_byname(sc->sc_node, "default"); @@ -500,8 +559,18 @@ dwxe_init(struct dwxe_softc *sc) /* Power up PHY. */ phy_supply = OF_getpropint(sc->sc_node, "phy-supply", 0); - if (phy_supply) + phy = OF_getpropint(sc->sc_node, "phy-handle", 0); + if (phy_supply) { regulator_enable(phy_supply); + } else if (phy) { + /* + * Orange Pi 3/One Plus uses *-supply property at PHY node + * instead of phy-sypply at EMAC. And, needs PHY reset. + */ + node = OF_getnodebyphandle(phy); + dwxe_enable_phy_supply(node); + dwxe_reset_phy(node); + } /* Do hardware specific initializations. */ if (OF_is_compatible(sc->sc_node, "allwinner,sun8i-r40-gmac"))