From 3c702e9987e261042a07e43460a8148be254412e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 21 Oct 2015 15:29:53 +0200 Subject: gpio: add a userspace chardev ABI for GPIOs A new chardev that is to be used for userspace GPIO access is added in this patch. It is intended to gradually replace the horribly broken sysfs ABI. Using a chardev has many upsides: - All operations are per-gpiochip, which is the actual device underlying the GPIOs, making us tie in to the kernel device model properly. - Hotpluggable GPIO controllers can come and go, as this kind of problem has been know to userspace for character devices since ages, and if a gpiochip handle is held in userspace we know we will break something, whereas the sysfs is stateless. - The one-value-per-file rule of sysfs is really hard to maintain when you want to twist more than one knob at a time, for example have in-kernel APIs to switch several GPIO lines at the same time, and this will be possible to do with a single ioctl() from userspace, saving a lot of context switching. We also need to add a new bus type for GPIO. This is necessary for example for userspace coldplug, where sysfs is traversed to find the boot-time device nodes and create the character devices in /dev. This new chardev ABI is *non* *optional* and can be counted on to be present in the future, emphasizing the preference of this ABI. The ABI only implements one single ioctl() to get the name and number of GPIO lines of a chip. Even this is debatable: see it as a minimal example for review. This ABI shall be ruthlessly reviewed and etched in stone. The old /sys/class/gpio is still optional to compile in, but will be deprecated. Unique device IDs are created using IDR, which is overkill and insanely scalable, but also well tested. Cc: Johan Hovold Cc: Michael Welling Cc: Markus Pargmann Cc: Greg Kroah-Hartman Cc: Arnd Bergmann Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..76986c3ab4ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4819,6 +4819,7 @@ F: drivers/gpio/ F: include/linux/gpio/ F: include/linux/gpio.h F: include/asm-generic/gpio.h +F: include/uapi/linux/gpio.h GRE DEMULTIPLEXER DRIVER M: Dmitry Kozlov -- cgit v1.2.3-73-gaa49b From 6d591c46bce037696d173bd5c8461b2b4bb680ad Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 21 Oct 2015 15:45:54 +0200 Subject: tools/gpio: create GPIO tools This creates GPIO tools under tools/gpio/* and adds a single example program to list the GPIOs on a system. When proper devices are created it provides this minimal output: Cc: Johan Hovold Cc: Michael Welling Cc: Markus Pargmann Signed-off-by: Linus Walleij --- MAINTAINERS | 1 + tools/Makefile | 8 +-- tools/gpio/Makefile | 12 +++++ tools/gpio/gpio-utils.c | 11 +++++ tools/gpio/gpio-utils.h | 25 ++++++++++ tools/gpio/lsgpio.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 tools/gpio/Makefile create mode 100644 tools/gpio/gpio-utils.c create mode 100644 tools/gpio/gpio-utils.h create mode 100644 tools/gpio/lsgpio.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 76986c3ab4ff..4d3d1b817873 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4820,6 +4820,7 @@ F: include/linux/gpio/ F: include/linux/gpio.h F: include/asm-generic/gpio.h F: include/uapi/linux/gpio.h +F: tools/gpio/ GRE DEMULTIPLEXER DRIVER M: Dmitry Kozlov diff --git a/tools/Makefile b/tools/Makefile index 6339f6ac3ccb..f41e7c6ea23e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -13,6 +13,7 @@ help: @echo ' cpupower - a tool for all things x86 CPU power' @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' @echo ' freefall - laptop accelerometer program for disk protection' + @echo ' gpio - GPIO tools' @echo ' hv - tools used when in Hyper-V clients' @echo ' iio - IIO tools' @echo ' lguest - a minimal 32-bit x86 hypervisor' @@ -53,7 +54,7 @@ acpi: FORCE cpupower: FORCE $(call descend,power/$@) -cgroup firewire hv guest spi usb virtio vm net iio: FORCE +cgroup firewire hv guest spi usb virtio vm net iio gpio: FORCE $(call descend,$@) liblockdep: FORCE @@ -119,7 +120,7 @@ acpi_clean: cpupower_clean: $(call descend,power/cpupower,clean) -cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean: +cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean gpio_clean: $(call descend,$(@:_clean=),clean) liblockdep_clean: @@ -155,6 +156,7 @@ build_clean: clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \ perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ - freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean + freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ + gpio_clean .PHONY: FORCE diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile new file mode 100644 index 000000000000..4d198d5c4203 --- /dev/null +++ b/tools/gpio/Makefile @@ -0,0 +1,12 @@ +CC = $(CROSS_COMPILE)gcc +CFLAGS += -Wall -g -D_GNU_SOURCE + +all: lsgpio + +lsgpio: lsgpio.o gpio-utils.o + +%.o: %.c gpio-utils.h + +.PHONY: clean +clean: + rm -f *.o lsgpio diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c new file mode 100644 index 000000000000..8208718f2c99 --- /dev/null +++ b/tools/gpio/gpio-utils.c @@ -0,0 +1,11 @@ +/* + * GPIO tools - helpers library for the GPIO tools + * + * Copyright (C) 2015 Linus Walleij + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include "gpio-utils.h" diff --git a/tools/gpio/gpio-utils.h b/tools/gpio/gpio-utils.h new file mode 100644 index 000000000000..b18209a45ad3 --- /dev/null +++ b/tools/gpio/gpio-utils.h @@ -0,0 +1,25 @@ +/* + * GPIO tools - utility helpers library for the GPIO tools + * + * Copyright (C) 2015 Linus Walleij + * + * Portions copied from iio_utils and lssio: + * Copyright (c) 2010 Manuel Stahl + * Copyright (c) 2008 Jonathan Cameron + * * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#ifndef _GPIO_UTILS_H_ +#define _GPIO_UTILS_H_ + +#include + +static inline int check_prefix(const char *str, const char *prefix) +{ + return strlen(str) > strlen(prefix) && + strncmp(str, prefix, strlen(prefix)) == 0; +} + +#endif /* _GPIO_UTILS_H_ */ diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c new file mode 100644 index 000000000000..4cfe29da279b --- /dev/null +++ b/tools/gpio/lsgpio.c @@ -0,0 +1,128 @@ +/* + * lsgpio - example on how to list the GPIO lines on a system + * + * Copyright (C) 2015 Linus Walleij + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * Usage: + * lsgpio <-n device-name> + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gpio-utils.h" + +int list_device(const char *device_name) +{ + struct gpiochip_info cinfo; + char *chrdev_name; + int fd; + int ret; + + ret = asprintf(&chrdev_name, "/dev/%s", device_name); + if (ret < 0) + return -ENOMEM; + + fd = open(chrdev_name, 0); + if (fd == -1) { + ret = -errno; + fprintf(stderr, "Failed to open %s\n", chrdev_name); + goto free_chrdev_name; + } + + /* Inspect this GPIO chip */ + ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo); + if (ret == -1) { + ret = -errno; + fprintf(stderr, "Failed to retrieve GPIO fd\n"); + if (close(fd) == -1) + perror("Failed to close GPIO character device file"); + + goto free_chrdev_name; + } + fprintf(stdout, "GPIO chip: %s, %u GPIO lines\n", + cinfo.name, cinfo.lines); + + if (close(fd) == -1) { + ret = -errno; + goto free_chrdev_name; + } + +free_chrdev_name: + free(chrdev_name); + + return ret; + +} + +void print_usage(void) +{ + fprintf(stderr, "Usage: lsgpio [options]...\n" + "List GPIO chips, lines and states\n" + " -n List GPIOs on a named device\n" + " -? This helptext\n" + ); +} + +int main(int argc, char **argv) +{ + const char *device_name; + int ret; + int c; + + while ((c = getopt(argc, argv, "n:")) != -1) { + switch (c) { + case 'n': + device_name = optarg; + break; + case '?': + print_usage(); + return -1; + } + } + + if (device_name) + ret = list_device(device_name); + else { + const struct dirent *ent; + DIR *dp; + + /* List all GPIO devices one at a time */ + dp = opendir("/dev"); + if (!dp) { + ret = -errno; + goto error_out; + } + + ret = -ENOENT; + while (ent = readdir(dp), ent) { + if (check_prefix(ent->d_name, "gpiochip")) { + ret = list_device(ent->d_name); + if (ret) + break; + } + } + + ret = 0; + if (closedir(dp) == -1) { + perror("scanning devices: Failed to close directory"); + ret = -errno; + } + } +error_out: + return ret; +} -- cgit v1.2.3-73-gaa49b From 40c159b776f882f2e2cbe20c9e29832841e5c0f9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 22 Oct 2015 10:21:57 +0200 Subject: gpio: add a userspace character device ABI Put in some documentation for the new character device ABI so we can properly etch it in stone. Signed-off-by: Linus Walleij --- Documentation/ABI/testing/gpio-cdev | 26 ++++++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 27 insertions(+) create mode 100644 Documentation/ABI/testing/gpio-cdev (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/testing/gpio-cdev b/Documentation/ABI/testing/gpio-cdev new file mode 100644 index 000000000000..7b265fbb47e3 --- /dev/null +++ b/Documentation/ABI/testing/gpio-cdev @@ -0,0 +1,26 @@ +What: /dev/gpiochip[0-9]+ +Date: November 2015 +KernelVersion: 4.4 +Contact: linux-gpio@vger.kernel.org +Description: + The character device files /dev/gpiochip* are the interface + between GPIO chips and userspace. + + The ioctl(2)-based ABI is defined and documented in + [include/uapi]. + + The following file operations are supported: + + open(2) + Currently the only useful flags are O_RDWR. + + ioctl(2) + Initiate various actions. + See the inline documentation in [include/uapi] + for descriptions of all ioctls. + + close(2) + Stops and free up the I/O contexts that was associated + with the file descriptor. + +Users: TBD diff --git a/MAINTAINERS b/MAINTAINERS index 4d3d1b817873..a85cd6dcb5de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4815,6 +4815,7 @@ L: linux-gpio@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git S: Maintained F: Documentation/gpio/ +F: Documentation/ABI/testing/gpio-cdev F: drivers/gpio/ F: include/linux/gpio/ F: include/linux/gpio.h -- cgit v1.2.3-73-gaa49b From fe95046e960b4b76e73dc1486955d93f47276134 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 22 Oct 2015 09:58:34 +0200 Subject: gpio: ABI: mark the sysfs ABI as obsolete This marks the (optional) sysfs GPIO ABI as obsolete and schedules it for removal in 2020. Cc: Johan Hovold Cc: Michael Welling Cc: Markus Pargmann Signed-off-by: Linus Walleij --- Documentation/ABI/obsolete/sysfs-gpio | 30 ++++++++++++++++++++++++++++++ Documentation/ABI/testing/sysfs-gpio | 28 ---------------------------- MAINTAINERS | 1 + 3 files changed, 31 insertions(+), 28 deletions(-) create mode 100644 Documentation/ABI/obsolete/sysfs-gpio delete mode 100644 Documentation/ABI/testing/sysfs-gpio (limited to 'MAINTAINERS') diff --git a/Documentation/ABI/obsolete/sysfs-gpio b/Documentation/ABI/obsolete/sysfs-gpio new file mode 100644 index 000000000000..867c1fab20e2 --- /dev/null +++ b/Documentation/ABI/obsolete/sysfs-gpio @@ -0,0 +1,30 @@ +What: /sys/class/gpio/ +Date: July 2008 +KernelVersion: 2.6.27 +Contact: Linus Walleij +Description: + + As a Kconfig option, individual GPIO signals may be accessed from + userspace. GPIOs are only made available to userspace by an explicit + "export" operation. If a given GPIO is not claimed for use by + kernel code, it may be exported by userspace (and unexported later). + Kernel code may export it for complete or partial access. + + GPIOs are identified as they are inside the kernel, using integers in + the range 0..INT_MAX. See Documentation/gpio.txt for more information. + + /sys/class/gpio + /export ... asks the kernel to export a GPIO to userspace + /unexport ... to return a GPIO to the kernel + /gpioN ... for each exported GPIO #N OR + / ... for a properly named GPIO line + /value ... always readable, writes fail for input GPIOs + /direction ... r/w as: in, out (default low); write: high, low + /edge ... r/w as: none, falling, rising, both + /gpiochipN ... for each gpiochip; #N is its first GPIO + /base ... (r/o) same as N + /label ... (r/o) descriptive, not necessarily unique + /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) + + This ABI is deprecated and will be removed after 2020. It is + replaced with the GPIO character device. diff --git a/Documentation/ABI/testing/sysfs-gpio b/Documentation/ABI/testing/sysfs-gpio deleted file mode 100644 index 55ffa2df1c10..000000000000 --- a/Documentation/ABI/testing/sysfs-gpio +++ /dev/null @@ -1,28 +0,0 @@ -What: /sys/class/gpio/ -Date: July 2008 -KernelVersion: 2.6.27 -Contact: David Brownell -Description: - - As a Kconfig option, individual GPIO signals may be accessed from - userspace. GPIOs are only made available to userspace by an explicit - "export" operation. If a given GPIO is not claimed for use by - kernel code, it may be exported by userspace (and unexported later). - Kernel code may export it for complete or partial access. - - GPIOs are identified as they are inside the kernel, using integers in - the range 0..INT_MAX. See Documentation/gpio.txt for more information. - - /sys/class/gpio - /export ... asks the kernel to export a GPIO to userspace - /unexport ... to return a GPIO to the kernel - /gpioN ... for each exported GPIO #N OR - / ... for a properly named GPIO line - /value ... always readable, writes fail for input GPIOs - /direction ... r/w as: in, out (default low); write: high, low - /edge ... r/w as: none, falling, rising, both - /gpiochipN ... for each gpiochip; #N is its first GPIO - /base ... (r/o) same as N - /label ... (r/o) descriptive, not necessarily unique - /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) - diff --git a/MAINTAINERS b/MAINTAINERS index a85cd6dcb5de..7df638be28e2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4816,6 +4816,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git S: Maintained F: Documentation/gpio/ F: Documentation/ABI/testing/gpio-cdev +F: Documentation/ABI/obsolete/sysfs-gpio F: drivers/gpio/ F: include/linux/gpio/ F: include/linux/gpio.h -- cgit v1.2.3-73-gaa49b