Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Jan 2018 14:29:29 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r327825 - head/sys/arm/allwinner
Message-ID:  <201801111429.w0BETTUl058769@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Thu Jan 11 14:29:29 2018
New Revision: 327825
URL: https://svnweb.freebsd.org/changeset/base/327825

Log:
  if_awg: Support new emac bindings
  
  Highlights of the new bindings:
  - ahb clock is specified as 'stmmaceth'
  - The PHY to be used is now specified as phy-handle
  - We must now check the parent of the node phy-handle points to in order to
  discover if we're using internal PHY.
  - The ephy clk/reset will be specified on the PHY node, not the emac node.
  
  Care has been taken to ensure that we remain compatible with the older
  bindings that we were previously using.
  
  Tested on:	Pine64 (A64, old bindings)
  Tested on:	Pine64-LTS (A64, new bindings) [manu]
  Tested on:	OrangePi-One (H3, internal PHY) [manu]
  Tested on:	NanoPi M1 Plus (H3, external PHY) [manu]
  Reviewed by:	manu
  Differential Revision:	https://reviews.freebsd.org/D13777

Modified:
  head/sys/arm/allwinner/if_awg.c

Modified: head/sys/arm/allwinner/if_awg.c
==============================================================================
--- head/sys/arm/allwinner/if_awg.c	Thu Jan 11 14:21:07 2018	(r327824)
+++ head/sys/arm/allwinner/if_awg.c	Thu Jan 11 14:29:29 2018	(r327825)
@@ -223,6 +223,8 @@ 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 phandle_t awg_get_phy_node(device_t dev);
+static bool awg_has_internal_phy(device_t dev);
 
 static int
 awg_miibus_readreg(device_t dev, int phy, int reg)
@@ -1186,6 +1188,35 @@ syscon_write_emac_clk_reg(device_t dev, uint32_t val)
 		bus_write_4(sc->res[_RES_SYSCON], 0, val);
 }
 
+static phandle_t
+awg_get_phy_node(device_t dev)
+{
+	phandle_t node;
+	pcell_t phy_handle;
+
+	node = ofw_bus_get_node(dev);
+	if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
+	    sizeof(phy_handle)) <= 0)
+		return (0);
+
+	return (OF_node_from_xref(phy_handle));
+}
+
+static bool
+awg_has_internal_phy(device_t dev)
+{
+	phandle_t node, phy_node;
+
+	node = ofw_bus_get_node(dev);
+	/* Legacy binding */
+	if (OF_hasprop(node, "allwinner,use-internal-phy"))
+		return (true);
+
+	phy_node = awg_get_phy_node(dev);
+	return (phy_node != 0 && ofw_bus_node_is_compatible(OF_parent(phy_node),
+	    "allwinner,sun8i-h3-mdio-internal") != 0);
+}
+
 static int
 awg_setup_phy(device_t dev)
 {
@@ -1241,7 +1272,7 @@ awg_setup_phy(device_t dev)
 		}
 
 		if (sc->type == EMAC_H3) {
-			if (OF_hasprop(node, "allwinner,use-internal-phy")) {
+			if (awg_has_internal_phy(dev)) {
 				reg |= EMAC_CLK_EPHY_SELECT;
 				reg &= ~EMAC_CLK_EPHY_SHUTDOWN;
 				if (OF_hasprop(node,
@@ -1308,7 +1339,7 @@ static int
 awg_setup_extres(device_t dev)
 {
 	struct awg_softc *sc;
-	phandle_t node;
+	phandle_t node, phy_node;
 	hwreset_t rst_ahb, rst_ephy;
 	clk_t clk_ahb, clk_ephy;
 	regulator_t reg;
@@ -1320,22 +1351,37 @@ awg_setup_extres(device_t dev)
 	clk_ahb = clk_ephy = NULL;
 	reg = NULL;
 	node = ofw_bus_get_node(dev);
+	phy_node = awg_get_phy_node(dev);
 
+	if (phy_node == 0 && OF_hasprop(node, "phy-handle")) {
+		error = ENXIO;
+		device_printf(dev, "cannot get phy handle\n");
+		goto fail;
+	}
+
 	/* Get AHB clock and reset resources */
-	error = hwreset_get_by_ofw_name(dev, 0, "ahb", &rst_ahb);
+	error = hwreset_get_by_ofw_name(dev, 0, "stmmaceth", &rst_ahb);
+	if (error != 0)
+		error = hwreset_get_by_ofw_name(dev, 0, "ahb", &rst_ahb);
 	if (error != 0) {
 		device_printf(dev, "cannot get ahb reset\n");
 		goto fail;
 	}
 	if (hwreset_get_by_ofw_name(dev, 0, "ephy", &rst_ephy) != 0)
-		rst_ephy = NULL;
-	error = clk_get_by_ofw_name(dev, 0, "ahb", &clk_ahb);
+		if (phy_node == 0 || hwreset_get_by_ofw_idx(dev, phy_node, 0,
+		    &rst_ephy) != 0)
+			rst_ephy = NULL;
+	error = clk_get_by_ofw_name(dev, 0, "stmmaceth", &clk_ahb);
+	if (error != 0)
+		error = clk_get_by_ofw_name(dev, 0, "ahb", &clk_ahb);
 	if (error != 0) {
 		device_printf(dev, "cannot get ahb clock\n");
 		goto fail;
 	}
 	if (clk_get_by_ofw_name(dev, 0, "ephy", &clk_ephy) != 0)
-		clk_ephy = NULL;
+		if (phy_node == 0 || clk_get_by_ofw_index(dev, phy_node, 0,
+		    &clk_ephy) != 0)
+			clk_ephy = NULL;
 
 	if (OF_hasprop(node, "syscon") && syscon_get_by_ofw_property(dev, node,
 	    "syscon", &sc->syscon) != 0) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801111429.w0BETTUl058769>