Index: sys/arm/allwinner/if_awg.c =================================================================== --- sys/arm/allwinner/if_awg.c +++ sys/arm/allwinner/if_awg.c @@ -70,6 +70,7 @@ #include #include +#include "syscon_if.h" #include "miibus_if.h" #include "gpio_if.h" @@ -105,6 +106,7 @@ #define RX_BATCH_DEFAULT 64 /* syscon EMAC clock register */ +#define EMAC_CLK_REG 0x30 #define EMAC_CLK_EPHY_ADDR (0x1f << 20) /* H3 */ #define EMAC_CLK_EPHY_ADDR_SHIFT 20 #define EMAC_CLK_EPHY_LED_POL (1 << 17) /* H3 */ @@ -203,6 +205,7 @@ int link; int if_flags; enum awg_type type; + device_t syscon; struct awg_txring tx; struct awg_rxring rx; @@ -217,6 +220,9 @@ static void awg_txeof(struct awg_softc *sc); +static uint32_t syscon_read_emac_clk_reg(device_t dev); +static void syscon_write_emac_clk_reg(device_t dev, uint32_t val); + static int awg_miibus_readreg(device_t dev, int phy, int reg) { @@ -1153,6 +1159,32 @@ return (error); } +static uint32_t +syscon_read_emac_clk_reg(device_t dev) +{ + struct awg_softc *sc; + + sc = device_get_softc(dev); + if (sc->syscon != NULL) + return (SYSCON_READ_4(sc->syscon, dev, EMAC_CLK_REG)); + else if (sc->res[_RES_SYSCON] != NULL) + return (bus_read_4(sc->res[_RES_SYSCON], 0)); + + return (0); +} + +static void +syscon_write_emac_clk_reg(device_t dev, uint32_t val) +{ + struct awg_softc *sc; + + sc = device_get_softc(dev); + if (sc->syscon != NULL) + SYSCON_WRITE_4(sc->syscon, dev, EMAC_CLK_REG, val); + else if (sc->res[_RES_SYSCON] != NULL) + bus_write_4(sc->res[_RES_SYSCON], 0, val); +} + static int awg_setup_phy(device_t dev) { @@ -1163,19 +1195,31 @@ phandle_t node; uint32_t reg, tx_delay, rx_delay; int error; + bool use_syscon; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); + use_syscon = false; if (OF_getprop_alloc(node, "phy-mode", 1, (void **)&phy_type) == 0) return (0); + if (sc->syscon != NULL || sc->res[_RES_SYSCON] != NULL) + use_syscon = true; + if (bootverbose) device_printf(dev, "PHY type: %s, conf mode: %s\n", phy_type, - sc->res[_RES_SYSCON] != NULL ? "reg" : "clk"); + use_syscon ? "reg" : "clk"); - if (sc->res[_RES_SYSCON] != NULL) { - reg = bus_read_4(sc->res[_RES_SYSCON], 0); + if (use_syscon) { + /* + * Abstract away writing to syscon for devices like the pine64. + * For the pine64, we get dtb from U-Boot and it still uses the + * legacy setup of specifying syscon register in emac node + * rather than as its own node and using an xref in emac. + * These abstractions can go away once U-Boot dts is up-to-date. + */ + reg = syscon_read_emac_clk_reg(dev); reg &= ~(EMAC_CLK_PIT | EMAC_CLK_SRC | EMAC_CLK_RMII_EN); if (strcmp(phy_type, "rgmii") == 0) reg |= EMAC_CLK_PIT_RGMII | EMAC_CLK_SRC_RGMII; @@ -1215,7 +1259,7 @@ if (bootverbose) device_printf(dev, "EMAC clock: 0x%08x\n", reg); - bus_write_4(sc->res[_RES_SYSCON], 0, reg); + syscon_write_emac_clk_reg(dev, reg); } else { if (strcmp(phy_type, "rgmii") == 0) tx_parent_name = "emac_int_tx"; @@ -1713,14 +1757,22 @@ { uint8_t eaddr[ETHER_ADDR_LEN]; struct awg_softc *sc; - phandle_t node; - int error; + phandle_t node, syscon_xref; + int error, len; sc = device_get_softc(dev); sc->dev = dev; sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + sc->syscon = NULL; node = ofw_bus_get_node(dev); + if (OF_hasprop(node, "syscon")) { + len = OF_getencprop(node, "syscon", &syscon_xref, + sizeof(syscon_xref)); + if (len > 0) + sc->syscon = OF_device_from_xref(syscon_xref); + } + if (bus_alloc_resources(dev, awg_spec, sc->res) != 0) { device_printf(dev, "cannot allocate resources for device\n"); return (ENXIO);