The Ethernet MAC used in newer Allwinner SoCs (H3, A64, H5) got an upstream Linux driver in v4.15. This one uses a slightly different binding from the original one used by the U-Boot driver. The differences to the old binding are: - The "syscon" address is held in a separate node, referenced via a phandle in the "syscon" property. - The reference to the PHY is held in a property called "phy-handle", not "phy". - The PHY register is at offset 0x30 in the syscon device, not at 0. - The internal PHY is activated when the node, which phy-handle points to, is a child node of an "allwinner,sun8i-h3-mdio-internal" node.
Teach the U-Boot driver how to find its resources in a "new-style" DT, so that we can use a Linux kernel compatible DT for U-Boot as well. This keeps support for the old binding for now, to allow a smooth transition. Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- drivers/net/sun8i_emac.c | 55 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index df2b857310..4ba8959239 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -279,7 +279,7 @@ static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) int ret; u32 reg; - reg = readl(priv->sysctl_reg); + reg = readl(priv->sysctl_reg + 0x30); if (priv->variant == H3_EMAC) { ret = sun8i_emac_set_syscon_ephy(priv, ®); @@ -310,7 +310,7 @@ static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) return -EINVAL; } - writel(reg, priv->sysctl_reg); + writel(reg, priv->sysctl_reg + 0x30); return 0; } @@ -806,17 +806,50 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev) #endif pdata->iobase = devfdt_get_addr_name(dev, "emac"); + if (pdata->iobase == FDT_ADDR_T_NONE) + pdata->iobase = devfdt_get_addr(dev); + if (pdata->iobase == FDT_ADDR_T_NONE) { + debug("%s: Cannot find MAC base address\n", __func__); + return -EINVAL; + } + priv->sysctl_reg = devfdt_get_addr_name(dev, "syscon"); + if (priv->sysctl_reg == FDT_ADDR_T_NONE) { + const fdt32_t *reg; + + offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "syscon"); + if (offset < 0) { + debug("%s: cannot find syscon node\n", __func__); + return -EINVAL; + } + reg = fdt_getprop(gd->fdt_blob, offset, "reg", NULL); + if (!reg) { + debug("%s: cannot find reg property in syscon node\n", + __func__); + return -EINVAL; + } + priv->sysctl_reg = fdt_translate_address((void *)gd->fdt_blob, + offset, reg); + } else + priv->sysctl_reg -= 0x30; + if (priv->sysctl_reg == FDT_ADDR_T_NONE) { + debug("%s: Cannot find syscon base address\n", __func__); + return -EINVAL; + } pdata->phy_interface = -1; priv->phyaddr = -1; priv->use_internal_phy = false; - offset = fdtdec_lookup_phandle(gd->fdt_blob, node, - "phy"); - if (offset > 0) - priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", - -1); + offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy"); + if (offset < 0) + offset = fdtdec_lookup_phandle(gd->fdt_blob, node, + "phy-handle"); + if (offset < 0) { + debug("%s: Cannot find PHY address\n", __func__); + return -EINVAL; + } + priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1); phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL); @@ -841,6 +874,14 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev) if (fdt_getprop(gd->fdt_blob, node, "allwinner,use-internal-phy", NULL)) priv->use_internal_phy = true; + else { + int parent = fdt_parent_offset(gd->fdt_blob, offset); + + if (parent >= 0 && + !fdt_node_check_compatible(gd->fdt_blob, parent, + "allwinner,sun8i-h3-mdio-internal")) + priv->use_internal_phy = true; + } } priv->interface = pdata->phy_interface; -- 2.14.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot