Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Mar 2015 00:47:50 +0000 (UTC)
From:      Luiz Otavio O Souza <loos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r279761 - in head: lib/libgpio sys/dev/gpio sys/sys usr.sbin/gpioctl
Message-ID:  <201503080047.t280lonI070705@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: loos
Date: Sun Mar  8 00:47:50 2015
New Revision: 279761
URL: https://svnweb.freebsd.org/changeset/base/279761

Log:
  Add a new ioctl to allow the setting of GPIO pin names.
  
  When a gpiobus child is added, use its name to identify the mapped pin
  names.
  
  Make the respective changes to libgpio.
  
  Add a new '-n' flag to gpioctl(8) to set the pin name.
  
  Differential Revision:	https://reviews.freebsd.org/D2002
  Reviewed by:	rpaulo
  Requested by:	many

Modified:
  head/lib/libgpio/gpio.3
  head/lib/libgpio/gpio.c
  head/lib/libgpio/libgpio.h
  head/sys/dev/gpio/gpiobus.c
  head/sys/dev/gpio/gpiobus_if.m
  head/sys/dev/gpio/gpiobusvar.h
  head/sys/dev/gpio/gpioc.c
  head/sys/dev/gpio/ofw_gpiobus.c
  head/sys/sys/gpio.h
  head/usr.sbin/gpioctl/gpioctl.8
  head/usr.sbin/gpioctl/gpioctl.c

Modified: head/lib/libgpio/gpio.3
==============================================================================
--- head/lib/libgpio/gpio.3	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/lib/libgpio/gpio.3	Sun Mar  8 00:47:50 2015	(r279761)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 17, 2014
+.Dd March 7, 2015
 .Dt GPIO 3
 .Os
 .Sh NAME
@@ -45,7 +45,9 @@
 .Ft int
 .Fn gpio_pin_list "gpio_handle_t handle, gpio_config_t **pcfgs"
 .Ft int
-.Fn gpio_pin_config "gpio_handle_t handle, gpio_config *cfg"
+.Fn gpio_pin_config "gpio_handle_t handle, gpio_config_t *cfg"
+.Ft int
+.Fn gpio_pin_set_name "gpio_handle_t handle, gpio_pin_t pin, char *name"
 .Ft int
 .Fn gpio_pin_set_flags "gpio_handle_t handle, gpio_config_t *cfg"
 .Ft gpio_value_t
@@ -111,6 +113,10 @@ variable which is part of the
 structure.
 .Pp
 The function
+.Fn gpio_pin_set_name
+sets the name used to describe a pin.
+.Pp
+The function
 .Fn gpio_pin_set_flags
 configures a pin with the flags passed in by the
 .Ft gpio_config_t

Modified: head/lib/libgpio/gpio.c
==============================================================================
--- head/lib/libgpio/gpio.c	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/lib/libgpio/gpio.c	Sun Mar  8 00:47:50 2015	(r279761)
@@ -119,6 +119,22 @@ gpio_pin_config(gpio_handle_t handle, gp
 }
 
 int
+gpio_pin_set_name(gpio_handle_t handle, gpio_pin_t pin, char *name)
+{
+	struct gpio_pin gppin;
+
+	if (name == NULL)
+		return (-1);
+	bzero(&gppin, sizeof(gppin));
+	gppin.gp_pin = pin;
+	strlcpy(gppin.gp_name, name, GPIOMAXNAME);
+	if (ioctl(handle, GPIOSETNAME, &gppin) < 0)
+		return (-1);
+
+	return (0);
+}
+
+int
 gpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg)
 {
 	struct gpio_pin gppin;

Modified: head/lib/libgpio/libgpio.h
==============================================================================
--- head/lib/libgpio/libgpio.h	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/lib/libgpio/libgpio.h	Sun Mar  8 00:47:50 2015	(r279761)
@@ -71,6 +71,11 @@ int		gpio_pin_list(gpio_handle_t, gpio_c
  */
 int		gpio_pin_config(gpio_handle_t, gpio_config_t *);
 /*
+ * Sets the GPIO pin name.  The pin number and pin name to be set are passed
+ * as parameters.
+ */
+int		gpio_pin_set_name(gpio_handle_t, gpio_pin_t, char *);
+/*
  * Sets the GPIO flags on a specific GPIO pin.  The pin number and the flags
  * to be set are passed through the gpio_config_t structure.
  */

Modified: head/sys/dev/gpio/gpiobus.c
==============================================================================
--- head/sys/dev/gpio/gpiobus.c	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/sys/dev/gpio/gpiobus.c	Sun Mar  8 00:47:50 2015	(r279761)
@@ -185,9 +185,9 @@ gpiobus_init_softc(device_t dev)
 	/* Pins = GPIO_PIN_MAX() + 1 */
 	sc->sc_npins++;
 
-	sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 
+	sc->sc_pins = malloc(sizeof(*sc->sc_pins) * sc->sc_npins, M_DEVBUF,
 	    M_NOWAIT | M_ZERO);
-	if (sc->sc_pins_mapped == NULL)
+	if (sc->sc_pins == NULL)
 		return (ENOMEM);
 
 	/* Initialize the bus lock. */
@@ -242,11 +242,11 @@ gpiobus_map_pin(device_t bus, uint32_t p
 		return (-1);
 	}
 	/* Mark pin as mapped and give warning if it's already mapped. */
-	if (sc->sc_pins_mapped[pin]) {
+	if (sc->sc_pins[pin].mapped) {
 		device_printf(bus, "warning: pin %d is already mapped\n", pin);
 		return (-1);
 	}
-	sc->sc_pins_mapped[pin] = 1;
+	sc->sc_pins[pin].mapped = 1;
 
 	return (0);
 }
@@ -281,6 +281,9 @@ gpiobus_parse_pins(struct gpiobus_softc 
 			return (EINVAL);
 		}
 		devi->pins[npins++] = i;
+		/* Use the child name as pin name. */
+		GPIOBUS_PIN_SETNAME(sc->sc_busdev, i,
+		    device_get_nameunit(child));
 	}
 
 	return (0);
@@ -340,10 +343,14 @@ gpiobus_detach(device_t dev)
 		gpiobus_free_ivars(devi);
 	}
 	free(devlist, M_TEMP);
