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);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to