Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Aug 2012 11:51:02 +0900 (JST)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        imp@bsdimp.com
Cc:        gonzo@FreeBSD.org, freebsd-arm@FreeBSD.org
Subject:   Re: gpiobus_hinted_child >32 pins support, pin_getname method, and gpio-sysctl bridge patch
Message-ID:  <20120820.115102.2041268449045028507.hrs@allbsd.org>
In-Reply-To: <8CDAB51C-14A0-42F0-8E16-43A3EABA2703@bsdimp.com>
References:  <20120819.171723.523519054460575158.hrs@allbsd.org> <8CDAB51C-14A0-42F0-8E16-43A3EABA2703@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
----Security_Multipart0(Mon_Aug_20_11_51_02_2012_300)--
Content-Type: Multipart/Mixed;
	boundary="--Next_Part(Mon_Aug_20_11_51_02_2012_584)--"
Content-Transfer-Encoding: 7bit

----Next_Part(Mon_Aug_20_11_51_02_2012_584)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Warner Losh <imp@bsdimp.com> wrote
  in <8CDAB51C-14A0-42F0-8E16-43A3EABA2703@bsdimp.com>:

im>
im> On Aug 19, 2012, at 2:17 AM, Hiroki Sato wrote:
im>
im> > Hi,
im>
im> Hi Sato-san,
im>
im> In general, I like this code in the context of the current GPIO
im> framework.  I've been growing dissatisfied with the current GPIO
im> framework, however, and some of my comments reflect that more than any
im> comments about this specific code.
im>
im> > Can you review the attached patches?  The first one is to add >32 pins
im> > support for hint.devname.%d.pins and pin_getname method into gpiobus
im> > similar to gpio interface.  After applying this, the following hint
im> > will be supported:
im> >
im> > hint.gpioled.0.at="gpiobus0"
im> > hint.gpioled.0.pins0="0x00000000" # 41
im> > hint.gpioled.0.pins1="0x00000200"
im>
im> This is, at best, awkward.  Why not '41' here?
im>
im> Why not hints.gpioled.0.pins0=41?

 Ah, the reason why I used the mask was to simply reuse the old
 interface.  The attached patch supports the following:

  hint.gpioled.0.at="gpiobus0"
  hint.gpioled.0.pins.0="10"
  hint.gpioled.0.pins.1="41"
  hint.gpioled.0.pins.2="43"

 My primary frustration was it was limited to 32 pins, so I am
 wondering if someone has a strong objection or not ;)

im> In general, the gpio stuff is too mask heavy and should be more pin
im> oriented.  We also need a more generic way to pass around all the GPIO
im> pins used for aux functions of embedded devices.  which pin is used
im> for media status interrupts, write protect detection, vcc power, etc.
im>
im> Looks a lot like we already keep book internally in pins.

im> I was rather hoping to recast much of the GPIO stuff so we can also
im> support interrupts based on pin numbers for any device in the tree.
im> I'd like this for a gpiokey generic interface that devices can
im> register button presses.  How does one configure in vs out for these
im> pins?  And how does one guard against trying to use the GPIO pins for
im> things like ethernet?  Again, that may be beyond the scope of what you
im> are trying to achieve.

 Agreed.  I was exploring more generic way to configure GPIO
 connection via DTS, hints, and/or gpiobus for some time, but it was
 difficult to do such things without device-specific code.  Although
 in/out initialization for each pin can be done via DTS (when the gpio
 driver attached and read gpios property), there seems no way to
 configure pin-to-interrupt relationship in the bindings. I am not
 familiar with DTS syntax but the interrupt-map property can be
 utilized to specify it.

-- Hiroki

----Next_Part(Mon_Aug_20_11_51_02_2012_584)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="gpiobus-part-20120820-1.diff"

Index: sys/dev/gpio/gpiobus.c
===================================================================
--- sys/dev/gpio/gpiobus.c	(revision 239381)
+++ sys/dev/gpio/gpiobus.c	(working copy)
@@ -40,6 +40,7 @@
 #include <machine/bus.h>
 #include <sys/rman.h>
 #include <machine/resource.h>
+#include <machine/_inttypes.h>

 #include <sys/gpio.h>
 #include <dev/gpio/gpiobusvar.h>
@@ -47,7 +48,9 @@
 #include "gpiobus_if.h"

 static void gpiobus_print_pins(struct gpiobus_ivar *);
-static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int);
+static int gpiobus_register_pins(struct gpiobus_softc *, device_t, int *,
+    size_t);
+static int gpiobus_parse_pinmask(int, int *, size_t);
 static int gpiobus_probe(device_t);
 static int gpiobus_attach(device_t);
 static int gpiobus_detach(device_t);
@@ -69,6 +72,7 @@
 static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t);
 static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*);
 static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*);
+static int gpiobus_pin_getname(device_t, device_t, uint32_t, char *);
 static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int);
 static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*);
 static int gpiobus_pin_toggle(device_t, device_t, uint32_t);
@@ -82,6 +86,8 @@
 #define	GPIOBUS_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
 #define	GPIOBUS_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);

+#define	GPIOBUS_PINS_MAX	128
+static char pinsmib[] = "pins.NNN";

 static void
 gpiobus_print_pins(struct gpiobus_ivar *devi)
@@ -119,17 +125,12 @@
 }

 static int
-gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
+gpiobus_register_pins(struct gpiobus_softc *sc, device_t child, int *pin,
+    size_t npins)
 {
 	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
-	int i, npins;
+	int i;

-	npins = 0;
-	for (i = 0; i < 32; i++) {
-		if (mask & (1 << i))
-			npins++;
-	}
-
 	if (npins == 0) {
 		device_printf(child, "empty pin mask");
 		return (EINVAL);
@@ -142,34 +143,37 @@
 	if (!devi->pins)
 		return (ENOMEM);

-	npins = 0;
-	for (i = 0; i < 32; i++) {
-
-		if ((mask & (1 << i)) == 0)
-			continue;
-
-		if (i >= sc->sc_npins) {
-			device_printf(child,
-			    "invalid pin %d, max: %d\n", i, sc->sc_npins - 1);
-			return (EINVAL);
-		}
-
-		devi->pins[npins++] = i;
+	for (i = 0; i < npins; i++) {
+		devi->pins[i] = pin[i];
 		/*
 		 * Mark pin as mapped and give warning if it's already mapped
 		 */
-		if (sc->sc_pins_mapped[i]) {
+		if (sc->sc_pins_mapped[pin[i]]) {
 			device_printf(child,
-			    "warning: pin %d is already mapped\n", i);
+			    "warning: pin %d is already mapped\n", pin[i]);
 			return (EINVAL);
 		}
-		sc->sc_pins_mapped[i] = 1;
 	}

 	return (0);
 }

 static int
+gpiobus_parse_pinmask(int mask, int *pins, size_t pinmax)
+{
+	int i, npins;
+
+	npins = 0;
+	for (i = 0; i < sizeof(mask) * 8 && i < pinmax; i++) {
+		if (mask & (1 << i)) {
+			pins[npins++] = i;
+		}
+	}
+
+	return (npins);
+}
+
+static int
 gpiobus_probe(device_t dev)
 {
 	device_set_desc(dev, "GPIO bus");
@@ -192,6 +196,8 @@
 	 * Increase to get number of pins
 	 */
 	sc->sc_npins++;
+	if (bootverbose)
+		device_printf(dev, "number of pins = %d\n", sc->sc_npins);

 	KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));

@@ -310,13 +316,40 @@
 	struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
 	struct gpiobus_ivar *devi;
 	device_t child;
-	int pins;
+	int i, error, mask, pins[GPIOBUS_PINS_MAX];

+	bzero((char *)&pins, sizeof(pins));

 	child = BUS_ADD_CHILD(bus, 0, dname, dunit);
 	devi = GPIOBUS_IVAR(child);
-	resource_int_value(dname, dunit, "pins", &pins);
-	if (gpiobus_parse_pins(sc, child, pins))
+	if (resource_int_value(dname, dunit, "pins", &mask) == 0) {
+		/*
+		 * Backward compatibility for 32-pinmask configuration in a
+		 * 32-bit hint:
+		 *
+		 * hint.devname.%d.pins=0x00000000
+		 */
+		i = gpiobus_parse_pinmask(mask, pins,
+		    sizeof(pins)/sizeof(pins[0]));
+		error = gpiobus_register_pins(sc, child, pins, i);
+	} else {
+		/*
+		 * GPIO pin spec in the following MIB:
+		 *
+		 * hint.devname.%d.pins.0="41"
+		 * hint.devname.%d.pins.1="42"
+		 * hint.devname.%d.pins.2="44"
+		 */
+		for (i = 0; i < sizeof(pins)/sizeof(pins[0]); i++) {
+			snprintf(pinsmib, sizeof(pinsmib), "pins.%d", i);
+			error = resource_int_value(dname, dunit, pinsmib,
+			     &pins[i]);
+			if (error)
+				break;
+		}
+		error = gpiobus_register_pins(sc, child, pins, i);
+	}
+	if (error)
 		device_delete_child(bus, child);
 }

@@ -409,6 +442,18 @@
 }

 static int
+gpiobus_pin_getname(device_t dev, device_t child, uint32_t pin, char *name)
+{
+	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
+	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+
+	if (pin >= devi->npins)
+		return (EINVAL);
+
+	return GPIO_PIN_GETNAME(sc->sc_dev, devi->pins[pin], name);
+}
+
+static int
 gpiobus_pin_set(device_t dev, device_t child, uint32_t pin,
     unsigned int value)
 {
@@ -469,6 +514,7 @@
 	DEVMETHOD(gpiobus_release_bus,	gpiobus_release_bus),
 	DEVMETHOD(gpiobus_pin_getflags,	gpiobus_pin_getflags),
 	DEVMETHOD(gpiobus_pin_getcaps,	gpiobus_pin_getcaps),
+	DEVMETHOD(gpiobus_pin_getname,	gpiobus_pin_getname),
 	DEVMETHOD(gpiobus_pin_setflags,	gpiobus_pin_setflags),
 	DEVMETHOD(gpiobus_pin_get,	gpiobus_pin_get),
 	DEVMETHOD(gpiobus_pin_set,	gpiobus_pin_set),

----Next_Part(Mon_Aug_20_11_51_02_2012_584)----

----Security_Multipart0(Mon_Aug_20_11_51_02_2012_300)--
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (FreeBSD)

iEYEABECAAYFAlAxphYACgkQTyzT2CeTzy3DUwCgt47Z67bDOkxjtP9ii4Y8o3FD
28YAn0prC1RTEaCrTrHgGELjr4m5g2IH
=0sjj
-----END PGP SIGNATURE-----

----Security_Multipart0(Mon_Aug_20_11_51_02_2012_300)----



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