From owner-svn-src-stable@FreeBSD.ORG Thu May 15 15:15:24 2014 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D4E082EE; Thu, 15 May 2014 15:15:24 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B7AE12254; Thu, 15 May 2014 15:15:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4FFFOFE044042; Thu, 15 May 2014 15:15:24 GMT (envelope-from loos@svn.freebsd.org) Received: (from loos@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4FFFNW9044037; Thu, 15 May 2014 15:15:23 GMT (envelope-from loos@svn.freebsd.org) Message-Id: <201405151515.s4FFFNW9044037@svn.freebsd.org> From: Luiz Otavio O Souza Date: Thu, 15 May 2014 15:15:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r266135 - in stable/10/sys/dev: gpio ofw X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 May 2014 15:15:25 -0000 Author: loos Date: Thu May 15 15:15:23 2014 New Revision: 266135 URL: http://svnweb.freebsd.org/changeset/base/266135 Log: MFC r265012, r265191, r265289, r265310 r265012: Fix the gpio-specifier decoding by respecting the GPIO controller's #gpio-cells property. Add a new ofw_bus method (OFW_BUS_MAP_GPIOS()) that allows the GPIO controller to implement its own mapping to deal with gpio-specifiers, allowing the decoding of gpio-specifiers to be controller specific. The default ofw_bus_map_gpios() decodes the linux standard (#gpio-cells = <2>) and the FreeBSD standard (#gpio-cells = <3>). It pass the gpio-specifier flag field to the children as an ivar variable so they can act upon. r265191: Remove unnecessary headers. Sort out the headers. Add a missing header on ofw_gpiobus.c (it was working because of sys/libkern.h). r265289: eally sort out the headers. sys/systm.h must always come after sys/param.h. Remove sys/types.h which should never be included together with sys/param.h. Add sys/malloc.h for correctness even if it seems to don't be needed. Remove more unused headers found by unusedinc (from bde@). r265310: Move gpiobus routines to dev/gpio. Avoid polluting ofw_bus with bus specific parts. Modified: stable/10/sys/dev/gpio/gpio_if.m stable/10/sys/dev/gpio/gpiobus.c stable/10/sys/dev/gpio/gpiobusvar.h stable/10/sys/dev/gpio/ofw_gpiobus.c stable/10/sys/dev/ofw/ofw_bus_if.m Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/gpio/gpio_if.m ============================================================================== --- stable/10/sys/dev/gpio/gpio_if.m Thu May 15 15:14:37 2014 (r266134) +++ stable/10/sys/dev/gpio/gpio_if.m Thu May 15 15:15:23 2014 (r266135) @@ -31,6 +31,32 @@ INTERFACE gpio; +CODE { + static gpio_map_gpios_t gpio_default_map_gpios; + + int + gpio_default_map_gpios(device_t bus, phandle_t dev, + phandle_t gparent, int gcells, pcell_t *gpios, uint32_t *pin, + uint32_t *flags) + { + /* Propagate up the bus hierarchy until someone handles it. */ + if (device_get_parent(bus) != NULL) + return (GPIO_MAP_GPIOS(device_get_parent(bus), dev, + gparent, gcells, gpios, pin, flags)); + + /* If that fails, then assume the FreeBSD defaults. */ + *pin = gpios[0]; + if (gcells == 2 || gcells == 3) + *flags = gpios[gcells - 1]; + + return (0); + } +}; + +HEADER { + #include +}; + # # Get total number of pins # @@ -100,3 +126,16 @@ METHOD int pin_setflags { uint32_t pin_num; uint32_t flags; }; + +# +# Allow the GPIO controller to map the gpio-specifier on its own. +# +METHOD int map_gpios { + device_t bus; + phandle_t dev; + phandle_t gparent; + int gcells; + pcell_t *gpios; + uint32_t *pin; + uint32_t *flags; +} DEFAULT gpio_default_map_gpios; Modified: stable/10/sys/dev/gpio/gpiobus.c ============================================================================== --- stable/10/sys/dev/gpio/gpiobus.c Thu May 15 15:14:37 2014 (r266134) +++ stable/10/sys/dev/gpio/gpiobus.c Thu May 15 15:15:23 2014 (r266135) @@ -29,21 +29,13 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include -#include "gpio_if.h" + #include "gpiobus_if.h" static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); Modified: stable/10/sys/dev/gpio/gpiobusvar.h ============================================================================== --- stable/10/sys/dev/gpio/gpiobusvar.h Thu May 15 15:14:37 2014 (r266134) +++ stable/10/sys/dev/gpio/gpiobusvar.h Thu May 15 15:15:23 2014 (r266135) @@ -32,7 +32,6 @@ #include "opt_platform.h" -#include #include #include @@ -40,6 +39,8 @@ #include #endif +#include "gpio_if.h" + #define GPIOBUS_IVAR(d) (struct gpiobus_ivar *) device_get_ivars(d) #define GPIOBUS_SOFTC(d) (struct gpiobus_softc *) device_get_softc(d) #define GPIOBUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) @@ -60,17 +61,29 @@ struct gpiobus_softc int *sc_pins_mapped; /* mark mapped pins */ }; - struct gpiobus_ivar { uint32_t npins; /* pins total */ + uint32_t *flags; /* pins flags */ uint32_t *pins; /* pins map */ }; -void gpiobus_print_pins(struct gpiobus_ivar *); #ifdef FDT +struct ofw_gpiobus_devinfo { + struct gpiobus_ivar opd_dinfo; + struct ofw_bus_devinfo opd_obdinfo; +}; + +static __inline int +gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, + pcell_t *gpios, uint32_t *pin, uint32_t *flags) +{ + return (GPIO_MAP_GPIOS(bus, dev, gparent, gcells, gpios, pin, flags)); +} + device_t ofw_gpiobus_add_fdt_child(device_t, phandle_t); #endif +void gpiobus_print_pins(struct gpiobus_ivar *); extern driver_t gpiobus_driver; Modified: stable/10/sys/dev/gpio/ofw_gpiobus.c ============================================================================== --- stable/10/sys/dev/gpio/ofw_gpiobus.c Thu May 15 15:14:37 2014 (r266134) +++ stable/10/sys/dev/gpio/ofw_gpiobus.c Thu May 15 15:15:23 2014 (r266135) @@ -30,27 +30,14 @@ __FBSDID("$FreeBSD$"); #include +#include #include -#include #include -#include -#include +#include #include -#include #include #include -#include - -#include - -#include "gpio_if.h" -#include "gpiobus_if.h" - -struct ofw_gpiobus_devinfo { - struct gpiobus_ivar opd_dinfo; - struct ofw_bus_devinfo opd_obdinfo; -}; static int ofw_gpiobus_parse_gpios(struct gpiobus_softc *, struct gpiobus_ivar *, phandle_t); @@ -83,10 +70,37 @@ ofw_gpiobus_add_fdt_child(device_t bus, } static int +ofw_gpiobus_alloc_ivars(struct gpiobus_ivar *dinfo) +{ + + /* Allocate pins and flags memory. */ + dinfo->pins = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, + M_NOWAIT | M_ZERO); + if (dinfo->pins == NULL) + return (ENOMEM); + dinfo->flags = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, + M_NOWAIT | M_ZERO); + if (dinfo->flags == NULL) { + free(dinfo->pins, M_DEVBUF); + return (ENOMEM); + } + + return (0); +} + +static void +ofw_gpiobus_free_ivars(struct gpiobus_ivar *dinfo) +{ + + free(dinfo->flags, M_DEVBUF); + free(dinfo->pins, M_DEVBUF); +} + +static int ofw_gpiobus_parse_gpios(struct gpiobus_softc *sc, struct gpiobus_ivar *dinfo, phandle_t child) { - int i, len; + int cells, i, j, len; pcell_t *gpios; phandle_t gpio; @@ -102,44 +116,81 @@ ofw_gpiobus_parse_gpios(struct gpiobus_s } /* - * Each 'gpios' entry must contain 4 pcells. - * The first one is the GPIO controller phandler. - * Then the last three are the GPIO pin, the GPIO pin direction and - * the GPIO pin flags. + * The gpio-specifier is controller independent, but the first pcell + * has the reference to the GPIO controller phandler. + * One the first pass we count the number of encoded gpio-specifiers. */ - if ((len / sizeof(pcell_t)) % 4) { + i = 0; + len /= sizeof(pcell_t); + while (i < len) { + /* Allow NULL specifiers. */ + if (gpios[i] == 0) { + dinfo->npins++; + i++; + continue; + } + gpio = OF_xref_phandle(gpios[i]); + /* Verify if we're attaching to the correct GPIO controller. */ + if (!OF_hasprop(gpio, "gpio-controller") || + gpio != ofw_bus_get_node(sc->sc_dev)) { + free(gpios, M_DEVBUF); + return (EINVAL); + } + /* Read gpio-cells property for this GPIO controller. */ + if (OF_getencprop(gpio, "#gpio-cells", &cells, + sizeof(cells)) < 0) { + free(gpios, M_DEVBUF); + return (EINVAL); + } + dinfo->npins++; + i += cells + 1; + } + + if (dinfo->npins == 0) { free(gpios, M_DEVBUF); return (EINVAL); } - dinfo->npins = len / (sizeof(pcell_t) * 4); - dinfo->pins = malloc(sizeof(uint32_t) * dinfo->npins, M_DEVBUF, - M_NOWAIT | M_ZERO); - if (dinfo->pins == NULL) { + + /* Allocate the child resources. */ + if (ofw_gpiobus_alloc_ivars(dinfo) != 0) { free(gpios, M_DEVBUF); return (ENOMEM); } - for (i = 0; i < dinfo->npins; i++) { + /* Decode the gpio specifier on the second pass. */ + i = 0; + j = 0; + while (i < len) { + /* Allow NULL specifiers. */ + if (gpios[i] == 0) { + i++; + j++; + continue; + } - /* Verify if we're attaching to the correct gpio controller. */ - gpio = OF_xref_phandle(gpios[i * 4 + 0]); - if (!OF_hasprop(gpio, "gpio-controller") || - gpio != ofw_bus_get_node(sc->sc_dev)) { - free(dinfo->pins, M_DEVBUF); + gpio = OF_xref_phandle(gpios[i]); + /* Read gpio-cells property for this GPIO controller. */ + if (OF_getencprop(gpio, "#gpio-cells", &cells, + sizeof(cells)) < 0) { + ofw_gpiobus_free_ivars(dinfo); free(gpios, M_DEVBUF); return (EINVAL); } - /* Get the GPIO pin number. */ - dinfo->pins[i] = gpios[i * 4 + 1]; - /* gpios[i * 4 + 2] - GPIO pin direction */ - /* gpios[i * 4 + 3] - GPIO pin flags */ + /* Get the GPIO pin number and flags. */ + if (gpio_map_gpios(sc->sc_dev, child, gpio, cells, + &gpios[i + 1], &dinfo->pins[j], &dinfo->flags[j]) != 0) { + ofw_gpiobus_free_ivars(dinfo); + free(gpios, M_DEVBUF); + return (EINVAL); + } - if (dinfo->pins[i] > sc->sc_npins) { + /* Consistency check. */ + if (dinfo->pins[j] > sc->sc_npins) { device_printf(sc->sc_busdev, "invalid pin %d, max: %d\n", - dinfo->pins[i], sc->sc_npins - 1); - free(dinfo->pins, M_DEVBUF); + dinfo->pins[j], sc->sc_npins - 1); + ofw_gpiobus_free_ivars(dinfo); free(gpios, M_DEVBUF); return (EINVAL); } @@ -147,15 +198,18 @@ ofw_gpiobus_parse_gpios(struct gpiobus_s /* * Mark pin as mapped and give warning if it's already mapped. */ - if (sc->sc_pins_mapped[dinfo->pins[i]]) { + if (sc->sc_pins_mapped[dinfo->pins[j]]) { device_printf(sc->sc_busdev, "warning: pin %d is already mapped\n", - dinfo->pins[i]); - free(dinfo->pins, M_DEVBUF); + dinfo->pins[j]); + ofw_gpiobus_free_ivars(dinfo); free(gpios, M_DEVBUF); return (EINVAL); } - sc->sc_pins_mapped[dinfo->pins[i]] = 1; + sc->sc_pins_mapped[dinfo->pins[j]] = 1; + + i += cells + 1; + j++; } free(gpios, M_DEVBUF); Modified: stable/10/sys/dev/ofw/ofw_bus_if.m ============================================================================== --- stable/10/sys/dev/ofw/ofw_bus_if.m Thu May 15 15:14:37 2014 (r266134) +++ stable/10/sys/dev/ofw/ofw_bus_if.m Thu May 15 15:15:23 2014 (r266135) @@ -169,5 +169,3 @@ METHOD int map_intr { int icells; pcell_t *interrupt; } DEFAULT ofw_bus_default_map_intr; - -