Index: lib/libgpio/gpio.3 =================================================================== --- lib/libgpio/gpio.3 +++ lib/libgpio/gpio.3 @@ -47,6 +47,8 @@ .Ft int .Fn gpio_pin_config "gpio_handle_t handle, gpio_config *cfg" .Ft int +.Fn gpio_pin_set_name "gpio_handle_t handle, gpio_config *cfg" +.Ft int .Fn gpio_pin_set_flags "gpio_handle_t handle, gpio_config_t *cfg" .Ft gpio_value_t .Fn gpio_pin_get "gpio_handle_t handle, gpio_pin_t pin" @@ -111,6 +113,16 @@ structure. .Pp The function +.Fn gpio_pin_set_name +configures a pin with the name passed in by the +.Ft gpio_config_t +structure. +The pin number should also be passed in through the +.Ft g_pin +variable. +All other structure members will be ignored by this function. +.Pp +The function .Fn gpio_pin_set_flags configures a pin with the flags passed in by the .Ft gpio_config_t Index: lib/libgpio/gpio.c =================================================================== --- lib/libgpio/gpio.c +++ lib/libgpio/gpio.c @@ -119,6 +119,21 @@ } int +gpio_pin_set_name(gpio_handle_t handle, gpio_config_t *cfg) +{ + struct gpio_pin gppin; + + if (cfg == NULL) + return (-1); + gppin.gp_pin = cfg->g_pin; + strlcpy(gppin.gp_name, cfg->g_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: lib/libgpio/libgpio.h =================================================================== --- lib/libgpio/libgpio.h +++ 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 + * through the gpio_config_t structure. + */ +int gpio_pin_set_name(gpio_handle_t, gpio_config_t *); +/* * 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: sys/dev/gpio/gpiobus.c =================================================================== --- sys/dev/gpio/gpiobus.c +++ sys/dev/gpio/gpiobus.c @@ -184,9 +184,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. */ @@ -241,12 +241,12 @@ 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(child, "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); @@ -650,6 +657,46 @@ 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_NOWAIT | M_ZERO); + if (sc->sc_pins[pin].name == NULL) + return (ENOMEM); + } + strlcpy(sc->sc_pins[pin].name, name, GPIOMAXNAME); + + return (0); +} + static device_method_t gpiobus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, gpiobus_probe), @@ -684,6 +731,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: sys/dev/gpio/gpiobus_if.m =================================================================== --- sys/dev/gpio/gpiobus_if.m +++ 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: sys/dev/gpio/gpiobusvar.h =================================================================== --- sys/dev/gpio/gpiobusvar.h +++ 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: sys/dev/gpio/gpioc.c =================================================================== --- sys/dev/gpio/gpioc.c +++ 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: sys/dev/gpio/ofw_gpiobus.c =================================================================== --- sys/dev/gpio/ofw_gpiobus.c +++ 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(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); } Index: sys/sys/gpio.h =================================================================== --- sys/sys/gpio.h +++ 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: usr.sbin/gpioctl/gpioctl.8 =================================================================== --- usr.sbin/gpioctl/gpioctl.8 +++ usr.sbin/gpioctl/gpioctl.8 @@ -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 pin name .It Fl t Ar pin toggle value of provided pin number .It Fl v Index: usr.sbin/gpioctl/gpioctl.c =================================================================== --- usr.sbin/gpioctl/gpioctl.c +++ 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,21 @@ exit(1); } + /* Set the pin name. */ + if (name) { + if (argc == 0) { + usage(); + exit(1); + } + pin.g_pin = pinn; + strlcpy(pin.g_name, argv[0], GPIOMAXNAME); + if (gpio_pin_set_name(handle, &pin) < 0) { + perror("gpio_pin_set_name"); + exit(1); + } + exit(0); + } + if (list) { dump_pins(handle, verbose); gpio_close(handle);