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"))

Reply via email to