Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 May 2014 15:15:23 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
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
Message-ID:  <201405151515.s4FFFNW9044037@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <dev/ofw/openfirm.h>
+};
+
 #
 # 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 <sys/param.h>
 #include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
-#include <sys/kernel.h>
-#include <sys/queue.h>
-#include <sys/sysctl.h>
-#include <sys/types.h>
 
-#include <sys/bus.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
-#include <machine/resource.h>
-
-#include <sys/gpio.h>
 #include <dev/gpio/gpiobusvar.h>
-#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 <sys/param.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 
@@ -40,6 +39,8 @@
 #include <dev/ofw/ofw_bus_subr.h>
 #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 <sys/param.h>
+#include <sys/systm.h>
 #include <sys/bus.h>
-#include <sys/gpio.h>
 #include <sys/kernel.h>
-#include <sys/libkern.h>
-#include <sys/lock.h>
+#include <sys/malloc.h>
 #include <sys/module.h>
-#include <sys/mutex.h>
 
 #include <dev/gpio/gpiobusvar.h>
 #include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/openfirm.h>
-
-#include <machine/resource.h>
-
-#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;
-
-



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