Module Name: src Committed By: jmcneill Date: Thu Nov 30 21:36:11 UTC 2017
Modified Files: src/sys/arch/arm/sunxi: sunxi_emac.c Log Message: Add support for new emac bindings To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/sunxi/sunxi_emac.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/sunxi/sunxi_emac.c diff -u src/sys/arch/arm/sunxi/sunxi_emac.c:1.9 src/sys/arch/arm/sunxi/sunxi_emac.c:1.10 --- src/sys/arch/arm/sunxi/sunxi_emac.c:1.9 Thu Nov 16 03:07:17 2017 +++ src/sys/arch/arm/sunxi/sunxi_emac.c Thu Nov 30 21:36:11 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_emac.c,v 1.9 2017/11/16 03:07:17 ozaki-r Exp $ */ +/* $NetBSD: sunxi_emac.c,v 1.10 2017/11/30 21:36:11 jmcneill Exp $ */ /*- * Copyright (c) 2016-2017 Jared McNeill <jmcne...@invisible.ca> @@ -33,7 +33,7 @@ #include "opt_net_mpsafe.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.9 2017/11/16 03:07:17 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.10 2017/11/30 21:36:11 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -97,23 +97,24 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c #define PAUSE_TIME_DEFAULT 0x400 /* syscon EMAC clock register */ -#define EMAC_CLK_EPHY_ADDR (0x1f << 20) /* H3 */ -#define EMAC_CLK_EPHY_ADDR_SHIFT 20 -#define EMAC_CLK_EPHY_LED_POL (1 << 17) /* H3 */ -#define EMAC_CLK_EPHY_SHUTDOWN (1 << 16) /* H3 */ -#define EMAC_CLK_EPHY_SELECT (1 << 15) /* H3 */ -#define EMAC_CLK_RMII_EN (1 << 13) -#define EMAC_CLK_ETXDC (0x7 << 10) -#define EMAC_CLK_ETXDC_SHIFT 10 -#define EMAC_CLK_ERXDC (0x1f << 5) -#define EMAC_CLK_ERXDC_SHIFT 5 -#define EMAC_CLK_PIT (0x1 << 2) -#define EMAC_CLK_PIT_MII (0 << 2) -#define EMAC_CLK_PIT_RGMII (1 << 2) -#define EMAC_CLK_SRC (0x3 << 0) -#define EMAC_CLK_SRC_MII (0 << 0) -#define EMAC_CLK_SRC_EXT_RGMII (1 << 0) -#define EMAC_CLK_SRC_RGMII (2 << 0) +#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 */ +#define EMAC_CLK_EPHY_SHUTDOWN (1 << 16) /* H3 */ +#define EMAC_CLK_EPHY_SELECT (1 << 15) /* H3 */ +#define EMAC_CLK_RMII_EN (1 << 13) +#define EMAC_CLK_ETXDC (0x7 << 10) +#define EMAC_CLK_ETXDC_SHIFT 10 +#define EMAC_CLK_ERXDC (0x1f << 5) +#define EMAC_CLK_ERXDC_SHIFT 5 +#define EMAC_CLK_PIT (0x1 << 2) +#define EMAC_CLK_PIT_MII (0 << 2) +#define EMAC_CLK_PIT_RGMII (1 << 2) +#define EMAC_CLK_SRC (0x3 << 0) +#define EMAC_CLK_SRC_MII (0 << 0) +#define EMAC_CLK_SRC_EXT_RGMII (1 << 0) +#define EMAC_CLK_SRC_RGMII (2 << 0) /* Burst length of RX and TX DMA transfers */ static int sunxi_emac_burst_len = BURST_LEN_DEFAULT; @@ -889,6 +890,27 @@ sunxi_emac_ioctl(struct ifnet *ifp, u_lo return error; } +static bool +sunxi_emac_has_internal_phy(struct sunxi_emac_softc *sc) +{ + const char * mdio_internal_compat[] = { + "allwinner,sun8i-h3-mdio-internal", + NULL + }; + int phy; + + /* Non-standard property, for compatible with old dts files */ + if (of_hasprop(sc->phandle, "allwinner,use-internal-phy")) + return true; + + phy = fdtbus_get_phandle(sc->phandle, "phy-handle"); + if (phy == -1) + return false; + + /* For internal PHY, check compatible string of parent node */ + return of_compatible(OF_parent(phy), mdio_internal_compat) >= 0; +} + static int sunxi_emac_setup_phy(struct sunxi_emac_softc *sc) { @@ -921,7 +943,7 @@ sunxi_emac_setup_phy(struct sunxi_emac_s } if (sc->type == EMAC_H3) { - if (of_hasprop(sc->phandle, "allwinner,use-internal-phy")) { + if (sunxi_emac_has_internal_phy(sc)) { reg |= EMAC_CLK_EPHY_SELECT; reg &= ~EMAC_CLK_EPHY_SHUTDOWN; if (of_hasprop(sc->phandle, @@ -1262,15 +1284,31 @@ sunxi_emac_get_resources(struct sunxi_em { const int phandle = sc->phandle; bus_addr_t addr, size; - u_int n; - /* Map registers */ - for (n = 0; n < _RES_NITEMS; n++) { - if (fdtbus_get_reg(phandle, n, &addr, &size) != 0) + /* Map EMAC registers */ + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) + return ENXIO; + if (bus_space_map(sc->bst, addr, size, 0, &sc->bsh[_RES_EMAC]) != 0) + return ENXIO; + + /* Map SYSCON registers */ + if (of_hasprop(phandle, "syscon")) { + const int syscon_phandle = fdtbus_get_phandle(phandle, + "syscon"); + if (syscon_phandle == -1) + return ENXIO; + if (fdtbus_get_reg(syscon_phandle, 0, &addr, &size) != 0) return ENXIO; - if (bus_space_map(sc->bst, addr, size, 0, &sc->bsh[n]) != 0) + if (size < EMAC_CLK_REG + 4) + return ENXIO; + addr += EMAC_CLK_REG; + size -= EMAC_CLK_REG; + } else { + if (fdtbus_get_reg(phandle, 1, &addr, &size) != 0) return ENXIO; } + if (bus_space_map(sc->bst, addr, size, 0, &sc->bsh[_RES_SYSCON]) != 0) + return ENXIO; /* Get clocks and resets. "ahb" is required, "ephy" is optional. */