Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Apr 2018 14:05:44 +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: r332327 - head/sys/arm/allwinner
Message-ID:  <201804091405.w39E5in8049357@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Mon Apr  9 14:05:43 2018
New Revision: 332327
URL: https://svnweb.freebsd.org/changeset/base/332327

Log:
  if_awg: Add support for allwinner,{tx,rx}-delay-ps bindings
  
  Split out delay parsing into a separate function; we'll support both
  {tx,rx}-delay as well as the new versions.
  
  While here, validate that they're within the expected range and fail to
  attach if they are not. Assuming that we can clamp the delay is a bad idea
  that might result in a non-working awg anyways, so we'll fail early to make
  it easier to catch.
  
  This version also unsets the tx and rx delay registers unconditionally and
  then sets them if we read a non-zero delay. These delay properties should
  default to 0 if not specified, as declared in the binding documentation.
  Presumably the delays will be set via hardware configuration if they're not
  explicitly set in FDT.

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

Modified: head/sys/arm/allwinner/if_awg.c
==============================================================================
--- head/sys/arm/allwinner/if_awg.c	Mon Apr  9 13:32:12 2018	(r332326)
+++ head/sys/arm/allwinner/if_awg.c	Mon Apr  9 14:05:43 2018	(r332327)
@@ -221,6 +221,8 @@ static struct resource_spec awg_spec[] = {
 
 static void awg_txeof(struct awg_softc *sc);
 
+static int awg_parse_delay(device_t dev, uint32_t *tx_delay,
+    uint32_t *rx_delay);
 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);
@@ -1218,6 +1220,50 @@ awg_has_internal_phy(device_t dev)
 }
 
 static int
+awg_parse_delay(device_t dev, uint32_t *tx_delay, uint32_t *rx_delay)
+{
+	phandle_t node;
+	uint32_t delay;
+
+	if (tx_delay == NULL || rx_delay == NULL)
+		return (EINVAL);
+	*tx_delay = *rx_delay = 0;
+	node = ofw_bus_get_node(dev);
+
+	if (OF_getencprop(node, "tx-delay", &delay, sizeof(delay)) >= 0)
+		*tx_delay = delay;
+	else if (OF_getencprop(node, "allwinner,tx-delay-ps", &delay,
+	    sizeof(delay)) >= 0) {
+		if ((delay % 100) != 0) {
+			device_printf(dev, "tx-delay-ps is not a multiple of 100\n");
+			return (EDOM);
+		}
+		*tx_delay = delay / 100;
+	}
+	if (*tx_delay > 7) {
+		device_printf(dev, "tx-delay out of range\n");
+		return (ERANGE);
+	}
+
+	if (OF_getencprop(node, "rx-delay", &delay, sizeof(delay)) >= 0)
+		*rx_delay = delay;
+	else if (OF_getencprop(node, "allwinner,rx-delay-ps", &delay,
+	    sizeof(delay)) >= 0) {
+		if ((delay % 100) != 0) {
+			device_printf(dev, "rx-delay-ps is not within documented domain\n");
+			return (EDOM);
+		}
+		*rx_delay = delay / 100;
+	}
+	if (*rx_delay > 31) {
+		device_printf(dev, "rx-delay out of range\n");
+		return (ERANGE);
+	}
+
+	return (0);
+}
+
+static int
 awg_setup_phy(device_t dev)
 {
 	struct awg_softc *sc;
@@ -1260,16 +1306,22 @@ awg_setup_phy(device_t dev)
 		else
 			reg |= EMAC_CLK_PIT_MII | EMAC_CLK_SRC_MII;
 
-		if (OF_getencprop(node, "tx-delay", &tx_delay,
-		    sizeof(tx_delay)) > 0) {
-			reg &= ~EMAC_CLK_ETXDC;
+		/*
+		 * Fail attach if we fail to parse either of the delay
+		 * parameters. If we don't have the proper delay to write to
+		 * syscon, then awg likely won't function properly anyways.
+		 * Lack of delay is not an error!
+		 */
+		error = awg_parse_delay(dev, &tx_delay, &rx_delay);
+		if (error != 0)
+			goto fail;
+
+		/* Default to 0 and we'll increase it if we need to. */
+		reg &= ~(EMAC_CLK_ETXDC | EMAC_CLK_ERXDC);
+		if (tx_delay > 0)
 			reg |= (tx_delay << EMAC_CLK_ETXDC_SHIFT);
-		}
-		if (OF_getencprop(node, "rx-delay", &rx_delay,
-		    sizeof(rx_delay)) > 0) {
-			reg &= ~EMAC_CLK_ERXDC;
+		if (rx_delay > 0)
 			reg |= (rx_delay << EMAC_CLK_ERXDC_SHIFT);
-		}
 
 		if (sc->type == EMAC_H3) {
 			if (awg_has_internal_phy(dev)) {



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