Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Dec 2019 21:27:10 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r355274 - head/sys/dev/gpio
Message-ID:  <201912012127.xB1LRAMj048575@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Dec  1 21:27:09 2019
New Revision: 355274
URL: https://svnweb.freebsd.org/changeset/base/355274

Log:
  Move most of the gpio_pin_* functions from ofw_gpiobus.c to gpiobus.c so
  that they can be used by drivers on non-FDT-configured systems.  Only the
  functions related to acquiring pins by parsing FDT data remain in
  ofw_gpiobus.  Also, add two new functions for acquiring gpio pins based on
  child device_t and index, or on the bus device_t and pin number.  And
  finally, defer reserving pins for gpiobus children until they acquire the
  pin, rather than reserving them as soon as the child is added (before it's
  even known whether the child will attach).
  
  This will allow drivers configured with hints (or any other mechanism) to
  use the same code as drivers configured via FDT data.  Until now, a hinted
  driver and an FDT driver had to be two completely different sets of code,
  because hinted drivers could only use gpiobus calls to manipulate pins,
  while fdt-configured drivers could not use that API (due to not always being
  children of the bus that owns the pins) and had to use the newer
  gpio_pin_xxxx() functions.  Now drivers can be written in the more
  traditional form, where most of the code is shared and only the resource
  acquisition code at attachment time changes.

Modified:
  head/sys/dev/gpio/gpiobus.c
  head/sys/dev/gpio/gpiobusvar.h
  head/sys/dev/gpio/ofw_gpiobus.c

Modified: head/sys/dev/gpio/gpiobus.c
==============================================================================
--- head/sys/dev/gpio/gpiobus.c	Sun Dec  1 21:01:33 2019	(r355273)
+++ head/sys/dev/gpio/gpiobus.c	Sun Dec  1 21:27:09 2019	(r355274)
@@ -77,6 +77,8 @@ static int gpiobus_pin_set(device_t, device_t, uint32_
 static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*);
 static int gpiobus_pin_toggle(device_t, device_t, uint32_t);
 
