svn commit: r296365 - head/sys/dev/dwc

Jared McNeill jmcneill at FreeBSD.org
Thu Mar 3 22:26:38 UTC 2016


Author: jmcneill
Date: Thu Mar  3 22:26:36 2016
New Revision: 296365
URL: https://svnweb.freebsd.org/changeset/base/296365

Log:
  Add support for resetting the PHY via GPIO.
  
  Submitted by:		Emmanuel Vadot <manu at bidouilliste.com>
  Reviewed by:		andrew, jmcneill
  Approved by:		adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D5505

Modified:
  head/sys/dev/dwc/if_dwc.c

Modified: head/sys/dev/dwc/if_dwc.c
==============================================================================
--- head/sys/dev/dwc/if_dwc.c	Thu Mar  3 22:25:28 2016	(r296364)
+++ head/sys/dev/dwc/if_dwc.c	Thu Mar  3 22:26:36 2016	(r296365)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/gpio.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include "if_dwc_if.h"
+#include "gpio_if.h"
 #include "miibus_if.h"
 
 #define	READ4(_sc, _reg) \
@@ -1010,6 +1012,62 @@ dwc_get_hwaddr(struct dwc_softc *sc, uin
 	return (0);
 }
 
+#define	GPIO_ACTIVE_LOW 1
+
+static int
+dwc_reset(device_t dev)
+{
+	pcell_t gpio_prop[4];
+	pcell_t delay_prop[3];
+	phandle_t node, gpio_node;
+	device_t gpio;
+	uint32_t pin, flags;
+	uint32_t pin_value;
+
+	node = ofw_bus_get_node(dev);
+	if (OF_getencprop(node, "snps,reset-gpio",
+	    gpio_prop, sizeof(gpio_prop)) <= 0)
+		return (0);
+
+	if (OF_getencprop(node, "snps,reset-delays-us",
+	    delay_prop, sizeof(delay_prop)) <= 0) {
+		device_printf(dev,
+		    "Wrong property for snps,reset-delays-us");
+		return (ENXIO);
+	}
+
+	gpio_node = OF_node_from_xref(gpio_prop[0]);
+	if ((gpio = OF_device_from_xref(gpio_prop[0])) == NULL) {
+		device_printf(dev,
+		    "Can't find gpio controller for phy reset\n");
+		return (ENXIO);
+	}
+
+	if (GPIO_MAP_GPIOS(gpio, node, gpio_node,
+	    sizeof(gpio_prop) / sizeof(gpio_prop[0]) - 1,
+	    gpio_prop + 1, &pin, &flags) != 0) {
+		device_printf(dev, "Can't map gpio for phy reset\n");
+		return (ENXIO);
+	}
+
+	pin_value = GPIO_PIN_LOW;
+	if (OF_hasprop(node, "snps,reset-active-low"))
+		pin_value = GPIO_PIN_HIGH;
+
+	if (flags & GPIO_ACTIVE_LOW)
+		pin_value = !pin_value;
+
+	GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
+	GPIO_PIN_SET(gpio, pin, pin_value);
+	DELAY(delay_prop[0]);
+	GPIO_PIN_SET(gpio, pin, !pin_value);
+	DELAY(delay_prop[1]);
+	GPIO_PIN_SET(gpio, pin, pin_value);
+	DELAY(delay_prop[2]);
+
+	return (0);
+}
+
 static int
 dwc_probe(device_t dev)
 {
@@ -1058,6 +1116,12 @@ dwc_attach(device_t dev)
 		return (ENXIO);
 	}
 
+	/* Reset the PHY if needed */
+	if (dwc_reset(dev) != 0) {
+		device_printf(dev, "Can't reset the PHY\n");
+		return (ENXIO);
+	}
+
 	/* Reset */
 	reg = READ4(sc, BUS_MODE);
 	reg |= (BUS_MODE_SWR);


More information about the svn-src-head mailing list