-
-	if (sc->sc_pins_mapped) {
-		free(sc->sc_pins_mapped, M_DEVBUF);
-		sc->sc_pins_mapped = NULL;
+	if (sc->sc_pins) {
+		for (i = 0; i < sc->sc_npins; i++) {
+			if (sc->sc_pins[i].name != NULL)
+				free(sc->sc_pins[i].name, M_DEVBUF);
+			sc->sc_pins[i].name = NULL;
+		}
+		free(sc->sc_pins, M_DEVBUF);
+		sc->sc_pins = NULL;
 	}
 
 	return (0);
@@ -664,6 +671,43 @@ gpiobus_pin_toggle(device_t dev, device_
 	return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]);
 }
 
+static int
+gpiobus_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+	struct gpiobus_softc *sc;
+
+	sc = GPIOBUS_SOFTC(dev);
+	if (pin > sc->sc_npins)
+		return (EINVAL);
+	/* Did we have a name for this pin ? */
+	if (sc->sc_pins[pin].name != NULL) {
+		memcpy(name, sc->sc_pins[pin].name, GPIOMAXNAME);
+		return (0);
+	}
+
+	/* Return the default pin name. */
+	return (GPIO_PIN_GETNAME(device_get_parent(dev), pin, name));
+}
+
+static int
+gpiobus_pin_setname(device_t dev, uint32_t pin, const char *name)
+{
+	struct gpiobus_softc *sc;
+
+	sc = GPIOBUS_SOFTC(dev);
+	if (pin > sc->sc_npins)
+		return (EINVAL);
+	if (name == NULL)
+		return (EINVAL);
+	/* Save the pin name. */
+	if (sc->sc_pins[pin].name == NULL)
+		sc->sc_pins[pin].name = malloc(GPIOMAXNAME, M_DEVBUF,
+		    M_WAITOK | M_ZERO);
+	strlcpy(sc->sc_pins[pin].name, name, GPIOMAXNAME);
+
+	return (0);
+}
+
 static device_method_t gpiobus_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		gpiobus_probe),
@@ -699,6 +743,8 @@ static device_method_t gpiobus_methods[]
 	DEVMETHOD(gpiobus_pin_get,	gpiobus_pin_get),
 	DEVMETHOD(gpiobus_pin_set,	gpiobus_pin_set),
 	DEVMETHOD(gpiobus_pin_toggle,	gpiobus_pin_toggle),
+	DEVMETHOD(gpiobus_pin_getname,	gpiobus_pin_getname),
+	DEVMETHOD(gpiobus_pin_setname,	gpiobus_pin_setname),
 
 	DEVMETHOD_END
 };

Modified: head/sys/dev/gpio/gpiobus_if.m
==============================================================================
--- head/sys/dev/gpio/gpiobus_if.m	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/sys/dev/gpio/gpiobus_if.m	Sun Mar  8 00:47:50 2015	(r279761)
@@ -106,3 +106,21 @@ METHOD int pin_setflags {
 	uint32_t pin_num;
 	uint32_t flags;
 };