+#define	GPIO_ACTIVE_LOW 1 /* XXX Note that nothing currently sets this flag */
+
 /*
  * XXX -> Move me to better place - gpio_subr.c?
  * Also, this function must be changed when interrupt configuration
@@ -135,6 +137,114 @@ gpio_check_flags(uint32_t caps, uint32_t flags)
 	return (0);
 }
 
+int
+gpio_pin_get_by_bus_pinnum(device_t busdev, uint32_t pinnum, gpio_pin_t *ppin)
+{
+	gpio_pin_t pin;
+	int err;
+
+	err = gpiobus_acquire_pin(busdev, pinnum);
+	if (err != 0)
+		return (EBUSY);
+
+	pin = malloc(sizeof(*pin), M_DEVBUF, M_WAITOK | M_ZERO);
+
+	pin->dev = device_get_parent(busdev);
+	pin->pin = pinnum;
+	GPIO_PIN_GETFLAGS(pin->dev, pin->pin, &pin->flags);
+
+	*ppin = pin;
+	return (0);
+}
+
+int
+gpio_pin_get_by_child_index(device_t childdev, uint32_t idx, gpio_pin_t *ppin)
+{
+	struct gpiobus_ivar *devi;
+
+	devi = GPIOBUS_IVAR(childdev);
+	if (idx >= devi->npins)
+		return (EINVAL);
+
+	return (gpio_pin_get_by_bus_pinnum(device_get_parent(childdev),
+	    devi->pins[idx], ppin));
+}
+
+int
+gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps)
+{
+
+	KASSERT(pin != NULL, ("GPIO pin is NULL."));
+	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
+	return (GPIO_PIN_GETCAPS(pin->dev, pin->pin, caps));
+}
+
+int
+gpio_pin_is_active(gpio_pin_t pin, bool *active)
+{
+	int rv;
+	uint32_t tmp;
+
+	KASSERT(pin != NULL, ("GPIO pin is NULL."));
+	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
+	rv = GPIO_PIN_GET(pin->dev, pin->pin, &tmp);
+	if (rv  != 0) {
+		return (rv);
+	}
+
+	if (pin->flags & GPIO_ACTIVE_LOW)
+		*active = tmp == 0;
+	else
+		*active = tmp != 0;
+	return (0);
+}
+
+void
+gpio_pin_release(gpio_pin_t gpio)
+{
+	device_t busdev;
+
+	if (gpio == NULL)
+		return;
+
+	KASSERT(gpio->dev != NULL, ("GPIO pin device is NULL."));
+
+	busdev = GPIO_GET_BUS(gpio->dev);
+	if (busdev != NULL)
+		gpiobus_release_pin(busdev, gpio->pin);
+
+	free(gpio, M_DEVBUF);
+}
+
+int
+gpio_pin_set_active(gpio_pin_t pin, bool active)
+{
+	int rv;
+	uint32_t tmp;
+
+	if (pin->flags & GPIO_ACTIVE_LOW)
+		tmp = active ? 0 : 1;
+	else
+		tmp = active ? 1 : 0;
+
+	KASSERT(pin != NULL, ("GPIO pin is NULL."));
+	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
+	rv = GPIO_PIN_SET(pin->dev, pin->pin, tmp);
+	return (rv);
+}
+
+int
+gpio_pin_setflags(gpio_pin_t pin, uint32_t flags)
+{
+	int rv;
+
+	KASSERT(pin != NULL, ("GPIO pin is NULL."));
+	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
+
+	rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags);
+	return (rv);
+}
+
 static void
 gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen)
 {
@@ -370,8 +480,6 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t 
 		devi->pins[npins++] = i;
 	}
 
-	if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
-		return (EINVAL);
 	return (0);
 }
 
@@ -425,8 +533,6 @@ gpiobus_parse_pin_list(struct gpiobus_softc *sc, devic
 		p = endp + 1;
 	}
 
-	if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
-		return (EINVAL);
 	return (0);
 }
 

Modified: head/sys/dev/gpio/gpiobusvar.h
==============================================================================
--- head/sys/dev/gpio/gpiobusvar.h	Sun Dec  1 21:01:33 2019	(r355273)
+++ head/sys/dev/gpio/gpiobusvar.h	Sun Dec  1 21:27:09 2019	(r355274)
@@ -141,7 +141,7 @@ int ofw_gpiobus_parse_gpios(device_t, char *, struct g
 void ofw_gpiobus_register_provider(device_t);
 void ofw_gpiobus_unregister_provider(device_t);
 
-/* Consumers interface. */
+/* Acquire a pin by parsing FDT data. */
 int gpio_pin_get_by_ofw_name(device_t consumer, phandle_t node,
     char *name, gpio_pin_t *gpio);
 int gpio_pin_get_by_ofw_idx(device_t consumer, phandle_t node,
@@ -150,14 +150,29 @@ int gpio_pin_get_by_ofw_property(device_t consumer, ph
     char *name, gpio_pin_t *gpio);
 int gpio_pin_get_by_ofw_propidx(device_t consumer, phandle_t node,
     char *name, int idx, gpio_pin_t *gpio);
+#endif /* FDT */
+
+/* Acquire a pin by bus and pin number. */
+int gpio_pin_get_by_bus_pinnum(device_t _bus, uint32_t _pinnum, gpio_pin_t *_gp);
+
+/* Acquire a pin by child and index (used by direct children of gpiobus). */
+int gpio_pin_get_by_child_index(device_t _child, uint32_t _idx, gpio_pin_t *_gp);
+
+/* Release a pin acquired via any gpio_pin_get_xxx() function. */
 void gpio_pin_release(gpio_pin_t gpio);
+
+/* Work with gpio pins acquired using the functions above. */
 int gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps);
 int gpio_pin_is_active(gpio_pin_t pin, bool *active);
 int gpio_pin_set_active(gpio_pin_t pin, bool active);
 int gpio_pin_setflags(gpio_pin_t pin, uint32_t flags);
