Date: Thu, 3 Mar 2016 22:26:37 +0000 (UTC) From: Jared McNeill <jmcneill@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r296365 - head/sys/dev/dwc Message-ID: <201603032226.u23MQbfO005502@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603032226.u23MQbfO005502>