+
+#
+# Get the pin name
+#
+METHOD int pin_getname {
+	device_t dev;
+	uint32_t pin_num;
+	char *name;
+};
+
+#
+# Set the pin name
+#
+METHOD int pin_setname {
+	device_t dev;
+	uint32_t pin_num;
+	const char *name;
+};

Modified: head/sys/dev/gpio/gpiobusvar.h
==============================================================================
--- head/sys/dev/gpio/gpiobusvar.h	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/sys/dev/gpio/gpiobusvar.h	Sun Mar  8 00:47:50 2015	(r279761)
@@ -60,6 +60,12 @@
 #define	GPIOBUS_WAIT		1
 #define	GPIOBUS_DONTWAIT	2
 
+struct gpiobus_pin_data
+{
+	int		mapped;		/* pin is mapped/reserved. */
+	char		*name;		/* pin name. */
+};
+
 struct gpiobus_softc
 {
 	struct mtx	sc_mtx;		/* bus mutex */
@@ -68,7 +74,7 @@ struct gpiobus_softc
 	device_t	sc_owner;	/* bus owner */
 	device_t	sc_dev;		/* driver device */
 	int		sc_npins;	/* total pins on bus */
-	int		*sc_pins_mapped; /* mark mapped pins */
+	struct gpiobus_pin_data	*sc_pins; /* pin data */
 };
 
 struct gpiobus_pin

Modified: head/sys/dev/gpio/gpioc.c
==============================================================================
--- head/sys/dev/gpio/gpioc.c	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/sys/dev/gpio/gpioc.c	Sun Mar  8 00:47:50 2015	(r279761)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/gpio/gpiobusvar.h>
 
 #include "gpio_if.h"
+#include "gpiobus_if.h"
 
 #undef GPIOC_DEBUG
 #ifdef GPIOC_DEBUG
@@ -112,12 +113,16 @@ static int 
 gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 
     struct thread *td)
 {
+	device_t bus;
 	int max_pin, res;
 	struct gpioc_softc *sc = cdev->si_drv1;
 	struct gpio_pin pin;
 	struct gpio_req req;
 	uint32_t caps;
 
+	bus = GPIO_GET_BUS(sc->sc_pdev);
+	if (bus == NULL)
+		return (EINVAL);
 	switch (cmd) {
 		case GPIOMAXPIN:
 			max_pin = -1;
@@ -133,7 +138,7 @@ gpioc_ioctl(struct cdev *cdev, u_long cm
 			if (res)
 				break;
 			GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps);
-			GPIO_PIN_GETNAME(sc->sc_pdev, pin.gp_pin, pin.gp_name);
+			GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name);
 			bcopy(&pin, arg, sizeof(pin));
 			break;
 		case GPIOSETCONFIG:
@@ -167,6 +172,12 @@ gpioc_ioctl(struct cdev *cdev, u_long cm
 			    req.gp_pin);
 			res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin);
 			break;
+		case GPIOSETNAME:
+			bcopy(arg, &pin, sizeof(pin));
+			dprintf("set name on pin %d\n", pin.gp_pin);
+			res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin,
+			    pin.gp_name);
+			break;
 		default:
 			return (ENOTTY);
 			break;

Modified: head/sys/dev/gpio/ofw_gpiobus.c
==============================================================================
--- head/sys/dev/gpio/ofw_gpiobus.c	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/sys/dev/gpio/ofw_gpiobus.c	Sun Mar  8 00:47:50 2015	(r279761)
@@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/gpio/gpiobusvar.h>
 #include <dev/ofw/ofw_bus.h>
 
+#include "gpiobus_if.h"
+
 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 *);
@@ -49,6 +51,8 @@ device_t
 ofw_gpiobus_add_fdt_child(device_t bus, const char *drvname, phandle_t child)
 {
 	device_t childdev;
+	int i;
+	struct gpiobus_ivar *devi;
 	struct ofw_gpiobus_devinfo *dinfo;
 
 	/*
@@ -67,6 +71,11 @@ ofw_gpiobus_add_fdt_child(device_t bus, 
 		device_delete_child(bus, childdev);
 		return (NULL);
 	}
+	/* Use the child name as pin name. */
+	devi = &dinfo->opd_dinfo;
+	for (i = 0; i < devi->npins; i++)
+		GPIOBUS_PIN_SETNAME(bus, devi->pins[i],
+		    device_get_nameunit(childdev));
 
 	return (childdev);
 }
