Index: head/lib/libgpio/gpio.3 =================================================================== --- head/lib/libgpio/gpio.3 +++ head/lib/libgpio/gpio.3 @@ -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 @@ 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 Index: head/lib/libgpio/gpio.c =================================================================== --- head/lib/libgpio/gpio.c +++ head/lib/libgpio/gpio.c @@ -119,6 +119,22 @@ } 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; Index: head/lib/libgpio/libgpio.h =================================================================== --- head/lib/libgpio/libgpio.h +++ head/lib/libgpio/libgpio.h @@ -71,6 +71,11 @@ */ 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. */ Index: head/sys/dev/gpio/gpiobus.c =================================================================== --- head/sys/dev/gpio/gpiobus.c +++ head/sys/dev/gpio/gpiobus.c @@ -185,9 +185,9 @@ /* 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 @@ 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 @@ 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_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 @@ 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 @@ 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 }; Index: head/sys/dev/gpio/gpiobus_if.m =================================================================== --- head/sys/dev/gpio/gpiobus_if.m +++ head/sys/dev/gpio/gpiobus_if.m @@ -106,3 +106,21 @@ 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; +}; Index: head/sys/dev/gpio/gpiobusvar.h =================================================================== --- head/sys/dev/gpio/gpiobusvar.h +++ head/sys/dev/gpio/gpiobusvar.h @@ -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 @@ 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 Index: head/sys/dev/gpio/gpioc.c =================================================================== --- head/sys/dev/gpio/gpioc.c +++ head/sys/dev/gpio/gpioc.c @@ -40,6 +40,7 @@ #include #include "gpio_if.h" +#include "gpiobus_if.h" #undef GPIOC_DEBUG #ifdef GPIOC_DEBUG @@ -112,12 +113,16 @@ 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 @@ 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 @@ 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; Index: head/sys/dev/gpio/ofw_gpiobus.c =================================================================== --- head/sys/dev/gpio/ofw_gpiobus.c +++ head/sys/dev/gpio/ofw_gpiobus.c @@ -39,6 +39,8 @@ #include #include +#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 @@ 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 @@ 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 @@ 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); Index: head/sys/sys/gpio.h =================================================================== --- head/sys/sys/gpio.h +++ head/sys/sys/gpio.h @@ -93,5 +93,6 @@ #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__ */ Index: head/usr.sbin/gpioctl/gpioctl.8 =================================================================== --- head/usr.sbin/gpioctl/gpioctl.8 +++ head/usr.sbin/gpioctl/gpioctl.8 @@ -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 @@ .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 Index: head/usr.sbin/gpioctl/gpioctl.c =================================================================== --- head/usr.sbin/gpioctl/gpioctl.c +++ head/usr.sbin/gpioctl/gpioctl.c @@ -68,6 +68,7 @@ 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 @@ 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 @@ 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 @@ 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);