-#endif
 struct resource *gpio_alloc_intr_resource(device_t consumer_dev, int *rid,
     u_int alloc_flags, gpio_pin_t pin, uint32_t intr_mode);
+
+/*
+ * Functions shared between gpiobus and other bus classes that derive from it;
+ * these should not be called directly by other drivers.
+ */
 int gpio_check_flags(uint32_t, uint32_t);
 device_t gpiobus_attach_bus(device_t);
 int gpiobus_detach_bus(device_t);

Modified: head/sys/dev/gpio/ofw_gpiobus.c
==============================================================================
--- head/sys/dev/gpio/ofw_gpiobus.c	Sun Dec  1 21:01:33 2019	(r355273)
+++ head/sys/dev/gpio/ofw_gpiobus.c	Sun Dec  1 21:27:09 2019	(r355274)
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
 
 #include "gpiobus_if.h"
 
-#define	GPIO_ACTIVE_LOW		1
-
 static struct ofw_gpiobus_devinfo *ofw_gpiobus_setup_devinfo(device_t,
 	device_t, phandle_t);
 static void ofw_gpiobus_destroy_devinfo(device_t, struct ofw_gpiobus_devinfo *);
@@ -138,82 +136,6 @@ gpio_pin_get_by_ofw_name(device_t consumer, phandle_t 
 	if (rv != 0)
 		return (rv);
 	return (gpio_pin_get_by_ofw_idx(consumer, node, idx, pin));
-}
-
-void
-gpio_pin_release(gpio_pin_t gpio)
-{
-	device_t busdev;
-
-	if (gpio == NULL)
-		return;
-
-	KASSERT(gpio->dev != NULL, ("invalid pin state"));
-
-	busdev = GPIO_GET_BUS(gpio->dev);
-	if (busdev != NULL)
-		gpiobus_release_pin(busdev, gpio->pin);
-
-	/* XXXX Unreserve pin. */
-	free(gpio, M_DEVBUF);
-}
-
-int
-gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps)
-{
-
-	KASSERT(pin != NULL, ("GPIO pin is NULL."));
-	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
-	return (GPIO_PIN_GETCAPS(pin->dev, pin->pin, caps));
-}
-
-int
-gpio_pin_is_active(gpio_pin_t pin, bool *active)
-{
-	int rv;
-	uint32_t tmp;
-
-	KASSERT(pin != NULL, ("GPIO pin is NULL."));
-	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
-	rv = GPIO_PIN_GET(pin->dev, pin->pin, &tmp);
-	if (rv  != 0) {
-		return (rv);
-	}
-
-	if (pin->flags & GPIO_ACTIVE_LOW)
-		*active = tmp == 0;
-	else
-		*active = tmp != 0;
-	return (0);
-}
-
-int
-gpio_pin_set_active(gpio_pin_t pin, bool active)
-{
-	int rv;
-	uint32_t tmp;
-
-	if (pin->flags & GPIO_ACTIVE_LOW)
-		tmp = active ? 0 : 1;
-	else
-		tmp = active ? 1 : 0;
-
-	KASSERT(pin != NULL, ("GPIO pin is NULL."));
-	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
-	rv = GPIO_PIN_SET(pin->dev, pin->pin, tmp);
-	return (rv);
-}
-
-int
-gpio_pin_setflags(gpio_pin_t pin, uint32_t flags)
-{
-	int rv;
-
-	KASSERT(pin != NULL, ("GPIO pin is NULL."));
-	KASSERT(pin->dev != NULL, ("GPIO pin device is NULL."));
-
-	rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags);
-	return (rv);
 }
 
 /*



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