@@ -159,7 +168,7 @@ ofw_gpiobus_destroy_devinfo(device_t bus
 	for (i = 0; i < devi->npins; i++) {
 		if (devi->pins[i] > sc->sc_npins)
 			continue;
-		sc->sc_pins_mapped[devi->pins[i]] = 0;
+		sc->sc_pins[devi->pins[i]].mapped = 0;
 	}
 	gpiobus_free_ivars(devi);
 	resource_list_free(&dinfo->opd_dinfo.rl);

Modified: head/sys/sys/gpio.h
==============================================================================
--- head/sys/sys/gpio.h	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/sys/sys/gpio.h	Sun Mar  8 00:47:50 2015	(r279761)
@@ -93,5 +93,6 @@ struct gpio_req {
 #define	GPIOGET			_IOWR('G', 3, struct gpio_req)
 #define	GPIOSET			_IOW('G', 4, struct gpio_req)
 #define	GPIOTOGGLE		_IOWR('G', 5, struct gpio_req)
+#define	GPIOSETNAME		_IOW('G', 6, struct gpio_pin)
 
 #endif /* __GPIO_H__ */

Modified: head/usr.sbin/gpioctl/gpioctl.8
==============================================================================
--- head/usr.sbin/gpioctl/gpioctl.8	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/usr.sbin/gpioctl/gpioctl.8	Sun Mar  8 00:47:50 2015	(r279761)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 7, 2013
+.Dd March 7, 2015
 .Dt GPIOCTL 1
 .Os
 .Sh NAME
@@ -35,20 +35,25 @@
 .Nd GPIO control utility
 .Sh SYNOPSIS
 .Nm
-.Cm -l
 .Op Fl f Ar ctldev
+.Cm -l
 .Op Fl v
 .Nm
-.Cm -t
 .Op Fl f Ar ctldev
+.Cm -t
 .Ar pin
 .Nm
-.Cm -c
 .Op Fl f Ar ctldev
+.Cm -c
 .Ar pin
 .Ar flag
 .Op flag ...
 .Nm
+.Op Fl f Ar ctldev
+.Cm -n
+.Ar pin
+.Ar pin-name
+.Nm
 .Op Cm -f Ar ctldev
 .Ar pin
 .Ar [0|1]
@@ -87,6 +92,8 @@ If not specified, defaults to
 .Pa /dev/gpioc0
 .It Fl l
 list available pins
+.It Fl n Ar pin Ar pin-name
+set the name used to describe the pin
 .It Fl t Ar pin
 toggle value of provided pin number
 .It Fl v

Modified: head/usr.sbin/gpioctl/gpioctl.c
==============================================================================
--- head/usr.sbin/gpioctl/gpioctl.c	Sun Mar  8 00:30:52 2015	(r279760)
+++ head/usr.sbin/gpioctl/gpioctl.c	Sun Mar  8 00:47:50 2015	(r279761)
@@ -68,6 +68,7 @@ usage(void)
 	fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n");
 	fprintf(stderr, "\tgpioctl [-f ctldev] -t pin\n");
 	fprintf(stderr, "\tgpioctl [-f ctldev] -c pin flag ...\n");
+	fprintf(stderr, "\tgpioctl [-f ctldev] -n pin pin-name\n");
 	fprintf(stderr, "\tgpioctl [-f ctldev] pin [0|1]\n");
 	exit(1);
 }
@@ -182,11 +183,11 @@ main(int argc, char **argv)
 	char *ctlfile = NULL;
 	int pinn, pinv, ch;
 	int flags, flag, ok;
-	int config, toggle, verbose, list;
+	int config, list, name, toggle, verbose;
 
-	config = toggle = verbose = list = pinn = 0;
+	config = toggle = verbose = list = name = pinn = 0;
 
-	while ((ch = getopt(argc, argv, "c:f:lt:v")) != -1) {
+	while ((ch = getopt(argc, argv, "c:f:ln:t:v")) != -1) {
 		switch (ch) {
 		case 'c':
 			config = 1;
@@ -200,6 +201,12 @@ main(int argc, char **argv)
 		case 'l':
 			list = 1;
 			break;
+		case 'n':
+			name = 1;
+			pinn = str2int(optarg, &ok);
+			if (!ok)
+				fail("Invalid pin number: %s\n", optarg);
+			break;
 		case 't':
 			toggle = 1;
 			pinn = str2int(optarg, &ok);
@@ -225,6 +232,19 @@ main(int argc, char **argv)
 		exit(1);
 	}
 
+	/* Set the pin name. */
+	if (name) {
+		if (argc == 0) {
+			usage();
+			exit(1);
+		}
+		if (gpio_pin_set_name(handle, pinn, argv[0]) < 0) {
+			perror("gpio_pin_set_name");
+			exit(1);
+		}
+		exit(0);
+	}
+
 	if (list) {
 		dump_pins(handle, verbose);
 		gpio_close(handle);



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