summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 21:05:32 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 21:05:32 -0700
commit1a46712aa99594eabe1e9aeedf115dfff0db1dfd (patch)
tree61240865e6b55e2f2b2c174b333c2a097bd4f31e /tools
parent82b666eee71618b7ca812ee529af116582617dec (diff)
parentccbd805aa934dd1b863ef115a9c55f119b2388cf (diff)
Merge tag 'gpio-v4.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for kernel v4.6. There is quite a lot of interesting stuff going on. The patches to other subsystems and arch-wide are ACKed as far as possible, though I consider things like per-arch <asm/gpio.h> as essentially a part of the GPIO subsystem so it should not be needed. Core changes: - The gpio_chip is now a *real device*. Until now the gpio chips were just piggybacking the parent device or (gasp) floating in space outside of the device model. We now finally make GPIO chips devices. The gpio_chip will create a gpio_device which contains a struct device, and this gpio_device struct is kept private. Anything that needs to be kept private from the rest of the kernel will gradually be moved over to the gpio_device. - As a result of making the gpio_device a real device, we have added resource management, so devm_gpiochip_add_data() will cut down on overhead and reduce code lines. A huge slew of patches convert almost all drivers in the subsystem to use this. - Building on making the GPIO a real device, we add the first step of a new userspace ABI: the GPIO character device. We take small steps here, so we first add a pure *information* ABI and the tool "lsgpio" that will list all GPIO devices on the system and all lines on these devices. We can now discover GPIOs properly from userspace. We still have not come up with a way to actually *use* GPIOs from userspace. - To encourage people to use the character device for the future, we have it always-enabled when using GPIO. The old sysfs ABI is still opt-in (and can be used in parallel), but is marked as deprecated. We will keep it around for the foreseeable future, but it will not be extended to cover ever more use cases. Cleanup: - Bjorn Helgaas removed a whole slew of per-architecture <asm/gpio.h> includes. This dates back to when GPIO was an opt-in feature and no shared library even existed: just a header file with proper prototypes was provided and all semantics were up to the arch to implement. These patches make the GPIO chip even more a proper device and cleans out leftovers of the old in-kernel API here and there. Still some cruft is left but it's very little now. - There is still some clamping of return values for .get() going on, but we now return sane values in the vast majority of drivers and the errorpath is sanitized. Some patches for powerpc, blackfin and unicore still drop in. - We continue to switch the ARM, MIPS, blackfin, m68k local GPIO implementations to use gpiochip_add_data() and cut down on code lines. - MPC8xxx is converted to use the generic GPIO helpers. - ATH79 is converted to use the generic GPIO helpers. New drivers: - WinSystems WS16C48 - Acces 104-DIO-48E - F81866 (a F7188x variant) - Qoric (a MPC8xxx variant) - TS-4800 - SPI serializers (pisosr): simple 74xx shift registers connected to SPI to obtain a dirt-cheap output-only GPIO expander. - Texas Instruments TPIC2810 - Texas Instruments TPS65218 - Texas Instruments TPS65912 - X-Gene (ARM64) standby GPIO controller" * tag 'gpio-v4.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (194 commits) Revert "Share upstreaming patches" gpio: mcp23s08: Fix clearing of interrupt. gpiolib: Fix comment referring to gpio_*() in gpiod_*() gpio: pca953x: Fix pca953x_gpio_set_multiple() on 64-bit gpio: xgene: Fix kconfig for standby GIPO contoller gpio: Add generic serializer DT binding gpio: uapi: use 0xB4 as ioctl() major gpio: tps65912: fix bad merge Revert "gpio: lp3943: Drop pin_used and lp3943_gpio_request/lp3943_gpio_free" gpio: omap: drop dev field from gpio_bank structure gpio: mpc8xxx: Slightly update the code for better readability gpio: mpc8xxx: Remove *read_reg and *write_reg from struct mpc8xxx_gpio_chip gpio: mpc8xxx: Fixup setting gpio direction output gpio: mcp23s08: Add support for mcp23s18 dt-bindings: gpio: altera: Fix altr,interrupt-type property gpio: add driver for MEN 16Z127 GPIO controller gpio: lp3943: Drop pin_used and lp3943_gpio_request/lp3943_gpio_free gpio: timberdale: Switch to devm_ioremap_resource() gpio: ts4800: Add IMX51 dependency gpiolib: rewrite gpiodev_add_to_list ...
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile8
-rw-r--r--tools/gpio/Makefile12
-rw-r--r--tools/gpio/gpio-utils.c11
-rw-r--r--tools/gpio/gpio-utils.h27
-rw-r--r--tools/gpio/lsgpio.c195
5 files changed, 250 insertions, 3 deletions
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..5f57133b8c04
--- /dev/null
+++ b/tools/gpio/gpio-utils.h
@@ -0,0 +1,27 @@
+/*
+ * 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 <manuel.stahl@iis.fraunhofer.de>
+ * 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 <string.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+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..1124da375942
--- /dev/null
+++ b/tools/gpio/lsgpio.c
@@ -0,0 +1,195 @@
+/*
+ * 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 <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <linux/gpio.h>
+
+#include "gpio-utils.h"
+
+struct gpio_flag {
+ char *name;
+ unsigned long mask;
+};
+
+struct gpio_flag flagnames[] = {
+ {
+ .name = "kernel",
+ .mask = GPIOLINE_FLAG_KERNEL,
+ },
+ {
+ .name = "output",
+ .mask = GPIOLINE_FLAG_IS_OUT,
+ },
+ {
+ .name = "active-low",
+ .mask = GPIOLINE_FLAG_ACTIVE_LOW,
+ },
+ {
+ .name = "open-drain",
+ .mask = GPIOLINE_FLAG_OPEN_DRAIN,
+ },
+ {
+ .name = "open-source",
+ .mask = GPIOLINE_FLAG_OPEN_SOURCE,
+ },
+};
+
+void print_flags(unsigned long flags)
+{
+ int i;
+ int printed = 0;
+
+ for (i = 0; i < ARRAY_SIZE(flagnames); i++) {
+ if (flags & flagnames[i].mask) {
+ if (printed)
+ fprintf(stdout, " ");
+ fprintf(stdout, "%s", flagnames[i].name);
+ printed++;
+ }
+ }
+}
+
+int list_device(const char *device_name)
+{
+ struct gpiochip_info cinfo;
+ char *chrdev_name;
+ int fd;
+ int ret;
+ int i;
+
+ 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 exit_close_error;
+ }
+
+ /* Inspect this GPIO chip */
+ ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &cinfo);
+ if (ret == -1) {
+ ret = -errno;
+ perror("Failed to issue CHIPINFO IOCTL\n");
+ goto exit_close_error;
+ }
+ fprintf(stdout, "GPIO chip: %s, \"%s\", %u GPIO lines\n",
+ cinfo.name, cinfo.label, cinfo.lines);
+
+ /* Loop over the lines and print info */
+ for (i = 0; i < cinfo.lines; i++) {
+ struct gpioline_info linfo;
+
+ memset(&linfo, 0, sizeof(linfo));
+ linfo.line_offset = i;
+
+ ret = ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &linfo);
+ if (ret == -1) {
+ ret = -errno;
+ perror("Failed to issue LINEINFO IOCTL\n");
+ goto exit_close_error;
+ }
+ fprintf(stdout, "\tline %2d:", linfo.line_offset);
+ if (linfo.name[0])
+ fprintf(stdout, " \"%s\"", linfo.name);
+ else
+ fprintf(stdout, " unnamed");
+ if (linfo.consumer[0])
+ fprintf(stdout, " \"%s\"", linfo.consumer);
+ else
+ fprintf(stdout, " unused");
+ if (linfo.flags) {
+ fprintf(stdout, " [");
+ print_flags(linfo.flags);
+ fprintf(stdout, "]");
+ }
+ fprintf(stdout, "\n");
+
+ }
+
+exit_close_error:
+ if (close(fd) == -1)
+ perror("Failed to close GPIO character device file");
+ free(chrdev_name);
+ return ret;
+}
+
+void print_usage(void)
+{
+ fprintf(stderr, "Usage: lsgpio [options]...\n"
+ "List GPIO chips, lines and states\n"
+ " -n <name> 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;
+}