From a630fe34ddc09ec9b82df4867a8680d0929fe926 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 28 Jan 2020 22:08:45 +0100 Subject: [PATCH 01/59] gpio: pxa: Avoid a warning when gpio0 and gpio1 IRQS are not there Not all platforms use those. Let's use platform_get_irq_byname_optional() instead platform_get_irq_byname() so that we avoid a useless warning: [ 1.359455] pxa-gpio d4019000.gpio: IRQ gpio0 not found [ 1.359583] pxa-gpio d4019000.gpio: IRQ gpio1 not found Signed-off-by: Lubomir Rintel Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pxa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 9888b62f37af..567742d962ae 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -652,8 +652,8 @@ static int pxa_gpio_probe(struct platform_device *pdev) if (!pchip->irqdomain) return -ENOMEM; - irq0 = platform_get_irq_byname(pdev, "gpio0"); - irq1 = platform_get_irq_byname(pdev, "gpio1"); + irq0 = platform_get_irq_byname_optional(pdev, "gpio0"); + irq1 = platform_get_irq_byname_optional(pdev, "gpio1"); irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) || (irq_mux <= 0)) From 47d7d116661993499d626f7ec6f7679e83d59f15 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 31 Jan 2020 20:29:17 +0800 Subject: [PATCH 02/59] gpio: wcd934x: Don't change gpio direction in wcd_gpio_set The .set callback should just set output value. Signed-off-by: Axel Lin Reviewed-by: Srinivas Kandagatla Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wcd934x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-wcd934x.c b/drivers/gpio/gpio-wcd934x.c index 74913f2e5697..9d4ec8941b9b 100644 --- a/drivers/gpio/gpio-wcd934x.c +++ b/drivers/gpio/gpio-wcd934x.c @@ -66,7 +66,10 @@ static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin) static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val) { - wcd_gpio_direction_output(chip, pin, val); + struct wcd_gpio_data *data = gpiochip_get_data(chip); + + regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET, + WCD_PIN_MASK(pin), val ? WCD_PIN_MASK(pin) : 0); } static int wcd_gpio_probe(struct platform_device *pdev) From 47203198ed3df0f6896d07613182c05cb94110a5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 31 Jan 2020 20:29:18 +0800 Subject: [PATCH 03/59] gpio: wcd934x: Fix logic of wcd_gpio_get The check with register value and mask should be & rather than &&. While at it, also use "unsigned int" for value variable because regmap_read() takes unsigned int *val argument. Signed-off-by: Axel Lin Reviewed-by: Srinivas Kandagatla Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wcd934x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-wcd934x.c b/drivers/gpio/gpio-wcd934x.c index 9d4ec8941b9b..1cbce5990855 100644 --- a/drivers/gpio/gpio-wcd934x.c +++ b/drivers/gpio/gpio-wcd934x.c @@ -57,11 +57,11 @@ static int wcd_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin) { struct wcd_gpio_data *data = gpiochip_get_data(chip); - int value; + unsigned int value; regmap_read(data->map, WCD_REG_VAL_CTL_OFFSET, &value); - return !!(value && WCD_PIN_MASK(pin)); + return !!(value & WCD_PIN_MASK(pin)); } static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val) From 046e14afb3561523efd0047c35c20793ae5f8848 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Feb 2020 15:43:36 +0200 Subject: [PATCH 04/59] gpio: Avoid kernel.h inclusion where it's possible Inclusion of kernel.h increases the mess with the header dependencies. Avoid kernel.h inclusion where it's possible. Besides that, clean up a bit other inclusions inside GPIO subsystem headers. It includes: - removal pin control bits (forward declaration and header) from linux/gpio.h - removal of.h from asm-generic/gpio.h - use of explicit headers in gpio/consumer.h - add FIXME note with regard to gpio.h inclusion in of_gpio,h Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200205134336.20197-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- include/asm-generic/gpio.h | 4 ++-- include/linux/gpio.h | 2 -- include/linux/gpio/consumer.h | 5 ++++- include/linux/of_gpio.h | 9 ++++++--- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 19eadac415c4..aea9aee1f3e9 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -2,10 +2,8 @@ #ifndef _ASM_GENERIC_GPIO_H #define _ASM_GENERIC_GPIO_H -#include #include #include -#include #ifdef CONFIG_GPIOLIB @@ -140,6 +138,8 @@ static inline void gpio_unexport(unsigned gpio) #else /* !CONFIG_GPIOLIB */ +#include + static inline bool gpio_is_valid(int number) { /* only non-negative numbers are valid */ diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 2157717c2136..008ad3ee56b7 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -102,11 +102,9 @@ void devm_gpio_free(struct device *dev, unsigned int gpio); #include #include #include -#include struct device; struct gpio_chip; -struct pinctrl_dev; static inline bool gpio_is_valid(int number) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index bf2d017dd7b7..0a72fccf60ff 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -2,9 +2,10 @@ #ifndef __LINUX_GPIO_CONSUMER_H #define __LINUX_GPIO_CONSUMER_H +#include #include +#include #include -#include struct device; @@ -189,6 +190,8 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #else /* CONFIG_GPIOLIB */ +#include + static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 16967390a3fe..f821095218b0 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -11,9 +11,8 @@ #define __LINUX_OF_GPIO_H #include -#include -#include -#include +#include +#include /* FIXME: Shouldn't be here */ #include struct device_node; @@ -34,6 +33,8 @@ enum of_gpio_flags { #ifdef CONFIG_OF_GPIO +#include + /* * OF GPIO chip for memory mapped banks */ @@ -63,6 +64,8 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); #else /* CONFIG_OF_GPIO */ +#include + /* Drivers may not strictly depend on the GPIO support, so let them link. */ static inline int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags) From 3f2e4c11e136e2cffd60dbc840b59ff65f017328 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Dec 2019 18:48:55 +0100 Subject: [PATCH 05/59] kfifo: provide noirqsave variants of spinlocked in and out helpers Provide variants of spinlocked kfifo_in() and kfifo_out() routines which don't disable interrupts. Signed-off-by: Bartosz Golaszewski Acked-by: Stefani Seibold --- include/linux/kfifo.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index fc4b0b10210f..123c200ed7cb 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -517,6 +517,26 @@ __kfifo_uint_must_check_helper( \ __ret; \ }) +/** + * kfifo_in_spinlocked_noirqsave - put data into fifo using a spinlock for + * locking, don't disable interrupts + * @fifo: address of the fifo to be used + * @buf: the data to be added + * @n: number of elements to be added + * @lock: pointer to the spinlock to use for locking + * + * This is a variant of kfifo_in_spinlocked() but uses spin_lock/unlock() + * for locking and doesn't disable interrupts. + */ +#define kfifo_in_spinlocked_noirqsave(fifo, buf, n, lock) \ +({ \ + unsigned int __ret; \ + spin_lock(lock); \ + __ret = kfifo_in(fifo, buf, n); \ + spin_unlock(lock); \ + __ret; \ +}) + /* alias for kfifo_in_spinlocked, will be removed in a future release */ #define kfifo_in_locked(fifo, buf, n, lock) \ kfifo_in_spinlocked(fifo, buf, n, lock) @@ -569,6 +589,28 @@ __kfifo_uint_must_check_helper( \ }) \ ) +/** + * kfifo_out_spinlocked_noirqsave - get data from the fifo using a spinlock + * for locking, don't disable interrupts + * @fifo: address of the fifo to be used + * @buf: pointer to the storage buffer + * @n: max. number of elements to get + * @lock: pointer to the spinlock to use for locking + * + * This is a variant of kfifo_out_spinlocked() which uses spin_lock/unlock() + * for locking and doesn't disable interrupts. + */ +#define kfifo_out_spinlocked_noirqsave(fifo, buf, n, lock) \ +__kfifo_uint_must_check_helper( \ +({ \ + unsigned int __ret; \ + spin_lock(lock); \ + __ret = kfifo_out(fifo, buf, n); \ + spin_unlock(lock); \ + __ret; \ +}) \ +) + /* alias for kfifo_out_spinlocked, will be removed in a future release */ #define kfifo_out_locked(fifo, buf, n, lock) \ kfifo_out_spinlocked(fifo, buf, n, lock) From 5195a89e8583bba43ec13871a7226763e401b44e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Dec 2019 11:30:59 +0100 Subject: [PATCH 06/59] kfifo: provide kfifo_is_empty_spinlocked() Provide two spinlocked versions of kfifo_is_empty() to be used with spinlocked variants of kfifo_in() and kfifo_out(). Signed-off-by: Bartosz Golaszewski Acked-by: Stefani Seibold --- include/linux/kfifo.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index 123c200ed7cb..86249476b57f 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -246,6 +246,37 @@ __kfifo_int_must_check_helper(int val) __tmpq->kfifo.in == __tmpq->kfifo.out; \ }) +/** + * kfifo_is_empty_spinlocked - returns true if the fifo is empty using + * a spinlock for locking + * @fifo: address of the fifo to be used + * @lock: spinlock to be used for locking + */ +#define kfifo_is_empty_spinlocked(fifo, lock) \ +({ \ + unsigned long __flags; \ + bool __ret; \ + spin_lock_irqsave(lock, __flags); \ + __ret = kfifo_is_empty(fifo); \ + spin_unlock_irqrestore(lock, __flags); \ + __ret; \ +}) + +/** + * kfifo_is_empty_spinlocked_noirqsave - returns true if the fifo is empty + * using a spinlock for locking, doesn't disable interrupts + * @fifo: address of the fifo to be used + * @lock: spinlock to be used for locking + */ +#define kfifo_is_empty_spinlocked_noirqsave(fifo, lock) \ +({ \ + bool __ret; \ + spin_lock(lock); \ + __ret = kfifo_is_empty(fifo); \ + spin_unlock(lock); \ + __ret; \ +}) + /** * kfifo_is_full - returns true if the fifo is full * @fifo: address of the fifo to be used From dea9c80ee6726986d90260f135c83545427cbc4e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Nov 2019 12:19:21 +0100 Subject: [PATCH 07/59] gpiolib: rework the locking mechanism for lineevent kfifo The read_lock mutex is supposed to prevent collisions between reading and writing to the line event kfifo but it's actually only taken when the events are being read from it. Drop the mutex entirely and reuse the spinlock made available to us in the waitqueue struct. Take the lock whenever the fifo is modified or inspected. Drop the call to kfifo_to_user() and instead first extract the new element from kfifo when the lock is taken and only then pass it on to the user after the spinlock is released. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 66 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 753283486037..43d98309e725 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -787,8 +787,6 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) * @irq: the interrupt that trigger in response to events on this GPIO * @wait: wait queue that handles blocking reads of events * @events: KFIFO for the GPIO events - * @read_lock: mutex lock to protect reads from colliding with adding - * new events to the FIFO * @timestamp: cache for the timestamp storing it between hardirq * and IRQ thread, used to bring the timestamp close to the actual * event @@ -801,7 +799,6 @@ struct lineevent_state { int irq; wait_queue_head_t wait; DECLARE_KFIFO(events, struct gpioevent_data, 16); - struct mutex read_lock; u64 timestamp; }; @@ -817,7 +814,7 @@ static __poll_t lineevent_poll(struct file *filep, poll_wait(filep, &le->wait, wait); - if (!kfifo_is_empty(&le->events)) + if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock)) events = EPOLLIN | EPOLLRDNORM; return events; @@ -830,43 +827,52 @@ static ssize_t lineevent_read(struct file *filep, loff_t *f_ps) { struct lineevent_state *le = filep->private_data; - unsigned int copied; + struct gpioevent_data event; + ssize_t bytes_read = 0; int ret; - if (count < sizeof(struct gpioevent_data)) + if (count < sizeof(event)) return -EINVAL; do { + spin_lock(&le->wait.lock); if (kfifo_is_empty(&le->events)) { - if (filep->f_flags & O_NONBLOCK) - return -EAGAIN; + if (bytes_read) { + spin_unlock(&le->wait.lock); + return bytes_read; + } - ret = wait_event_interruptible(le->wait, + if (filep->f_flags & O_NONBLOCK) { + spin_unlock(&le->wait.lock); + return -EAGAIN; + } + + ret = wait_event_interruptible_locked(le->wait, !kfifo_is_empty(&le->events)); - if (ret) + if (ret) { + spin_unlock(&le->wait.lock); return ret; + } } - if (mutex_lock_interruptible(&le->read_lock)) - return -ERESTARTSYS; - ret = kfifo_to_user(&le->events, buf, count, &copied); - mutex_unlock(&le->read_lock); + ret = kfifo_out(&le->events, &event, 1); + spin_unlock(&le->wait.lock); + if (ret != 1) { + /* + * This should never happen - we were holding the lock + * from the moment we learned the fifo is no longer + * empty until now. + */ + ret = -EIO; + break; + } - if (ret) - return ret; + if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + return -EFAULT; + bytes_read += sizeof(event); + } while (count >= bytes_read + sizeof(event)); - /* - * If we couldn't read anything from the fifo (a different - * thread might have been faster) we either return -EAGAIN if - * the file descriptor is non-blocking, otherwise we go back to - * sleep and wait for more data to arrive. - */ - if (copied == 0 && (filep->f_flags & O_NONBLOCK)) - return -EAGAIN; - - } while (copied == 0); - - return copied; + return bytes_read; } static int lineevent_release(struct inode *inode, struct file *filep) @@ -968,7 +974,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) return IRQ_NONE; } - ret = kfifo_put(&le->events, ge); + ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge, + 1, &le->wait.lock); if (ret) wake_up_poll(&le->wait, EPOLLIN); @@ -1083,7 +1090,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) INIT_KFIFO(le->events); init_waitqueue_head(&le->wait); - mutex_init(&le->read_lock); /* Request a thread to read the events */ ret = request_threaded_irq(le->irq, From 248ae1752e91438cb7cfc8432b88bc34410e8e4e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 29 Nov 2019 11:22:18 +0100 Subject: [PATCH 08/59] gpiolib: emit a debug message when adding events to a full kfifo Currently if the line-event kfifo is full, we just silently drop any new events. Add a ratelimited debug message so that we at least have some trace in the kernel log of event overflow. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 43d98309e725..36afe0b2b150 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -978,6 +978,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) 1, &le->wait.lock); if (ret) wake_up_poll(&le->wait, EPOLLIN); + else + pr_debug_ratelimited("event FIFO is full - event dropped\n"); return IRQ_HANDLED; } From d2ac25798208fb85f866056cd7d8030eb919da99 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 3 Dec 2019 14:08:44 +0100 Subject: [PATCH 09/59] gpiolib: provide a dedicated function for setting lineinfo We'll soon be filling out the gpioline_info structure in multiple places. Add a separate function that given a gpio_desc sets all relevant fields. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- drivers/gpio/gpiolib.c | 98 ++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 36afe0b2b150..443321f9cf63 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1147,6 +1147,60 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) return ret; } +static void gpio_desc_to_lineinfo(struct gpio_desc *desc, + struct gpioline_info *info) +{ + struct gpio_chip *chip = desc->gdev->chip; + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + + if (desc->name) { + strncpy(info->name, desc->name, sizeof(info->name)); + info->name[sizeof(info->name) - 1] = '\0'; + } else { + info->name[0] = '\0'; + } + + if (desc->label) { + strncpy(info->consumer, desc->label, sizeof(info->consumer)); + info->consumer[sizeof(info->consumer) - 1] = '\0'; + } else { + info->consumer[0] = '\0'; + } + + /* + * Userspace only need to know that the kernel is using this GPIO so + * it can't use it. + */ + info->flags = 0; + if (test_bit(FLAG_REQUESTED, &desc->flags) || + test_bit(FLAG_IS_HOGGED, &desc->flags) || + test_bit(FLAG_USED_AS_IRQ, &desc->flags) || + test_bit(FLAG_EXPORT, &desc->flags) || + test_bit(FLAG_SYSFS, &desc->flags) || + !pinctrl_gpio_can_use_line(chip->base + info->line_offset)) + info->flags |= GPIOLINE_FLAG_KERNEL; + if (test_bit(FLAG_IS_OUT, &desc->flags)) + info->flags |= GPIOLINE_FLAG_IS_OUT; + if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) + info->flags |= GPIOLINE_FLAG_ACTIVE_LOW; + if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) + info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN | + GPIOLINE_FLAG_IS_OUT); + if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) + info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE | + GPIOLINE_FLAG_IS_OUT); + if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_DISABLE; + if (test_bit(FLAG_PULL_DOWN, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; + if (test_bit(FLAG_PULL_UP, &desc->flags)) + info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP; + + spin_unlock_irqrestore(&gpio_lock, flags); +} + /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ @@ -1187,49 +1241,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - if (desc->name) { - strncpy(lineinfo.name, desc->name, - sizeof(lineinfo.name)); - lineinfo.name[sizeof(lineinfo.name)-1] = '\0'; - } else { - lineinfo.name[0] = '\0'; - } - if (desc->label) { - strncpy(lineinfo.consumer, desc->label, - sizeof(lineinfo.consumer)); - lineinfo.consumer[sizeof(lineinfo.consumer)-1] = '\0'; - } else { - lineinfo.consumer[0] = '\0'; - } - - /* - * Userspace only need to know that the kernel is using - * this GPIO so it can't use it. - */ - lineinfo.flags = 0; - if (test_bit(FLAG_REQUESTED, &desc->flags) || - test_bit(FLAG_IS_HOGGED, &desc->flags) || - test_bit(FLAG_USED_AS_IRQ, &desc->flags) || - test_bit(FLAG_EXPORT, &desc->flags) || - test_bit(FLAG_SYSFS, &desc->flags) || - !pinctrl_gpio_can_use_line(chip->base + lineinfo.line_offset)) - lineinfo.flags |= GPIOLINE_FLAG_KERNEL; - if (test_bit(FLAG_IS_OUT, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_IS_OUT; - if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_ACTIVE_LOW; - if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) - lineinfo.flags |= (GPIOLINE_FLAG_OPEN_DRAIN | - GPIOLINE_FLAG_IS_OUT); - if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) - lineinfo.flags |= (GPIOLINE_FLAG_OPEN_SOURCE | - GPIOLINE_FLAG_IS_OUT); - if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_DISABLE; - if (test_bit(FLAG_PULL_DOWN, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; - if (test_bit(FLAG_PULL_UP, &desc->flags)) - lineinfo.flags |= GPIOLINE_FLAG_BIAS_PULL_UP; + gpio_desc_to_lineinfo(desc, &lineinfo); if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) return -EFAULT; From 51c1064e82e77b39a49889287ca50709303e2f26 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 22 Nov 2019 15:19:21 +0100 Subject: [PATCH 10/59] gpiolib: add new ioctl() for monitoring changes in line info Currently there is no way for user-space to be informed about changes in status of GPIO lines e.g. when someone else requests the line or its config changes. We can only periodically re-read the line-info. This is fine for simple one-off user-space tools, but any daemon that provides a centralized access to GPIO chips would benefit hugely from an event driven line info synchronization. This patch adds a new ioctl() that allows user-space processes to reuse the file descriptor associated with the character device for watching any changes in line properties. Every such event contains the updated line information. Currently the events are generated on three types of status changes: when a line is requested, when it's released and when its config is changed. The first two are self-explanatory. For the third one: this will only happen when another user-space process calls the new SET_CONFIG ioctl() as any changes that can happen from within the kernel (i.e. set_transitory() or set_debounce()) are of no interest to user-space. Signed-off-by: Bartosz Golaszewski Reviewed-by: Linus Walleij --- drivers/gpio/gpiolib.c | 188 ++++++++++++++++++++++++++++++++++++-- drivers/gpio/gpiolib.h | 1 + include/uapi/linux/gpio.h | 30 ++++++ 3 files changed, 210 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 443321f9cf63..f73077f26eff 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -546,6 +546,9 @@ static long linehandle_set_config(struct linehandle_state *lh, if (ret) return ret; } + + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_CONFIG, desc); } return 0; } @@ -1201,14 +1204,25 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, spin_unlock_irqrestore(&gpio_lock, flags); } +struct gpio_chardev_data { + struct gpio_device *gdev; + wait_queue_head_t wait; + DECLARE_KFIFO(events, struct gpioline_info_changed, 32); + struct notifier_block lineinfo_changed_nb; + unsigned long *watched_lines; +}; + /* * gpio_ioctl() - ioctl handler for the GPIO chardev */ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct gpio_device *gdev = filp->private_data; + struct gpio_chardev_data *priv = filp->private_data; + struct gpio_device *gdev = priv->gdev; struct gpio_chip *chip = gdev->chip; void __user *ip = (void __user *)arg; + struct gpio_desc *desc; + __u32 offset; /* We fail any subsequent ioctl():s when the chip is gone */ if (!chip) @@ -1230,9 +1244,9 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user(ip, &chipinfo, sizeof(chipinfo))) return -EFAULT; return 0; - } else if (cmd == GPIO_GET_LINEINFO_IOCTL) { + } else if (cmd == GPIO_GET_LINEINFO_IOCTL || + cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) { struct gpioline_info lineinfo; - struct gpio_desc *desc; if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) return -EFAULT; @@ -1245,11 +1259,25 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) return -EFAULT; + + if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) + set_bit(desc_to_gpio(desc), priv->watched_lines); + return 0; } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { return linehandle_create(gdev, ip); } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) { return lineevent_create(gdev, ip); + } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) { + if (copy_from_user(&offset, ip, sizeof(offset))) + return -EFAULT; + + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + clear_bit(desc_to_gpio(desc), &desc->flags); + return 0; } return -EINVAL; } @@ -1262,6 +1290,101 @@ static long gpio_ioctl_compat(struct file *filp, unsigned int cmd, } #endif +static struct gpio_chardev_data * +to_gpio_chardev_data(struct notifier_block *nb) +{ + return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb); +} + +static int lineinfo_changed_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct gpio_chardev_data *priv = to_gpio_chardev_data(nb); + struct gpioline_info_changed chg; + struct gpio_desc *desc = data; + int ret; + + if (!test_bit(desc_to_gpio(desc), priv->watched_lines)) + return NOTIFY_DONE; + + memset(&chg, 0, sizeof(chg)); + chg.info.line_offset = gpio_chip_hwgpio(desc); + chg.event_type = action; + chg.timestamp = ktime_get_ns(); + gpio_desc_to_lineinfo(desc, &chg.info); + + ret = kfifo_in_spinlocked(&priv->events, &chg, 1, &priv->wait.lock); + if (ret) + wake_up_poll(&priv->wait, EPOLLIN); + else + pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n"); + + return NOTIFY_OK; +} + +static __poll_t lineinfo_watch_poll(struct file *filep, + struct poll_table_struct *pollt) +{ + struct gpio_chardev_data *priv = filep->private_data; + __poll_t events = 0; + + poll_wait(filep, &priv->wait, pollt); + + if (!kfifo_is_empty_spinlocked_noirqsave(&priv->events, + &priv->wait.lock)) + events = EPOLLIN | EPOLLRDNORM; + + return events; +} + +static ssize_t lineinfo_watch_read(struct file *filep, char __user *buf, + size_t count, loff_t *off) +{ + struct gpio_chardev_data *priv = filep->private_data; + struct gpioline_info_changed event; + ssize_t bytes_read = 0; + int ret; + + if (count < sizeof(event)) + return -EINVAL; + + do { + spin_lock(&priv->wait.lock); + if (kfifo_is_empty(&priv->events)) { + if (bytes_read) { + spin_unlock(&priv->wait.lock); + return bytes_read; + } + + if (filep->f_flags & O_NONBLOCK) { + spin_unlock(&priv->wait.lock); + return -EAGAIN; + } + + ret = wait_event_interruptible_locked(priv->wait, + !kfifo_is_empty(&priv->events)); + if (ret) { + spin_unlock(&priv->wait.lock); + return ret; + } + } + + ret = kfifo_out(&priv->events, &event, 1); + spin_unlock(&priv->wait.lock); + if (ret != 1) { + ret = -EIO; + break; + /* We should never get here. See lineevent_read(). */ + } + + if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + return -EFAULT; + bytes_read += sizeof(event); + } while (count >= bytes_read + sizeof(event)); + + return bytes_read; +} + /** * gpio_chrdev_open() - open the chardev for ioctl operations * @inode: inode for this chardev @@ -1272,14 +1395,48 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) { struct gpio_device *gdev = container_of(inode->i_cdev, struct gpio_device, chrdev); + struct gpio_chardev_data *priv; + int ret = -ENOMEM; /* Fail on open if the backing gpiochip is gone */ if (!gdev->chip) return -ENODEV; - get_device(&gdev->dev); - filp->private_data = gdev; - return nonseekable_open(inode, filp); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); + if (!priv->watched_lines) + goto out_free_priv; + + init_waitqueue_head(&priv->wait); + INIT_KFIFO(priv->events); + priv->gdev = gdev; + + priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; + ret = atomic_notifier_chain_register(&gdev->notifier, + &priv->lineinfo_changed_nb); + if (ret) + goto out_free_bitmap; + + get_device(&gdev->dev); + filp->private_data = priv; + + ret = nonseekable_open(inode, filp); + if (ret) + goto out_unregister_notifier; + + return ret; + +out_unregister_notifier: + atomic_notifier_chain_unregister(&gdev->notifier, + &priv->lineinfo_changed_nb); +out_free_bitmap: + bitmap_free(priv->watched_lines); +out_free_priv: + kfree(priv); + return ret; } /** @@ -1290,17 +1447,23 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) */ static int gpio_chrdev_release(struct inode *inode, struct file *filp) { - struct gpio_device *gdev = container_of(inode->i_cdev, - struct gpio_device, chrdev); + struct gpio_chardev_data *priv = filp->private_data; + struct gpio_device *gdev = priv->gdev; + bitmap_free(priv->watched_lines); + atomic_notifier_chain_unregister(&gdev->notifier, + &priv->lineinfo_changed_nb); put_device(&gdev->dev); + kfree(priv); + return 0; } - static const struct file_operations gpio_fileops = { .release = gpio_chrdev_release, .open = gpio_chrdev_open, + .poll = lineinfo_watch_poll, + .read = lineinfo_watch_read, .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = gpio_ioctl, @@ -1511,6 +1674,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, spin_unlock_irqrestore(&gpio_lock, flags); + ATOMIC_INIT_NOTIFIER_HEAD(&gdev->notifier); + #ifdef CONFIG_PINCTRL INIT_LIST_HEAD(&gdev->pin_ranges); #endif @@ -2843,6 +3008,8 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) } done: spin_unlock_irqrestore(&gpio_lock, flags); + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_REQUESTED, desc); return ret; } @@ -2940,6 +3107,9 @@ static bool gpiod_free_commit(struct gpio_desc *desc) } spin_unlock_irqrestore(&gpio_lock, flags); + atomic_notifier_call_chain(&desc->gdev->notifier, + GPIOLINE_CHANGED_RELEASED, desc); + return ret; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 3e0aab2945d8..5ab90746b519 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -56,6 +56,7 @@ struct gpio_device { const char *label; void *data; struct list_head list; + struct atomic_notifier_head notifier; #ifdef CONFIG_PINCTRL /* diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h index 799cf823d493..dca320764e4d 100644 --- a/include/uapi/linux/gpio.h +++ b/include/uapi/linux/gpio.h @@ -59,6 +59,34 @@ struct gpioline_info { /* Maximum number of requested handles */ #define GPIOHANDLES_MAX 64 +/* Possible line status change events */ +enum { + GPIOLINE_CHANGED_REQUESTED = 1, + GPIOLINE_CHANGED_RELEASED, + GPIOLINE_CHANGED_CONFIG, +}; + +/** + * struct gpioline_info_changed - Information about a change in status + * of a GPIO line + * @info: updated line information + * @timestamp: estimate of time of status change occurrence, in nanoseconds + * and GPIOLINE_CHANGED_CONFIG + * @event_type: one of GPIOLINE_CHANGED_REQUESTED, GPIOLINE_CHANGED_RELEASED + * + * Note: struct gpioline_info embedded here has 32-bit alignment on its own, + * but it works fine with 64-bit alignment too. With its 72 byte size, we can + * guarantee there are no implicit holes between it and subsequent members. + * The 20-byte padding at the end makes sure we don't add any implicit padding + * at the end of the structure on 64-bit architectures. + */ +struct gpioline_info_changed { + struct gpioline_info info; + __u64 timestamp; + __u32 event_type; + __u32 padding[5]; /* for future use */ +}; + /* Linerequest flags */ #define GPIOHANDLE_REQUEST_INPUT (1UL << 0) #define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1) @@ -176,6 +204,8 @@ struct gpioevent_data { #define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) #define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) +#define GPIO_GET_LINEINFO_WATCH_IOCTL _IOWR(0xB4, 0x0b, struct gpioline_info) +#define GPIO_GET_LINEINFO_UNWATCH_IOCTL _IOWR(0xB4, 0x0c, __u32) #define GPIO_GET_LINEHANDLE_IOCTL _IOWR(0xB4, 0x03, struct gpiohandle_request) #define GPIO_GET_LINEEVENT_IOCTL _IOWR(0xB4, 0x04, struct gpioevent_request) From 33f0c47b8fb4724792b16351a32b24902a5d3b07 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 27 Nov 2019 10:17:54 +0100 Subject: [PATCH 11/59] tools: gpio: implement gpio-watch Add a simple program that allows to test the new LINECHANGED_FD ioctl(). Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- tools/gpio/.gitignore | 1 + tools/gpio/Build | 1 + tools/gpio/Makefile | 11 ++++- tools/gpio/gpio-watch.c | 99 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 tools/gpio/gpio-watch.c diff --git a/tools/gpio/.gitignore b/tools/gpio/.gitignore index a94c0e83b209..eab36c6d7751 100644 --- a/tools/gpio/.gitignore +++ b/tools/gpio/.gitignore @@ -1,4 +1,5 @@ gpio-event-mon gpio-hammer +gpio-watch lsgpio include/linux/gpio.h diff --git a/tools/gpio/Build b/tools/gpio/Build index 4141f35837db..67c7b7f6a717 100644 --- a/tools/gpio/Build +++ b/tools/gpio/Build @@ -2,3 +2,4 @@ gpio-utils-y += gpio-utils.o lsgpio-y += lsgpio.o gpio-utils.o gpio-hammer-y += gpio-hammer.o gpio-utils.o gpio-event-mon-y += gpio-event-mon.o gpio-utils.o +gpio-watch-y += gpio-watch.o diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index 6080de58861f..842287e42c83 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -18,7 +18,7 @@ MAKEFLAGS += -r override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include -ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon +ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon gpio-watch ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) all: $(ALL_PROGRAMS) @@ -66,6 +66,15 @@ $(GPIO_EVENT_MON_IN): prepare FORCE $(OUTPUT)gpio-utils-in.o $(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ +# +# gpio-watch +# +GPIO_WATCH_IN := $(OUTPUT)gpio-watch-in.o +$(GPIO_WATCH_IN): prepare FORCE + $(Q)$(MAKE) $(build)=gpio-watch +$(OUTPUT)gpio-watch: $(GPIO_WATCH_IN) + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ + clean: rm -f $(ALL_PROGRAMS) rm -f $(OUTPUT)include/linux/gpio.h diff --git a/tools/gpio/gpio-watch.c b/tools/gpio/gpio-watch.c new file mode 100644 index 000000000000..5cea24fddfa7 --- /dev/null +++ b/tools/gpio/gpio-watch.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * gpio-watch - monitor unrequested lines for property changes using the + * character device + * + * Copyright (C) 2019 BayLibre SAS + * Author: Bartosz Golaszewski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + struct gpioline_info_changed chg; + struct gpioline_info req; + struct pollfd pfd; + int fd, i, j, ret; + char *event, *end; + ssize_t rd; + + if (argc < 3) + goto err_usage; + + fd = open(argv[1], O_RDWR | O_CLOEXEC); + if (fd < 0) { + perror("unable to open gpiochip"); + return EXIT_FAILURE; + } + + for (i = 0, j = 2; i < argc - 2; i++, j++) { + memset(&req, 0, sizeof(req)); + + req.line_offset = strtoul(argv[j], &end, 0); + if (*end != '\0') + goto err_usage; + + ret = ioctl(fd, GPIO_GET_LINEINFO_WATCH_IOCTL, &req); + if (ret) { + perror("unable to set up line watch"); + return EXIT_FAILURE; + } + } + + pfd.fd = fd; + pfd.events = POLLIN | POLLPRI; + + for (;;) { + ret = poll(&pfd, 1, 5000); + if (ret < 0) { + perror("error polling the linechanged fd"); + return EXIT_FAILURE; + } else if (ret > 0) { + memset(&chg, 0, sizeof(chg)); + rd = read(pfd.fd, &chg, sizeof(chg)); + if (rd < 0 || rd != sizeof(chg)) { + if (rd != sizeof(chg)) + errno = EIO; + + perror("error reading line change event"); + return EXIT_FAILURE; + } + + switch (chg.event_type) { + case GPIOLINE_CHANGED_REQUESTED: + event = "requested"; + break; + case GPIOLINE_CHANGED_RELEASED: + event = "released"; + break; + case GPIOLINE_CHANGED_CONFIG: + event = "config changed"; + break; + default: + fprintf(stderr, + "invalid event type received from the kernel\n"); + return EXIT_FAILURE; + } + + printf("line %u: %s at %llu\n", + chg.info.line_offset, event, chg.timestamp); + } + } + + return 0; + +err_usage: + printf("%s: ...\n", argv[0]); + return EXIT_FAILURE; +} From b36368f685d66a53da73a05b63af32233e32cf36 Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Sun, 9 Feb 2020 15:26:00 +0530 Subject: [PATCH 12/59] gpio: rcar: Fix typo in comment "Positive" is spelled incorrectly as "Postive" in comment fix this. Signed-off-by: Ashish Chavan Link: https://lore.kernel.org/r/20200209095600.16394-1-ashish.gschavan@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index f800b250971c..7284473c9fe3 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -116,7 +116,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p, spin_lock_irqsave(&p->lock, flags); - /* Configure postive or negative logic in POSNEG */ + /* Configure positive or negative logic in POSNEG */ gpio_rcar_modify_bit(p, POSNEG, hwirq, !active_high_rising_edge); /* Configure edge or level trigger in EDGLEVEL */ @@ -228,7 +228,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, spin_lock_irqsave(&p->lock, flags); - /* Configure postive logic in POSNEG */ + /* Configure positive logic in POSNEG */ gpio_rcar_modify_bit(p, POSNEG, gpio, false); /* Select "General Input/Output Mode" in IOINTSEL */ From f6e51bb331d51d4b08fe9b766c5ed442f889c853 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 10 Feb 2020 16:50:59 +0100 Subject: [PATCH 13/59] gpio: mockup: coding-style fix The indentation is wrong in gpio_mockup_apply_pull(). This patch makes the code more readable. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200210155059.29609-1-brgl@bgdev.pl Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mockup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 7d343bea784a..3eb94f3740d1 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -171,7 +171,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, /* Change the value unless we're actively driving the line. */ if (!test_bit(FLAG_REQUESTED, &desc->flags) || - !test_bit(FLAG_IS_OUT, &desc->flags)) + !test_bit(FLAG_IS_OUT, &desc->flags)) __gpio_mockup_set(chip, offset, value); out: From 023892ec80f0efcffe22045e92bb89f3f1480f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 11 Feb 2020 14:51:21 +0100 Subject: [PATCH 14/59] gpio: siox: use raw spinlock for irq related locking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the irq related callbacks are called with the (raw) spinlock desc->lock being held. So the lock here must be raw as well. Also irqs were already disabled by the caller for the irq chip callbacks, so the non-irq variants of spin_lock must be used there. Fixes: be8c8facc707 ("gpio: new driver to work with a 8x12 siox") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20200211135121.15752-1-uwe@kleine-koenig.org Signed-off-by: Linus Walleij --- drivers/gpio/gpio-siox.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-siox.c b/drivers/gpio/gpio-siox.c index 311f66757b92..26e1fe092304 100644 --- a/drivers/gpio/gpio-siox.c +++ b/drivers/gpio/gpio-siox.c @@ -15,7 +15,7 @@ struct gpio_siox_ddata { u8 setdata[1]; u8 getdata[3]; - spinlock_t irqlock; + raw_spinlock_t irqlock; u32 irq_enable; u32 irq_status; u32 irq_type[20]; @@ -44,7 +44,7 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) mutex_lock(&ddata->lock); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock_irq(&ddata->irqlock); for (offset = 0; offset < 12; ++offset) { unsigned int bitpos = 11 - offset; @@ -66,7 +66,7 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) trigger = ddata->irq_status & ddata->irq_enable; - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock_irq(&ddata->irqlock); ddata->getdata[0] = buf[0]; ddata->getdata[1] = buf[1]; @@ -84,9 +84,9 @@ static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[]) * handler of the irq chip. But it doesn't, so we have * to clean the irq_status here. */ - spin_lock_irq(&ddata->irqlock); + raw_spin_lock_irq(&ddata->irqlock); ddata->irq_status &= ~(1 << offset); - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock_irq(&ddata->irqlock); handle_nested_irq(irq); } @@ -101,9 +101,9 @@ static void gpio_siox_irq_ack(struct irq_data *d) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_status &= ~(1 << d->hwirq); - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); } static void gpio_siox_irq_mask(struct irq_data *d) @@ -112,9 +112,9 @@ static void gpio_siox_irq_mask(struct irq_data *d) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_enable &= ~(1 << d->hwirq); - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); } static void gpio_siox_irq_unmask(struct irq_data *d) @@ -123,9 +123,9 @@ static void gpio_siox_irq_unmask(struct irq_data *d) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_enable |= 1 << d->hwirq; - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); } static int gpio_siox_irq_set_type(struct irq_data *d, u32 type) @@ -134,9 +134,9 @@ static int gpio_siox_irq_set_type(struct irq_data *d, u32 type) struct gpio_siox_ddata *ddata = container_of(ic, struct gpio_siox_ddata, ichip); - spin_lock_irq(&ddata->irqlock); + raw_spin_lock(&ddata->irqlock); ddata->irq_type[d->hwirq] = type; - spin_unlock_irq(&ddata->irqlock); + raw_spin_unlock(&ddata->irqlock); return 0; } @@ -222,7 +222,7 @@ static int gpio_siox_probe(struct siox_device *sdevice) dev_set_drvdata(dev, ddata); mutex_init(&ddata->lock); - spin_lock_init(&ddata->irqlock); + raw_spin_lock_init(&ddata->irqlock); ddata->gchip.base = -1; ddata->gchip.can_sleep = 1; From 1739a2d852265977836152be43073ead5c64d1ea Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 19 Feb 2020 10:47:02 +0100 Subject: [PATCH 15/59] gpiolib: use gpiochip_get_desc() where applicable Whenever retrieving a descriptor from a gpiochip: use the provided helper which checks for errors. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200219094702.6463-1-brgl@bgdev.pl Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f73077f26eff..611709fd560f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3143,7 +3143,9 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) if (offset >= chip->ngpio) return NULL; - desc = &chip->gpiodev->descs[offset]; + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) + return NULL; if (test_bit(FLAG_REQUESTED, &desc->flags) == 0) return NULL; From f8850206e160bfe35de9ca2e726ab6d6b8cb77dd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 20 Feb 2020 15:56:24 +0100 Subject: [PATCH 16/59] gpio: Switch timestamps to ktime_get_ns() The existing use of ktime_get_real_ns() in the timestamps from the GPIO events is dubious. We have had several discussions about this timestamp, and it is unclear whether userspace has ever taken into account that a timestamp from ktime_get_real_ns() can actually move backwards in time relative the previous timetamp, and userspace is more likely to expect a monotonic counter. Background: https://lore.kernel.org/linux-gpio/CAK8P3a1Skvm48sje8FNDPLYqyz9Lf8q0qX1QETWtyZTxuX4k1g@mail.gmail.com/ https://marc.info/?l=linux-gpio&m=151661955709074&w=2 The change is ABI incompatible, but incompatible in a way that is IMO more likely to fix future bugs rather than break current userspace. To the best of my knowledge all userspace expects a monotonic timestamp and users are just lucky that they very seldom move backwards in time. Cc: Arnd Bergmann Acked-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 611709fd560f..2c3a9c1c76be 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -954,7 +954,7 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) * we didn't get the timestamp from lineevent_irq_handler(). */ if (!le->timestamp) - ge.timestamp = ktime_get_real_ns(); + ge.timestamp = ktime_get_ns(); else ge.timestamp = le->timestamp; @@ -995,7 +995,7 @@ static irqreturn_t lineevent_irq_handler(int irq, void *p) * Just store the timestamp in hardirq context so we get it as * close in time as possible to the actual event. */ - le->timestamp = ktime_get_real_ns(); + le->timestamp = ktime_get_ns(); return IRQ_WAKE_THREAD; } From bc21077e084b80c22072a40d32beb24ea33938ec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Feb 2020 14:01:48 +0100 Subject: [PATCH 17/59] gpio: of: Extract of_gpiochip_add_hog() Extract the code to add all GPIO hogs of a gpio-hog node into its own function, so it can be reused. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200220130149.26283-2-geert+renesas@glider.be Reviewed-by: Frank Rowand Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 49 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index c6d30f73df07..2b47f9388607 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -604,6 +604,35 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, return desc; } +/** + * of_gpiochip_add_hog - Add all hogs in a hog device node + * @chip: gpio chip to act on + * @hog: device node describing the hogs + * + * Returns error if it fails otherwise 0 on success. + */ +static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog) +{ + enum gpiod_flags dflags; + struct gpio_desc *desc; + unsigned long lflags; + const char *name; + unsigned int i; + int ret; + + for (i = 0;; i++) { + desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags); + if (IS_ERR(desc)) + break; + + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret < 0) + return ret; + } + + return 0; +} + /** * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions * @chip: gpio chip to act on @@ -614,29 +643,17 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, */ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) { - struct gpio_desc *desc = NULL; struct device_node *np; - const char *name; - unsigned long lflags; - enum gpiod_flags dflags; - unsigned int i; int ret; for_each_available_child_of_node(chip->of_node, np) { if (!of_property_read_bool(np, "gpio-hog")) continue; - for (i = 0;; i++) { - desc = of_parse_own_gpio(np, chip, i, &name, &lflags, - &dflags); - if (IS_ERR(desc)) - break; - - ret = gpiod_hog(desc, name, lflags, dflags); - if (ret < 0) { - of_node_put(np); - return ret; - } + ret = of_gpiochip_add_hog(chip, np); + if (ret < 0) { + of_node_put(np); + return ret; } } From 63636d956c455c0fbe2118078a03f563ddd6bf6e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Feb 2020 14:01:49 +0100 Subject: [PATCH 18/59] gpio: of: Add DT overlay support for GPIO hogs As GPIO hogs are configured at GPIO controller initialization time, adding/removing GPIO hogs in DT overlays does not work. Add support for GPIO hogs described in DT overlays by registering an OF reconfiguration notifier, to handle the addition and removal of GPIO hog subnodes to/from a GPIO controller device node. Note that when a GPIO hog device node is being removed, its "gpios" properties is no longer available, so we have to keep track of which node a hog belongs to, which is done by adding a pointer to the hog's device node to struct gpio_desc. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200220130149.26283-3-geert+renesas@glider.be Reviewed-by: Frank Rowand Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 90 +++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib-of.h | 2 + drivers/gpio/gpiolib.c | 14 ++++-- drivers/gpio/gpiolib.h | 3 ++ 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 2b47f9388607..ccc449df3792 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -628,6 +628,10 @@ static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog) ret = gpiod_hog(desc, name, lflags, dflags); if (ret < 0) return ret; + +#ifdef CONFIG_OF_DYNAMIC + desc->hog = hog; +#endif } return 0; @@ -655,11 +659,97 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) of_node_put(np); return ret; } + + of_node_set_flag(np, OF_POPULATED); } return 0; } +#ifdef CONFIG_OF_DYNAMIC +/** + * of_gpiochip_remove_hog - Remove all hogs in a hog device node + * @chip: gpio chip to act on + * @hog: device node describing the hogs + */ +static void of_gpiochip_remove_hog(struct gpio_chip *chip, + struct device_node *hog) +{ + struct gpio_desc *descs = chip->gpiodev->descs; + unsigned int i; + + for (i = 0; i < chip->ngpio; i++) { + if (test_bit(FLAG_IS_HOGGED, &descs[i].flags) && + descs[i].hog == hog) + gpiochip_free_own_desc(&descs[i]); + } +} + +static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) +{ + return chip->gpiodev->dev.of_node == data; +} + +static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) +{ + return gpiochip_find(np, of_gpiochip_match_node); +} + +static int of_gpio_notify(struct notifier_block *nb, unsigned long action, + void *arg) +{ + struct of_reconfig_data *rd = arg; + struct gpio_chip *chip; + int ret; + + /* + * This only supports adding and removing complete gpio-hog nodes. + * Modifying an existing gpio-hog node is not supported (except for + * changing its "status" property, which is treated the same as + * addition/removal). + */ + switch (of_reconfig_get_state_change(action, arg)) { + case OF_RECONFIG_CHANGE_ADD: + if (!of_property_read_bool(rd->dn, "gpio-hog")) + return NOTIFY_OK; /* not for us */ + + if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) + return NOTIFY_OK; + + chip = of_find_gpiochip_by_node(rd->dn->parent); + if (chip == NULL) + return NOTIFY_OK; /* not for us */ + + ret = of_gpiochip_add_hog(chip, rd->dn); + if (ret < 0) { + pr_err("%s: failed to add hogs for %pOF\n", __func__, + rd->dn); + of_node_clear_flag(rd->dn, OF_POPULATED); + return notifier_from_errno(ret); + } + break; + + case OF_RECONFIG_CHANGE_REMOVE: + if (!of_node_check_flag(rd->dn, OF_POPULATED)) + return NOTIFY_OK; /* already depopulated */ + + chip = of_find_gpiochip_by_node(rd->dn->parent); + if (chip == NULL) + return NOTIFY_OK; /* not for us */ + + of_gpiochip_remove_hog(chip, rd->dn); + of_node_clear_flag(rd->dn, OF_POPULATED); + break; + } + + return NOTIFY_OK; +} + +struct notifier_block gpio_of_notifier = { + .notifier_call = of_gpio_notify, +}; +#endif /* CONFIG_OF_DYNAMIC */ + /** * of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags * @gc: pointer to the gpio_chip structure diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index 9768831b1fe2..ed26664f1537 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -35,4 +35,6 @@ static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc) } #endif /* CONFIG_OF_GPIO */ +extern struct notifier_block gpio_of_notifier; + #endif /* GPIOLIB_OF_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2c3a9c1c76be..9ad86477af9c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3103,6 +3103,9 @@ static bool gpiod_free_commit(struct gpio_desc *desc) clear_bit(FLAG_PULL_DOWN, &desc->flags); clear_bit(FLAG_BIAS_DISABLE, &desc->flags); clear_bit(FLAG_IS_HOGGED, &desc->flags); +#ifdef CONFIG_OF_DYNAMIC + desc->hog = NULL; +#endif ret = true; } @@ -5281,10 +5284,15 @@ static int __init gpiolib_dev_init(void) if (ret < 0) { pr_err("gpiolib: failed to allocate char dev region\n"); bus_unregister(&gpio_bus_type); - } else { - gpiolib_initialized = true; - gpiochip_setup_devs(); + return ret; } + + gpiolib_initialized = true; + gpiochip_setup_devs(); + + if (IS_ENABLED(CONFIG_OF_DYNAMIC)) + WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier)); + return ret; } core_initcall(gpiolib_dev_init); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 5ab90746b519..853ce681b4a4 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -120,6 +120,9 @@ struct gpio_desc { const char *label; /* Name of the GPIO */ const char *name; +#ifdef CONFIG_OF_DYNAMIC + struct device_node *hog; +#endif }; int gpiod_request(struct gpio_desc *desc, const char *label); From 869233f81337bfb33c79f1e7539147d52c0ba383 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 25 Feb 2020 13:47:25 +0200 Subject: [PATCH 19/59] gpiolib: Optimize gpiochip_remove() when check for requested line Here are the following optimizations have been done: - break the loop after first found requested line - due to above, drop redundant boolean variable - replace open coded variant of gpiochip_is_requested() - due to above, drop redundant pointer to struct gpio_desc - use 'unsigned int' instead of 'unsigned' for loop counter Note, pointer to struct gpio_chip followed by pointer to struct gpio_device is still valid, back link is not. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200225114725.839-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9ad86477af9c..2253ab495349 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1797,10 +1797,8 @@ EXPORT_SYMBOL_GPL(gpiochip_get_data); void gpiochip_remove(struct gpio_chip *chip) { struct gpio_device *gdev = chip->gpiodev; - struct gpio_desc *desc; unsigned long flags; - unsigned i; - bool requested = false; + unsigned int i; /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ gpiochip_sysfs_unregister(gdev); @@ -1820,13 +1818,12 @@ void gpiochip_remove(struct gpio_chip *chip) spin_lock_irqsave(&gpio_lock, flags); for (i = 0; i < gdev->ngpio; i++) { - desc = &gdev->descs[i]; - if (test_bit(FLAG_REQUESTED, &desc->flags)) - requested = true; + if (gpiochip_is_requested(chip, i)) + break; } spin_unlock_irqrestore(&gpio_lock, flags); - if (requested) + if (i == gdev->ngpio) dev_crit(&gdev->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); From ec18d7e7d28625355bf2f5c18d47c09b1cde5cde Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 15:06:18 -0600 Subject: [PATCH 20/59] gpio: uniphier: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-uniphier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index 7ec97499b7f7..f99f3c10bed0 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -30,7 +30,7 @@ struct uniphier_gpio_priv { struct irq_domain *domain; void __iomem *regs; spinlock_t lock; - u32 saved_vals[0]; + u32 saved_vals[]; }; static unsigned int uniphier_gpio_bank_to_reg(unsigned int bank) From df2cd589766cf7c35a73690fc22d6a6be179cb57 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 13 Feb 2020 19:09:04 +0200 Subject: [PATCH 21/59] gpiolib: Rename 'event' to 'ge' to be consistent with other use Rename 'event' to 'ge' to be consistent with other use. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2253ab495349..2982d983c4fd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -830,11 +830,11 @@ static ssize_t lineevent_read(struct file *filep, loff_t *f_ps) { struct lineevent_state *le = filep->private_data; - struct gpioevent_data event; + struct gpioevent_data ge; ssize_t bytes_read = 0; int ret; - if (count < sizeof(event)) + if (count < sizeof(ge)) return -EINVAL; do { @@ -858,7 +858,7 @@ static ssize_t lineevent_read(struct file *filep, } } - ret = kfifo_out(&le->events, &event, 1); + ret = kfifo_out(&le->events, &ge, 1); spin_unlock(&le->wait.lock); if (ret != 1) { /* @@ -870,10 +870,10 @@ static ssize_t lineevent_read(struct file *filep, break; } - if (copy_to_user(buf + bytes_read, &event, sizeof(event))) + if (copy_to_user(buf + bytes_read, &ge, sizeof(ge))) return -EFAULT; - bytes_read += sizeof(event); - } while (count >= bytes_read + sizeof(event)); + bytes_read += sizeof(ge); + } while (count >= bytes_read + sizeof(ge)); return bytes_read; } From 48543bd8e92880b1ca81b15cf392103dc82cd3e0 Mon Sep 17 00:00:00 2001 From: Kent Gibson Date: Mon, 24 Feb 2020 14:49:53 +0000 Subject: [PATCH 22/59] gpiolib: fix unwatch ioctl() Fix the field having a bit cleared by the unwatch ioctl(). Fixes: 51c1064e82e7 ("gpiolib: add new ioctl() for monitoring changes in line info") Signed-off-by: Kent Gibson Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2982d983c4fd..20683695c598 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1276,7 +1276,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - clear_bit(desc_to_gpio(desc), &desc->flags); + clear_bit(desc_to_gpio(desc), priv->watched_lines); return 0; } return -EINVAL; From 1931479788c5e3c0396a0bde3606e517c64b9f95 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 26 Feb 2020 14:53:23 +0100 Subject: [PATCH 23/59] gpiolib: fix bitmap operations related to line event watching When operating on the bits of watched_lines bitmap, we're using desc_to_gpio() which returns the GPIO number from the global numberspace. This leads to all sorts of memory corruptions and invalid behavior. We should switch to using gpio_chip_hwgpio() instead. Fixes: 51c1064e82e7 ("gpiolib: add new ioctl() for monitoring changes in line info") Reported-by: Kent Gibson Signed-off-by: Bartosz Golaszewski Tested-by: Kent Gibson --- drivers/gpio/gpiolib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20683695c598..bc71f05d5193 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1261,7 +1261,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EFAULT; if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) - set_bit(desc_to_gpio(desc), priv->watched_lines); + set_bit(gpio_chip_hwgpio(desc), priv->watched_lines); return 0; } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { @@ -1276,7 +1276,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (IS_ERR(desc)) return PTR_ERR(desc); - clear_bit(desc_to_gpio(desc), priv->watched_lines); + clear_bit(gpio_chip_hwgpio(desc), priv->watched_lines); return 0; } return -EINVAL; @@ -1304,7 +1304,7 @@ static int lineinfo_changed_notify(struct notifier_block *nb, struct gpio_desc *desc = data; int ret; - if (!test_bit(desc_to_gpio(desc), priv->watched_lines)) + if (!test_bit(gpio_chip_hwgpio(desc), priv->watched_lines)) return NOTIFY_DONE; memset(&chg, 0, sizeof(chg)); From ca18a852ee3696ea625efa13b1fac3c33f025a53 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 Mar 2020 09:24:48 +0100 Subject: [PATCH 24/59] gpiolib: Fix inverted check in gpiochip_remove() The optimization to check for requested lines actually optimized for the uncomon error case, where one of the GPIO lines is still in use. Hence the error message must be printed when the loop is terminated early, not when it went through all available GPIO lines. Fixes: 869233f81337bfb3 ("gpiolib: Optimize gpiochip_remove() when check for requested line") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200302082448.11795-1-geert+renesas@glider.be Acked-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2253ab495349..0879731caf25 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1823,7 +1823,7 @@ void gpiochip_remove(struct gpio_chip *chip) } spin_unlock_irqrestore(&gpio_lock, flags); - if (i == gdev->ngpio) + if (i != gdev->ngpio) dev_crit(&gdev->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); From bc0ae0e737f5167348579612493e2754e2122dfb Mon Sep 17 00:00:00 2001 From: Asmaa Mnebhi Date: Mon, 2 Mar 2020 16:04:46 -0500 Subject: [PATCH 25/59] gpio: add driver for Mellanox BlueField 2 GPIO controller This patch adds support for the GPIO controller used by Mellanox BlueField 2 SOCs. Signed-off-by: Asmaa Mnebhi Link: https://lore.kernel.org/r/1680de9eb6d2b8855228dde9a2dd065f0dcbe1fb.1583182325.git.Asmaa@mellanox.com Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-mlxbf2.c | 335 +++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+) create mode 100644 drivers/gpio/gpio-mlxbf2.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b8013cf90064..6234ccc90e7e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1399,6 +1399,13 @@ config GPIO_MLXBF help Say Y here if you want GPIO support on Mellanox BlueField SoC. +config GPIO_MLXBF2 + tristate "Mellanox BlueField 2 SoC GPIO" + depends on (MELLANOX_PLATFORM && ARM64 && ACPI) || (64BIT && COMPILE_TEST) + select GPIO_GENERIC + help + Say Y here if you want GPIO support on Mellanox BlueField 2 SoC. + config GPIO_ML_IOH tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" depends on X86 || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 0b571264ddbc..b2cfc21a97f3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o +obj-$(CONFIG_GPIO_MLXBF2) += gpio-mlxbf2.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o obj-$(CONFIG_GPIO_MOXTET) += gpio-moxtet.o diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c new file mode 100644 index 000000000000..7b7085050219 --- /dev/null +++ b/drivers/gpio/gpio-mlxbf2.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * There are 3 YU GPIO blocks: + * gpio[0]: HOST_GPIO0->HOST_GPIO31 + * gpio[1]: HOST_GPIO32->HOST_GPIO63 + * gpio[2]: HOST_GPIO64->HOST_GPIO69 + */ +#define MLXBF2_GPIO_MAX_PINS_PER_BLOCK 32 + +/* + * arm_gpio_lock register: + * bit[31] lock status: active if set + * bit[15:0] set lock + * The lock is enabled only if 0xd42f is written to this field + */ +#define YU_ARM_GPIO_LOCK_ADDR 0x2801088 +#define YU_ARM_GPIO_LOCK_SIZE 0x8 +#define YU_LOCK_ACTIVE_BIT(val) (val >> 31) +#define YU_ARM_GPIO_LOCK_ACQUIRE 0xd42f +#define YU_ARM_GPIO_LOCK_RELEASE 0x0 + +/* + * gpio[x] block registers and their offset + */ +#define YU_GPIO_DATAIN 0x04 +#define YU_GPIO_MODE1 0x08 +#define YU_GPIO_MODE0 0x0c +#define YU_GPIO_DATASET 0x14 +#define YU_GPIO_DATACLEAR 0x18 +#define YU_GPIO_MODE1_CLEAR 0x50 +#define YU_GPIO_MODE0_SET 0x54 +#define YU_GPIO_MODE0_CLEAR 0x58 + +#ifdef CONFIG_PM +struct mlxbf2_gpio_context_save_regs { + u32 gpio_mode0; + u32 gpio_mode1; +}; +#endif + +/* BlueField-2 gpio block context structure. */ +struct mlxbf2_gpio_context { + struct gpio_chip gc; + + /* YU GPIO blocks address */ + void __iomem *gpio_io; + +#ifdef CONFIG_PM + struct mlxbf2_gpio_context_save_regs *csave_regs; +#endif +}; + +/* BlueField-2 gpio shared structure. */ +struct mlxbf2_gpio_param { + void __iomem *io; + struct resource *res; + struct mutex *lock; +}; + +static struct resource yu_arm_gpio_lock_res = { + .start = YU_ARM_GPIO_LOCK_ADDR, + .end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1, + .name = "YU_ARM_GPIO_LOCK", +}; + +static DEFINE_MUTEX(yu_arm_gpio_lock_mutex); + +static struct mlxbf2_gpio_param yu_arm_gpio_lock_param = { + .res = &yu_arm_gpio_lock_res, + .lock = &yu_arm_gpio_lock_mutex, +}; + +/* Request memory region and map yu_arm_gpio_lock resource */ +static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + resource_size_t size; + int ret = 0; + + mutex_lock(yu_arm_gpio_lock_param.lock); + + /* Check if the memory map already exists */ + if (yu_arm_gpio_lock_param.io) + goto exit; + + res = yu_arm_gpio_lock_param.res; + size = resource_size(res); + + if (!devm_request_mem_region(dev, res->start, size, res->name)) { + ret = -EFAULT; + goto exit; + } + + yu_arm_gpio_lock_param.io = devm_ioremap(dev, res->start, size); + if (IS_ERR(yu_arm_gpio_lock_param.io)) + ret = PTR_ERR(yu_arm_gpio_lock_param.io); + +exit: + mutex_unlock(yu_arm_gpio_lock_param.lock); + + return ret; +} + +/* + * Acquire the YU arm_gpio_lock to be able to change the direction + * mode. If the lock_active bit is already set, return an error. + */ +static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs) +{ + u32 arm_gpio_lock_val; + + spin_lock(&gs->gc.bgpio_lock); + mutex_lock(yu_arm_gpio_lock_param.lock); + + arm_gpio_lock_val = readl(yu_arm_gpio_lock_param.io); + + /* + * When lock active bit[31] is set, ModeX is write enabled + */ + if (YU_LOCK_ACTIVE_BIT(arm_gpio_lock_val)) { + mutex_unlock(yu_arm_gpio_lock_param.lock); + spin_unlock(&gs->gc.bgpio_lock); + return -EINVAL; + } + + writel(YU_ARM_GPIO_LOCK_ACQUIRE, yu_arm_gpio_lock_param.io); + + return 0; +} + +/* + * Release the YU arm_gpio_lock after changing the direction mode. + */ +static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs) +{ + writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io); + mutex_unlock(yu_arm_gpio_lock_param.lock); + spin_unlock(&gs->gc.bgpio_lock); +} + +/* + * mode0 and mode1 are both locked by the gpio_lock field. + * + * Together, mode0 and mode1 define the gpio Mode dependeing also + * on Reg_DataOut. + * + * {mode1,mode0}:{Reg_DataOut=0,Reg_DataOut=1}->{DataOut=0,DataOut=1} + * + * {0,0}:Reg_DataOut{0,1}->{Z,Z} Input PAD + * {0,1}:Reg_DataOut{0,1}->{0,1} Full drive Output PAD + * {1,0}:Reg_DataOut{0,1}->{0,Z} 0-set PAD to low, 1-float + * {1,1}:Reg_DataOut{0,1}->{Z,1} 0-float, 1-set PAD to high + */ + +/* + * Set input direction: + * {mode1,mode0} = {0,0} + */ +static int mlxbf2_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); + int ret; + + /* + * Although the arm_gpio_lock was set in the probe function, check again + * if it is still enabled to be able to write to the ModeX registers. + */ + ret = mlxbf2_gpio_lock_acquire(gs); + if (ret < 0) + return ret; + + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_CLEAR); + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); + + mlxbf2_gpio_lock_release(gs); + + return ret; +} + +/* + * Set output direction: + * {mode1,mode0} = {0,1} + */ +static int mlxbf2_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, + int value) +{ + struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); + int ret = 0; + + /* + * Although the arm_gpio_lock was set in the probe function, + * check again it is still enabled to be able to write to the + * ModeX registers. + */ + ret = mlxbf2_gpio_lock_acquire(gs); + if (ret < 0) + return ret; + + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); + writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_SET); + + mlxbf2_gpio_lock_release(gs); + + return ret; +} + +/* BlueField-2 GPIO driver initialization routine. */ +static int +mlxbf2_gpio_probe(struct platform_device *pdev) +{ + struct mlxbf2_gpio_context *gs; + struct device *dev = &pdev->dev; + struct gpio_chip *gc; + struct resource *res; + unsigned int npins; + int ret; + + gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); + if (!gs) + return -ENOMEM; + + /* YU GPIO block address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res)); + if (!gs->gpio_io) + return -ENOMEM; + + ret = mlxbf2_gpio_get_lock_res(pdev); + if (ret) { + dev_err(dev, "Failed to get yu_arm_gpio_lock resource\n"); + return ret; + } + + if (device_property_read_u32(dev, "npins", &npins)) + npins = MLXBF2_GPIO_MAX_PINS_PER_BLOCK; + + gc = &gs->gc; + + ret = bgpio_init(gc, dev, 4, + gs->gpio_io + YU_GPIO_DATAIN, + gs->gpio_io + YU_GPIO_DATASET, + gs->gpio_io + YU_GPIO_DATACLEAR, + NULL, + NULL, + 0); + + gc->direction_input = mlxbf2_gpio_direction_input; + gc->direction_output = mlxbf2_gpio_direction_output; + gc->ngpio = npins; + gc->owner = THIS_MODULE; + + platform_set_drvdata(pdev, gs); + + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); + if (ret) { + dev_err(dev, "Failed adding memory mapped gpiochip\n"); + return ret; + } + + return 0; +} + +#ifdef CONFIG_PM +static int mlxbf2_gpio_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); + + gs->csave_regs->gpio_mode0 = readl(gs->gpio_io + + YU_GPIO_MODE0); + gs->csave_regs->gpio_mode1 = readl(gs->gpio_io + + YU_GPIO_MODE1); + + return 0; +} + +static int mlxbf2_gpio_resume(struct platform_device *pdev) +{ + struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); + + writel(gs->csave_regs->gpio_mode0, gs->gpio_io + + YU_GPIO_MODE0); + writel(gs->csave_regs->gpio_mode1, gs->gpio_io + + YU_GPIO_MODE1); + + return 0; +} +#endif + +static const struct acpi_device_id mlxbf2_gpio_acpi_match[] = { + { "MLNXBF22", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match); + +static struct platform_driver mlxbf2_gpio_driver = { + .driver = { + .name = "mlxbf2_gpio", + .acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match), + }, + .probe = mlxbf2_gpio_probe, +#ifdef CONFIG_PM + .suspend = mlxbf2_gpio_suspend, + .resume = mlxbf2_gpio_resume, +#endif +}; + +module_platform_driver(mlxbf2_gpio_driver); + +MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); +MODULE_AUTHOR("Mellanox Technologies"); +MODULE_LICENSE("GPL v2"); From 55be2f50336f67800513b46c5ba6270e4ed0e784 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 14:54:30 -0800 Subject: [PATCH 26/59] ARM: OMAP2+: Handle errors for cpu_pm We need to check for errors when calling cpu_pm_enter() and cpu_cluster_pm_enter(). And we need to bail out on errors as otherwise we can enter a deeper idle state when not desired. I'm not aware of the lack of error handling causing issues yet, but we need this at least for blocking deeper idle states when a GPIO instance has pending interrupts. Cc: Dave Gerlach Cc: Grygorii Strashko Cc: Keerthy Cc: Ladislav Michl Cc: Russell King Cc: Tero Kristo Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20200304225433.37336-2-tony@atomide.com Signed-off-by: Linus Walleij --- arch/arm/mach-omap2/cpuidle34xx.c | 9 +++++++-- arch/arm/mach-omap2/cpuidle44xx.c | 26 +++++++++++++++++--------- arch/arm/mach-omap2/pm34xx.c | 8 ++++++-- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 532a3e4b98c6..090a8aafb25e 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -109,6 +109,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = &omap3_idle_data[index]; + int error; if (omap_irq_pending() || need_resched()) goto return_sleep_time; @@ -125,8 +126,11 @@ static int omap3_enter_idle(struct cpuidle_device *dev, * Call idle CPU PM enter notifier chain so that * VFP context is saved. */ - if (cx->mpu_state == PWRDM_POWER_OFF) - cpu_pm_enter(); + if (cx->mpu_state == PWRDM_POWER_OFF) { + error = cpu_pm_enter(); + if (error) + goto out_clkdm_set; + } /* Execute ARM wfi */ omap_sram_idle(); @@ -139,6 +143,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF) cpu_pm_exit(); +out_clkdm_set: /* Re-allow idle for C1 */ if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE) clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index fe75d4fa6073..6f5f89711f25 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c @@ -122,6 +122,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, { struct idle_statedata *cx = state_ptr + index; u32 mpuss_can_lose_context = 0; + int error; /* * CPU0 has to wait and stay ON until CPU1 is OFF state. @@ -159,7 +160,9 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, * Call idle CPU PM enter notifier chain so that * VFP and per CPU interrupt context is saved. */ - cpu_pm_enter(); + error = cpu_pm_enter(); + if (error) + goto cpu_pm_out; if (dev->cpu == 0) { pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); @@ -169,13 +172,17 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, * Call idle CPU cluster PM enter notifier chain * to save GIC and wakeupgen context. */ - if (mpuss_can_lose_context) - cpu_cluster_pm_enter(); + if (mpuss_can_lose_context) { + error = cpu_cluster_pm_enter(); + if (error) + goto cpu_cluster_pm_out; + } } omap4_enter_lowpower(dev->cpu, cx->cpu_state); cpu_done[dev->cpu] = true; +cpu_cluster_pm_out: /* Wakeup CPU1 only if it is not offlined */ if (dev->cpu == 0 && cpumask_test_cpu(1, cpu_online_mask)) { @@ -197,12 +204,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, } } - /* - * Call idle CPU PM exit notifier chain to restore - * VFP and per CPU IRQ context. - */ - cpu_pm_exit(); - /* * Call idle CPU cluster PM exit notifier chain * to restore GIC and wakeupgen context. @@ -210,6 +211,13 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev, if (dev->cpu == 0 && mpuss_can_lose_context) cpu_cluster_pm_exit(); + /* + * Call idle CPU PM exit notifier chain to restore + * VFP and per CPU IRQ context. + */ + cpu_pm_exit(); + +cpu_pm_out: tick_broadcast_exit(); fail: diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index e66e9948636c..6df395fff971 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -191,6 +191,7 @@ void omap_sram_idle(void) int per_next_state = PWRDM_POWER_ON; int core_next_state = PWRDM_POWER_ON; u32 sdrc_pwr = 0; + int error; mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); switch (mpu_next_state) { @@ -219,8 +220,11 @@ void omap_sram_idle(void) pwrdm_pre_transition(NULL); /* PER */ - if (per_next_state == PWRDM_POWER_OFF) - cpu_cluster_pm_enter(); + if (per_next_state == PWRDM_POWER_OFF) { + error = cpu_cluster_pm_enter(); + if (error) + return; + } /* CORE */ if (core_next_state < PWRDM_POWER_ON) { From 43582265be8c5c29f4f420ce08a29d48f560c86e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 14:54:31 -0800 Subject: [PATCH 27/59] gpio: omap: Block idle on pending gpio interrupts With the SoC cpuidle handling fixed for cpu_pm, we can now start to return NOTIFY_BAD if there there are pending gpio interrupts. This way the deeper SoC idle states can get blocked, and gpio latency is improved in some cases. Note that this will not help with the latency if the SoC has already entered a deeper idle state. Note that this patch depends on cpu_pm properly handling the errors returned by notifiers. For omap variants, this is fixed with patch "ARM: OMAP2+: Handle errors for cpu_pm". Cc: Dave Gerlach Cc: Grygorii Strashko Cc: Keerthy Cc: Ladislav Michl Cc: Russell King Cc: Tero Kristo Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20200304225433.37336-3-tony@atomide.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 3bd8adaeed9e..3d50cb25aa24 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1237,26 +1237,35 @@ static int gpio_omap_cpu_notifier(struct notifier_block *nb, { struct gpio_bank *bank; unsigned long flags; + int ret = NOTIFY_OK; + u32 isr, mask; bank = container_of(nb, struct gpio_bank, nb); raw_spin_lock_irqsave(&bank->lock, flags); + if (bank->is_suspended) + goto out_unlock; + switch (cmd) { case CPU_CLUSTER_PM_ENTER: - if (bank->is_suspended) + mask = omap_get_gpio_irqbank_mask(bank); + isr = readl_relaxed(bank->base + bank->regs->irqstatus) & mask; + if (isr) { + ret = NOTIFY_BAD; break; + } omap_gpio_idle(bank, true); break; case CPU_CLUSTER_PM_ENTER_FAILED: case CPU_CLUSTER_PM_EXIT: - if (bank->is_suspended) - break; omap_gpio_unidle(bank); break; } + +out_unlock: raw_spin_unlock_irqrestore(&bank->lock, flags); - return NOTIFY_OK; + return ret; } static const struct omap_gpio_reg_offs omap2_gpio_regs = { From 579ced8fdb00b8e94304a83e3cc419f6f8eab08e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 4 Mar 2020 14:54:32 -0800 Subject: [PATCH 28/59] Revert "gpio: omap: Fix lost edge wake-up interrupts" This reverts commit a522f1d0c381c42f3ace13b8bbeeccabdd6d2e5c. With cpu_pm handling fixed for omaps, and with gpio-omap now returning notify error on pending interrupts, we can drop the old workaround for seeing if there may be pending edge interrupts. Depends-on: ARM: OMAP2+: Handle errors for cpu_pm Depends-on: gpio: omap: Block idle on pending gpio interrupts Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Ladislav Michl Cc: Peter Ujfalusi Cc: Russell King Cc: Tero Kristo Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20200304225433.37336-4-tony@atomide.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 3d50cb25aa24..b8e2ecc3eade 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1102,23 +1102,13 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) { struct device *dev = bank->chip.parent; void __iomem *base = bank->base; - u32 mask, nowake; + u32 nowake; bank->saved_datain = readl_relaxed(base + bank->regs->datain); if (!bank->enabled_non_wakeup_gpios) goto update_gpio_context_count; - /* Check for pending EDGE_FALLING, ignore EDGE_BOTH */ - mask = bank->enabled_non_wakeup_gpios & bank->context.fallingdetect; - mask &= ~bank->context.risingdetect; - bank->saved_datain |= mask; - - /* Check for pending EDGE_RISING, ignore EDGE_BOTH */ - mask = bank->enabled_non_wakeup_gpios & bank->context.risingdetect; - mask &= ~bank->context.fallingdetect; - bank->saved_datain &= ~mask; - if (!may_lose_context) goto update_gpio_context_count; From a28e1c0505a09c3a2d81fed1c8453ac2d8d02b3a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Mar 2020 09:15:22 +0100 Subject: [PATCH 29/59] gpio: Move devres calls to devres file These two devres functions devm_gpiochip_[add|remove]() were in the wrong file. They should be in gpiolib-devres.c not gpiolib.c. Link: https://lore.kernel.org/r/20200313081522.35143-1-linus.walleij@linaro.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-devres.c | 46 +++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib.c | 46 ----------------------------------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c index 72b6001c56ef..5c91c4365da1 100644 --- a/drivers/gpio/gpiolib-devres.c +++ b/drivers/gpio/gpiolib-devres.c @@ -478,3 +478,49 @@ void devm_gpio_free(struct device *dev, unsigned int gpio) &gpio)); } EXPORT_SYMBOL_GPL(devm_gpio_free); + +static void devm_gpio_chip_release(struct device *dev, void *res) +{ + struct gpio_chip *gc = *(struct gpio_chip **)res; + + gpiochip_remove(gc); +} + +/** + * devm_gpiochip_add_data() - Resource managed gpiochip_add_data() + * @dev: pointer to the device that gpio_chip belongs to. + * @gc: the GPIO chip to register + * @data: driver-private data associated with this chip + * + * Context: potentially before irqs will work + * + * The gpio chip automatically be released when the device is unbound. + * + * Returns: + * A negative errno if the chip can't be registered, such as because the + * gc->base is invalid or already associated with a different chip. + * Otherwise it returns zero as a success code. + */ +int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc, + void *data) +{ + struct gpio_chip **ptr; + int ret; + + ptr = devres_alloc(devm_gpio_chip_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = gpiochip_add_data(gc, data); + if (ret < 0) { + devres_free(ptr); + return ret; + } + + *ptr = gc; + devres_add(dev, ptr); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_gpiochip_add_data); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 02f8b2b81199..00890f38f95f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1838,52 +1838,6 @@ void gpiochip_remove(struct gpio_chip *chip) } EXPORT_SYMBOL_GPL(gpiochip_remove); -static void devm_gpio_chip_release(struct device *dev, void *res) -{ - struct gpio_chip *chip = *(struct gpio_chip **)res; - - gpiochip_remove(chip); -} - -/** - * devm_gpiochip_add_data() - Resource managed gpiochip_add_data() - * @dev: pointer to the device that gpio_chip belongs to. - * @chip: the chip to register, with chip->base initialized - * @data: driver-private data associated with this chip - * - * Context: potentially before irqs will work - * - * The gpio chip automatically be released when the device is unbound. - * - * Returns: - * A negative errno if the chip can't be registered, such as because the - * chip->base is invalid or already associated with a different chip. - * Otherwise it returns zero as a success code. - */ -int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip, - void *data) -{ - struct gpio_chip **ptr; - int ret; - - ptr = devres_alloc(devm_gpio_chip_release, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - ret = gpiochip_add_data(chip, data); - if (ret < 0) { - devres_free(ptr); - return ret; - } - - *ptr = chip; - devres_add(dev, ptr); - - return 0; -} -EXPORT_SYMBOL_GPL(devm_gpiochip_add_data); - /** * gpiochip_find() - iterator for locating a specific gpio_chip * @data: data to pass to match function From 32f5f62d7991c62095ee62a060b35dec0a9ac404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= Date: Tue, 3 Mar 2020 21:01:48 +0100 Subject: [PATCH 30/59] gpio: uapi: Improve phrasing around arrays representing empty strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Character arrays can be considered empty strings (if they are immediately terminated), but they cannot be NULL. Signed-off-by: Jonathan Neuschäfer Signed-off-by: Bartosz Golaszewski --- include/uapi/linux/gpio.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h index dca320764e4d..0206383c0383 100644 --- a/include/uapi/linux/gpio.h +++ b/include/uapi/linux/gpio.h @@ -18,7 +18,7 @@ * struct gpiochip_info - Information about a certain GPIO chip * @name: the Linux kernel name of this GPIO chip * @label: a functional name for this GPIO chip, such as a product - * number, may be NULL + * number, may be empty * @lines: number of GPIO lines on this chip */ struct gpiochip_info { @@ -44,10 +44,10 @@ struct gpiochip_info { * @flags: various flags for this line * @name: the name of this GPIO line, such as the output pin of the line on the * chip, a rail or a pin header name on a board, as specified by the gpio - * chip, may be NULL + * chip, may be empty * @consumer: a functional name for the consumer of this GPIO line as set by - * whatever is using it, will be NULL if there is no current user but may - * also be NULL if the consumer doesn't set this up + * whatever is using it, will be empty if there is no current user but may + * also be empty if the consumer doesn't set this up */ struct gpioline_info { __u32 line_offset; From f8c3cea834d27ad1a292f735ef092be7aaef1bba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 3 Mar 2020 16:50:35 +0100 Subject: [PATCH 31/59] docs: gpio: driver.rst: don't mark literal blocks twice Two literal blocks there are marked with both "::" and .. code-block:: c This causes Sphinx (2.4.1) to do the wrong thing, causing lots of warnings: Documentation/driver-api/gpio/driver.rst:425: WARNING: Unexpected indentation. Documentation/driver-api/gpio/driver.rst:423: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:427: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/driver-api/gpio/driver.rst:429: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:429: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:429: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:433: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:446: WARNING: Unexpected indentation. Documentation/driver-api/gpio/driver.rst:440: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:440: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:447: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/driver-api/gpio/driver.rst:449: WARNING: Definition list ends without a blank line; unexpected unindent. Documentation/driver-api/gpio/driver.rst:462: WARNING: Unexpected indentation. Documentation/driver-api/gpio/driver.rst:460: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:462: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:465: WARNING: Block quote ends without a blank line; unexpected unindent. Documentation/driver-api/gpio/driver.rst:467: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:467: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:467: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:471: WARNING: Inline emphasis start-string without end-string. Documentation/driver-api/gpio/driver.rst:478: WARNING: Inline emphasis start-string without end-string. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Bartosz Golaszewski --- Documentation/driver-api/gpio/driver.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index 871922529332..9809f593c0ab 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -416,7 +416,7 @@ The preferred way to set up the helpers is to fill in the struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip. If you do this, the additional irq_chip will be set up by gpiolib at the same time as setting up the rest of the GPIO functionality. The following -is a typical example of a cascaded interrupt handler using gpio_irq_chip:: +is a typical example of a cascaded interrupt handler using gpio_irq_chip: .. code-block:: c @@ -453,7 +453,7 @@ is a typical example of a cascaded interrupt handler using gpio_irq_chip:: return devm_gpiochip_add_data(dev, &g->gc, g); The helper support using hierarchical interrupt controllers as well. -In this case the typical set-up will look like this:: +In this case the typical set-up will look like this: .. code-block:: c From 1a555713ac9d169dbe43363aafe0633f2dc58daf Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 3 Mar 2020 10:28:28 +0100 Subject: [PATCH 32/59] gpio: pl061: Warn when IRQ line has not been configured Existing (irq < 0) condition is always false because adev->irq has unsigned type and contains 0 in case of failed irq_of_parse_and_map(). Up to now all the mapping errors were silently ignored. Seems that repairing this check would be backwards-incompatible and might break the probe() for the implementations without IRQ support. Therefore warn the user instead. Signed-off-by: Alexander Sverdlin Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pl061.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 5df7782e348f..3439120f166a 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -326,10 +326,8 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) writeb(0, pl061->base + GPIOIE); /* disable irqs */ irq = adev->irq[0]; - if (irq < 0) { - dev_err(&adev->dev, "invalid IRQ\n"); - return -ENODEV; - } + if (!irq) + dev_warn(&adev->dev, "IRQ support disabled\n"); pl061->parent_irq = irq; girq = &pl061->gc.irq; From d4e9361442e23fe6edd4c1702004f19fc15553df Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Sat, 7 Mar 2020 21:31:57 +0800 Subject: [PATCH 33/59] gpio: mxc: Add COMPILE_TEST support for GPIO_MXC Add COMPILE_TEST support to GPIO_MXC driver for better compile testing coverage. Signed-off-by: Anson Huang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 6234ccc90e7e..ef55c45131c5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -394,7 +394,7 @@ config GPIO_MVEBU config GPIO_MXC def_bool y - depends on ARCH_MXC + depends on ARCH_MXC || COMPILE_TEST select GPIO_GENERIC select GENERIC_IRQ_CHIP From 6876ca311bfca5d7cae30c4b529aeb9449c072eb Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 9 Mar 2020 09:57:38 +0800 Subject: [PATCH 34/59] gpio: mxs: add COMPILE_TEST support for GPIO_MXS Add COMPILE_TEST support to GPIO_MXS driver for better compile testing coverage. Signed-off-by: Anson Huang Reported-by: kbuild test robot Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ef55c45131c5..1b96169d84f7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -400,7 +400,7 @@ config GPIO_MXC config GPIO_MXS def_bool y - depends on ARCH_MXS + depends on ARCH_MXS || COMPILE_TEST select GPIO_GENERIC select GENERIC_IRQ_CHIP From 525b0858ff2fdb78defec2d4d6d63baaa423d5fd Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 13 Mar 2020 16:42:44 +1300 Subject: [PATCH 35/59] gpio: mvebu: avoid error message for optional IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq() will generate an error message if the requested irq is not present mvebu-gpio f1010140.gpio: IRQ index 3 not found use platform_get_irq_optional() to avoid the error message being generated. Signed-off-by: Chris Packham Acked-by: Uwe Kleine-König Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mvebu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index d2b999c7987f..3c9f4fb3d5a2 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -1247,7 +1247,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) * pins. */ for (i = 0; i < 4; i++) { - int irq = platform_get_irq(pdev, i); + int irq = platform_get_irq_optional(pdev, i); if (irq < 0) continue; From d1ee7e1f5c9191afb69ce46cc7752e4257340a31 Mon Sep 17 00:00:00 2001 From: Gabriel Ravier Date: Thu, 12 Mar 2020 15:50:21 +0100 Subject: [PATCH 36/59] tools: gpio-hammer: Avoid potential overflow in main If '-o' was used more than 64 times in a single invocation of gpio-hammer, this could lead to an overflow of the 'lines' array. This commit fixes this by avoiding the overflow and giving a proper diagnostic back to the user Signed-off-by: Gabriel Ravier Signed-off-by: Bartosz Golaszewski --- tools/gpio/gpio-hammer.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c index 0e0060a6eb34..083399d276e4 100644 --- a/tools/gpio/gpio-hammer.c +++ b/tools/gpio/gpio-hammer.c @@ -135,7 +135,14 @@ int main(int argc, char **argv) device_name = optarg; break; case 'o': - lines[i] = strtoul(optarg, NULL, 10); + /* + * Avoid overflow. Do not immediately error, we want to + * be able to accurately report on the amount of times + * '-o' was given to give an accurate error message + */ + if (i < GPIOHANDLES_MAX) + lines[i] = strtoul(optarg, NULL, 10); + i++; break; case '?': @@ -143,6 +150,14 @@ int main(int argc, char **argv) return -1; } } + + if (i >= GPIOHANDLES_MAX) { + fprintf(stderr, + "Only %d occurences of '-o' are allowed, %d were found\n", + GPIOHANDLES_MAX, i + 1); + return -1; + } + nlines = i; if (!device_name || !nlines) { From d19d2de61fb131abcd29f7c61d3f168f687bfd6e Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sun, 15 Mar 2020 20:13:37 +0800 Subject: [PATCH 37/59] gpio: mmio: introduce BGPIOF_NO_SET_ON_INPUT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some gpio controllers ignores pin value writing when that pin is configured as input mode. As a result, bgpio_dir_out should set pin to output before configuring pin values or gpio pin values can't be set up properly. Introduce two variants of bgpio_dir_out: bgpio_dir_out_val_first and bgpio_dir_out_dir_first, and assign direction_output according to a new flag: BGPIOF_NO_SET_ON_INPUT. Signed-off-by: Chuanhong Guo Tested-by: René van Dorst Reviewed-by: Sergio Paracuellos Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mmio.c | 23 +++++++++++++++++++---- include/linux/gpio/driver.h | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index f729e3e9e983..b778f33cc6af 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -389,12 +389,10 @@ static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) return GPIO_LINE_DIRECTION_IN; } -static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; - gc->set(gc, gpio, val); - spin_lock_irqsave(&gc->bgpio_lock, flags); gc->bgpio_dir |= bgpio_line2mask(gc, gpio); @@ -405,7 +403,21 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} +static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + bgpio_dir_out(gc, gpio, val); + gc->set(gc, gpio, val); + return 0; +} + +static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, + int val) +{ + gc->set(gc, gpio, val); + bgpio_dir_out(gc, gpio, val); return 0; } @@ -538,7 +550,10 @@ static int bgpio_setup_direction(struct gpio_chip *gc, if (dirout || dirin) { gc->reg_dir_out = dirout; gc->reg_dir_in = dirin; - gc->direction_output = bgpio_dir_out; + if (flags & BGPIOF_NO_SET_ON_INPUT) + gc->direction_output = bgpio_dir_out_dir_first; + else + gc->direction_output = bgpio_dir_out_val_first; gc->direction_input = bgpio_dir_in; gc->get_direction = bgpio_get_dir; } else { diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6ef05bccc0a6..ed65e00ee977 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -572,6 +572,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, #define BGPIOF_BIG_ENDIAN_BYTE_ORDER BIT(3) #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ +#define BGPIOF_NO_SET_ON_INPUT BIT(6) int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq); From 427cabede05cd93a4ad79153679f6aab21dc1bfa Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sun, 15 Mar 2020 20:13:38 +0800 Subject: [PATCH 38/59] gpio: mt7621: add BGPIOF_NO_SET_ON_INPUT flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DSET/DCLR registers only works on output pins. Add corresponding BGPIOF_NO_SET_ON_INPUT flag to bgpio_init call to fix direction_out behavior. Signed-off-by: Chuanhong Guo Tested-by: René van Dorst Reviewed-by: Sergio Paracuellos Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mt7621.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index b992321bb852..82fb20dca53a 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -227,8 +227,8 @@ mediatek_gpio_bank_probe(struct device *dev, ctrl = mtk->base + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_STRIDE); diro = mtk->base + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_STRIDE); - ret = bgpio_init(&rg->chip, dev, 4, - dat, set, ctrl, diro, NULL, 0); + ret = bgpio_init(&rg->chip, dev, 4, dat, set, ctrl, diro, NULL, + BGPIOF_NO_SET_ON_INPUT); if (ret) { dev_err(dev, "bgpio_init() failed\n"); return ret; From 55f17e2ae916e4443e5f0acf067a3b6e9180f1cd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Mar 2020 09:23:40 +0000 Subject: [PATCH 39/59] tools: gpio-hammer: fix spelling mistake: "occurences" -> "occurrences" There is a spelling mistake in an error message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Bartosz Golaszewski --- tools/gpio/gpio-hammer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c index 083399d276e4..28d2329e83d2 100644 --- a/tools/gpio/gpio-hammer.c +++ b/tools/gpio/gpio-hammer.c @@ -153,7 +153,7 @@ int main(int argc, char **argv) if (i >= GPIOHANDLES_MAX) { fprintf(stderr, - "Only %d occurences of '-o' are allowed, %d were found\n", + "Only %d occurrences of '-o' are allowed, %d were found\n", GPIOHANDLES_MAX, i + 1); return -1; } From ee203bbd63c0ae75c7672f30ae09f74abfcf6f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Sun, 15 Mar 2020 17:34:34 +0100 Subject: [PATCH 40/59] gpiolib: gpio_name_to_desc: factor out !name check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since name == NULL can't ever match, move the check out of IRQ-disabled region. Signed-off-by: Michał Mirosław Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 00890f38f95f..c7ee224bcb86 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -301,6 +301,9 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name) struct gpio_device *gdev; unsigned long flags; + if (!name) + return NULL; + spin_lock_irqsave(&gpio_lock, flags); list_for_each_entry(gdev, &gpio_devices, list) { @@ -309,7 +312,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name) for (i = 0; i != gdev->ngpio; ++i) { struct gpio_desc *desc = &gdev->descs[i]; - if (!desc->name || !name) + if (!desc->name) continue; if (!strcmp(desc->name, name)) { From 1003bc16481a46fe5cecf99dcd3edbf48648d2a0 Mon Sep 17 00:00:00 2001 From: Gabriel Ravier Date: Mon, 16 Mar 2020 20:50:48 +0100 Subject: [PATCH 41/59] tools: gpio-hammer: Apply scripts/Lindent and retain good changes "retain good changes" means that I left the help string split up instead of having this weird thing where it tries to merge together the last three lines and it looks **really** bad Signed-off-by: Gabriel Ravier Signed-off-by: Bartosz Golaszewski --- tools/gpio/gpio-hammer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c index 28d2329e83d2..9fd926e8cb52 100644 --- a/tools/gpio/gpio-hammer.c +++ b/tools/gpio/gpio-hammer.c @@ -77,7 +77,7 @@ int hammer_device(const char *device_name, unsigned int *lines, int nlines, fprintf(stdout, "[%c] ", swirr[j]); j++; - if (j == sizeof(swirr)-1) + if (j == sizeof(swirr) - 1) j = 0; fprintf(stdout, "["); From 97551625025320e9d635531625316e43c8ed62b0 Mon Sep 17 00:00:00 2001 From: Mykyta Poturai Date: Sun, 22 Mar 2020 12:10:17 +0200 Subject: [PATCH 42/59] tools: gpio: Fix typo in gpio-utils Replace COMSUMER with proper CONSUMER Signed-off-by: Mykyta Poturai Signed-off-by: Bartosz Golaszewski --- tools/gpio/gpio-utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c index 53470de6a502..06003789e7c7 100644 --- a/tools/gpio/gpio-utils.c +++ b/tools/gpio/gpio-utils.c @@ -17,7 +17,7 @@ #include #include "gpio-utils.h" -#define COMSUMER "gpio-utils" +#define CONSUMER "gpio-utils" /** * doc: Operation of gpio @@ -209,7 +209,7 @@ int gpiotools_gets(const char *device_name, unsigned int *lines, ret = gpiotools_request_linehandle(device_name, lines, nlines, GPIOHANDLE_REQUEST_INPUT, data, - COMSUMER); + CONSUMER); if (ret < 0) return ret; @@ -259,7 +259,7 @@ int gpiotools_sets(const char *device_name, unsigned int *lines, ret = gpiotools_request_linehandle(device_name, lines, nlines, GPIOHANDLE_REQUEST_OUTPUT, data, - COMSUMER); + CONSUMER); if (ret < 0) return ret; From 5eefcaed501dd9e3933dbff58720244bd75ed90f Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Mon, 9 Mar 2020 12:02:01 -0700 Subject: [PATCH 43/59] gpio: brcmstb: support gpio-line-names property The default handling of the gpio-line-names property by the gpiolib-of implementation does not work with the multiple gpiochip banks per device structure used by the gpio-brcmstb driver. This commit adds driver level support for the device tree property so that GPIO lines can be assigned friendly names. Signed-off-by: Doug Berger Link: https://lore.kernel.org/r/1583780521-45702-1-git-send-email-opendmb@gmail.com Acked-by: Gregory Fong Acked-by: Florian Fainelli Signed-off-by: Linus Walleij --- drivers/gpio/gpio-brcmstb.c | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 05e3f99ae59c..fcfc1a1f1a5c 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -603,6 +603,49 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = { .resume_noirq = brcmstb_gpio_resume, }; +static void brcmstb_gpio_set_names(struct device *dev, + struct brcmstb_gpio_bank *bank) +{ + struct device_node *np = dev->of_node; + const char **names; + int nstrings, base; + unsigned int i; + + base = bank->id * MAX_GPIO_PER_BANK; + + nstrings = of_property_count_strings(np, "gpio-line-names"); + if (nstrings <= base) + /* Line names not present */ + return; + + names = devm_kcalloc(dev, MAX_GPIO_PER_BANK, sizeof(*names), + GFP_KERNEL); + if (!names) + return; + + /* + * Make sure to not index beyond the end of the number of descriptors + * of the GPIO device. + */ + for (i = 0; i < bank->width; i++) { + const char *name; + int ret; + + ret = of_property_read_string_index(np, "gpio-line-names", + base + i, &name); + if (ret) { + if (ret != -ENODATA) + dev_err(dev, "unable to name line %d: %d\n", + base + i, ret); + break; + } + if (*name) + names[i] = name; + } + + bank->gc.names = names; +} + static int brcmstb_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -726,6 +769,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank); gc->write_reg(reg_base + GIO_MASK(bank->id), 0); + brcmstb_gpio_set_names(dev, bank); err = gpiochip_add_data(gc, bank); if (err) { dev_err(dev, "Could not add gpiochip for bank %d\n", From da3f594737cfa24c44769ff17ce2643f85eb0ef5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Mar 2020 14:56:46 +0100 Subject: [PATCH 44/59] ARM: integrator: impd1: Use GPIO_LOOKUP() helper macro impd1_probe() fills in the GPIO lookup table by manually populating an array of gpiod_lookup structures. Use the existing GPIO_LOOKUP() helper macro instead, to relax a dependency on the gpiod_lookup structure's member names. Signed-off-by: Geert Uytterhoeven Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20200324135653.6676-1-geert+renesas@glider.be Signed-off-by: Linus Walleij --- arch/arm/mach-integrator/impd1.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 1ecbea5331d6..6f875ded8419 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -410,13 +410,10 @@ static int __ref impd1_probe(struct lm_device *dev) * 5 = Key lower right */ /* We need the two MMCI GPIO entries */ - lookup->table[0].chip_label = chipname; - lookup->table[0].chip_hwnum = 3; - lookup->table[0].con_id = "wp"; - lookup->table[1].chip_label = chipname; - lookup->table[1].chip_hwnum = 4; - lookup->table[1].con_id = "cd"; - lookup->table[1].flags = GPIO_ACTIVE_LOW; + lookup->table[0] = (struct gpiod_lookup) + GPIO_LOOKUP(chipname, 3, "wp", 0); + lookup->table[1] = (struct gpiod_lookup) + GPIO_LOOKUP(chipname, 4, "cd", GPIO_ACTIVE_LOW); gpiod_add_lookup_table(lookup); } From 2ab73c6d8323fa1eb02c16c07c40ba2ed17da729 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 19 Mar 2020 13:27:29 +0100 Subject: [PATCH 45/59] gpio: Support GPIO controllers without pin-ranges Wake gpiochip_generic_request() call into the pinctrl helpers only if a GPIO controller had any pin-ranges assigned to it. This allows a driver to unconditionally use this helper if it supports multiple devices of which only a subset have pin-ranges assigned to them. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200319122737.3063291-2-thierry.reding@gmail.com Tested-by: Vidya Sagar Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c7ee224bcb86..4a36164843d9 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2745,7 +2745,10 @@ static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) */ int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset) { - return pinctrl_gpio_request(chip->gpiodev->base + offset); + if (!list_empty(&chip->gpiodev->pin_ranges)) + return pinctrl_gpio_request(chip->gpiodev->base + offset); + + return 0; } EXPORT_SYMBOL_GPL(gpiochip_generic_request); From b64d6c9a6a050d9a15c9e044db9ebc874aed6072 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 19 Mar 2020 13:27:30 +0100 Subject: [PATCH 46/59] gpio: tegra186: Add support for pin ranges Add support for Tegra SoC generations to specify a list of pin ranges that map GPIOs to ranges of pins in the pin controller. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200319122737.3063291-3-thierry.reding@gmail.com Tested-by: Vidya Sagar Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra186.c | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index de241263d4be..1086c1fcaf49 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -58,11 +58,20 @@ struct tegra_gpio_port { unsigned int pins; }; +struct tegra186_pin_range { + unsigned int offset; + const char *group; +}; + struct tegra_gpio_soc { const struct tegra_gpio_port *ports; unsigned int num_ports; const char *name; unsigned int instance; + + const struct tegra186_pin_range *pin_ranges; + unsigned int num_pin_ranges; + const char *pinmux; }; struct tegra_gpio { @@ -254,6 +263,50 @@ static int tegra186_gpio_set_config(struct gpio_chip *chip, return 0; } +static int tegra186_gpio_add_pin_ranges(struct gpio_chip *chip) +{ + struct tegra_gpio *gpio = gpiochip_get_data(chip); + struct pinctrl_dev *pctldev; + struct device_node *np; + unsigned int i, j; + int err; + + if (!gpio->soc->pinmux || gpio->soc->num_pin_ranges == 0) + return 0; + + np = of_find_compatible_node(NULL, NULL, gpio->soc->pinmux); + if (!np) + return -ENODEV; + + pctldev = of_pinctrl_get(np); + of_node_put(np); + if (!pctldev) + return -EPROBE_DEFER; + + for (i = 0; i < gpio->soc->num_pin_ranges; i++) { + unsigned int pin = gpio->soc->pin_ranges[i].offset, port; + const char *group = gpio->soc->pin_ranges[i].group; + + port = pin / 8; + pin = pin % 8; + + if (port >= gpio->soc->num_ports) { + dev_warn(chip->parent, "invalid port %u for %s\n", + port, group); + continue; + } + + for (j = 0; j < port; j++) + pin += gpio->soc->ports[j].pins; + + err = gpiochip_add_pingroup_range(chip, pctldev, pin, group); + if (err < 0) + return err; + } + + return 0; +} + static int tegra186_gpio_of_xlate(struct gpio_chip *chip, const struct of_phandle_args *spec, u32 *flags) @@ -578,12 +631,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->gpio.label = gpio->soc->name; gpio->gpio.parent = &pdev->dev; + gpio->gpio.request = gpiochip_generic_request; + gpio->gpio.free = gpiochip_generic_free; gpio->gpio.get_direction = tegra186_gpio_get_direction; gpio->gpio.direction_input = tegra186_gpio_direction_input; gpio->gpio.direction_output = tegra186_gpio_direction_output; gpio->gpio.get = tegra186_gpio_get, gpio->gpio.set = tegra186_gpio_set; gpio->gpio.set_config = tegra186_gpio_set_config; + gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; gpio->gpio.base = -1; From ffa91e7ca1426a89eec1b3101286d82785760767 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 19 Mar 2020 13:27:31 +0100 Subject: [PATCH 47/59] gpio: tegra186: Add Tegra194 pin ranges for GG.0 and GG.1 The GG.0 and GG.1 GPIOs serve as CLKREQ and RST pins, respectively, for PCIe controller 5 on Tegra194. When this controller is configured in endpoint mode, these pins need to be used as GPIOs by the PCIe endpoint driver. Typically the mode programming of these pins (GPIO vs. SFIO) is performed by early boot firmware to ensure that the configuration is consistent. However, the GG.0 and GG.1 pins are part of a special power partition that is not enabled during early boot, and hence the early boot firmware cannot program these pins to be GPIOs (they are SFIO by default). Adding them as pin ranges for the pin controller allows the pin controller to be involved when these pins are requested as GPIOs and allows the proper programming to take place. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200319122737.3063291-4-thierry.reding@gmail.com Tested-by: Vidya Sagar Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra186.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 1086c1fcaf49..79b553dc39a3 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -839,11 +839,19 @@ static const struct tegra_gpio_port tegra194_main_ports[] = { TEGRA194_MAIN_GPIO_PORT(GG, 0, 0, 2) }; +static const struct tegra186_pin_range tegra194_main_pin_ranges[] = { + { TEGRA194_MAIN_GPIO(GG, 0), "pex_l5_clkreq_n_pgg0" }, + { TEGRA194_MAIN_GPIO(GG, 1), "pex_l5_rst_n_pgg1" }, +}; + static const struct tegra_gpio_soc tegra194_main_soc = { .num_ports = ARRAY_SIZE(tegra194_main_ports), .ports = tegra194_main_ports, .name = "tegra194-gpio", .instance = 0, + .num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges), + .pin_ranges = tegra194_main_pin_ranges, + .pinmux = "nvidia,tegra194-pinmux", }; #define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \ From 35c6cfb4340c199974f06a36670f7d1e9d32e1c7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 17 Mar 2020 15:54:21 +0100 Subject: [PATCH 48/59] gpio: gpiolib: fix a doc warning Use a different markup for the ERR_PTR, as %FOO doesn't work if there are parenthesis. So, use, instead: ``ERR_PTR(-EINVAL)`` This fixes the following warning: ./drivers/gpio/gpiolib.c:139: WARNING: Inline literal start-string without end-string. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/51197e3568f073e22c280f0584bfa20b44436708.1584456635.git.mchehab+huawei@kernel.org Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4a36164843d9..44f2a449729f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -136,7 +136,7 @@ EXPORT_SYMBOL_GPL(gpio_to_desc); * @hwnum: hardware number of the GPIO for this chip * * Returns: - * A pointer to the GPIO descriptor or %ERR_PTR(-EINVAL) if no GPIO exists + * A pointer to the GPIO descriptor or ``ERR_PTR(-EINVAL)`` if no GPIO exists * in the given chip for the specified hardware number. */ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, From 82f04bfe2aff428b063eefd234679b2d693228ed Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Wed, 25 Mar 2020 12:31:54 +0200 Subject: [PATCH 49/59] tools: gpio: Fix out-of-tree build regression Commit 0161a94e2d1c7 ("tools: gpio: Correctly add make dependencies for gpio_utils") added a make rule for gpio-utils-in.o but used $(output) instead of the correct $(OUTPUT) for the output directory, breaking out-of-tree build (O=xx) with the following error: No rule to make target 'out/tools/gpio/gpio-utils-in.o', needed by 'out/tools/gpio/lsgpio-in.o'. Stop. Fix that. Fixes: 0161a94e2d1c ("tools: gpio: Correctly add make dependencies for gpio_utils") Cc: Cc: Laura Abbott Signed-off-by: Anssi Hannula Link: https://lore.kernel.org/r/20200325103154.32235-1-anssi.hannula@bitwise.fi Reviewed-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- tools/gpio/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index 842287e42c83..440434027557 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -35,7 +35,7 @@ $(OUTPUT)include/linux/gpio.h: ../../include/uapi/linux/gpio.h prepare: $(OUTPUT)include/linux/gpio.h -GPIO_UTILS_IN := $(output)gpio-utils-in.o +GPIO_UTILS_IN := $(OUTPUT)gpio-utils-in.o $(GPIO_UTILS_IN): prepare FORCE $(Q)$(MAKE) $(build)=gpio-utils From 8ced32ffadc857eaa45d62c0c5a34cf6f37168ea Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 24 Mar 2020 14:56:50 +0100 Subject: [PATCH 50/59] gpiolib: Introduce gpiod_set_config() The GPIO Aggregator will need a method to forward a .set_config() call to its parent gpiochip. This requires obtaining the gpio_chip and offset for a given gpio_desc. While gpiod_to_chip() is public, gpio_chip_hwgpio() is not, so there is currently no method to obtain the needed GPIO offset parameter. Hence introduce a public gpiod_set_config() helper, which invokes the .set_config() callback through a gpio_desc pointer, like is done for most other gpio_chip callbacks. Rewrite the existing gpiod_set_debounce() helper as a wrapper around gpiod_set_config(), to avoid duplication. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200324135653.6676-5-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 28 ++++++++++++++++++++++------ include/linux/gpio/consumer.h | 8 ++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e3616cc85d66..6c3e4eb53771 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3431,6 +3431,26 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) } EXPORT_SYMBOL_GPL(gpiod_direction_output); +/** + * gpiod_set_config - sets @config for a GPIO + * @desc: descriptor of the GPIO for which to set the configuration + * @config: Same packed config format as generic pinconf + * + * Returns: + * 0 on success, %-ENOTSUPP if the controller doesn't support setting the + * configuration. + */ +int gpiod_set_config(struct gpio_desc *desc, unsigned long config) +{ + struct gpio_chip *chip; + + VALIDATE_DESC(desc); + chip = desc->gdev->chip; + + return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config); +} +EXPORT_SYMBOL_GPL(gpiod_set_config); + /** * gpiod_set_debounce - sets @debounce time for a GPIO * @desc: descriptor of the GPIO for which to set debounce time @@ -3442,14 +3462,10 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output); */ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) { - struct gpio_chip *chip; - unsigned long config; - - VALIDATE_DESC(desc); - chip = desc->gdev->chip; + unsigned long config; config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce); - return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config); + return gpiod_set_config(desc, config); } EXPORT_SYMBOL_GPL(gpiod_set_debounce); diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 0a72fccf60ff..901aab89d025 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -157,6 +157,7 @@ int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_array *array_info, unsigned long *value_bitmap); +int gpiod_set_config(struct gpio_desc *desc, unsigned long config); int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); int gpiod_set_transitory(struct gpio_desc *desc, bool transitory); void gpiod_toggle_active_low(struct gpio_desc *desc); @@ -473,6 +474,13 @@ static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size, return 0; } +static inline int gpiod_set_config(struct gpio_desc *desc, unsigned long config) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); + return -ENOSYS; +} + static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) { /* GPIO can never have been requested */ From 83522358438dd9de8567991f7366db510b3eb433 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 Mar 2020 11:04:38 +0100 Subject: [PATCH 51/59] gpiolib: Pass gpio_desc to gpio_set_config() All callers of gpio_set_config() have to convert a gpio_desc to a gpio_chip and offset. Avoid these duplicated conversion steps by letting gpio_set_config() take a gpio_desc pointer directly. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200325100439.14000-2-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6c3e4eb53771..0541c9ff22b3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3196,9 +3196,9 @@ static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset, return gc->set_config(gc, offset, config); } -static int gpio_set_config(struct gpio_chip *gc, unsigned int offset, - enum pin_config_param mode) +static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode) { + struct gpio_chip *chip = desc->gdev->chip; unsigned long config; unsigned arg; @@ -3213,7 +3213,7 @@ static int gpio_set_config(struct gpio_chip *gc, unsigned int offset, } config = PIN_CONF_PACKED(mode, arg); - return gpio_do_set_config(gc, offset, config); + return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config); } static int gpio_set_bias(struct gpio_chip *chip, struct gpio_desc *desc) @@ -3229,7 +3229,7 @@ static int gpio_set_bias(struct gpio_chip *chip, struct gpio_desc *desc) bias = PIN_CONFIG_BIAS_PULL_DOWN; if (bias) { - ret = gpio_set_config(chip, gpio_chip_hwgpio(desc), bias); + ret = gpio_set_config(desc, bias); if (ret != -ENOTSUPP) return ret; } @@ -3387,8 +3387,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) gc = desc->gdev->chip; if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { /* First see if we can enable open drain in hardware */ - ret = gpio_set_config(gc, gpio_chip_hwgpio(desc), - PIN_CONFIG_DRIVE_OPEN_DRAIN); + ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_DRAIN); if (!ret) goto set_output_value; /* Emulate open drain by not actively driving the line high */ @@ -3398,8 +3397,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) } } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { - ret = gpio_set_config(gc, gpio_chip_hwgpio(desc), - PIN_CONFIG_DRIVE_OPEN_SOURCE); + ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_SOURCE); if (!ret) goto set_output_value; /* Emulate open source by not actively driving the line low */ @@ -3408,8 +3406,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) goto set_output_flag; } } else { - gpio_set_config(gc, gpio_chip_hwgpio(desc), - PIN_CONFIG_DRIVE_PUSH_PULL); + gpio_set_config(desc, PIN_CONFIG_DRIVE_PUSH_PULL); } set_output_value: From 5f4bf171ca03b79f0ed7a17216fd854e50955617 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 25 Mar 2020 11:04:39 +0100 Subject: [PATCH 52/59] gpiolib: Remove unused gpio_chip parameter from gpio_set_bias() gpio_set_bias() no longer uses the passed gpio_chip pointer parameter. Remove it. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20200325100439.14000-3-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0541c9ff22b3..8acb0c96fa4c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3216,7 +3216,7 @@ static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode) return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config); } -static int gpio_set_bias(struct gpio_chip *chip, struct gpio_desc *desc) +static int gpio_set_bias(struct gpio_desc *desc) { int bias = 0; int ret = 0; @@ -3282,7 +3282,7 @@ int gpiod_direction_input(struct gpio_desc *desc) } if (ret == 0) { clear_bit(FLAG_IS_OUT, &desc->flags); - ret = gpio_set_bias(chip, desc); + ret = gpio_set_bias(desc); } trace_gpio_direction(desc_to_gpio(desc), 1, ret); @@ -3366,7 +3366,6 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output_raw); */ int gpiod_direction_output(struct gpio_desc *desc, int value) { - struct gpio_chip *gc; int ret; VALIDATE_DESC(desc); @@ -3384,7 +3383,6 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) return -EIO; } - gc = desc->gdev->chip; if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) { /* First see if we can enable open drain in hardware */ ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_DRAIN); @@ -3410,7 +3408,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) } set_output_value: - ret = gpio_set_bias(gc, desc); + ret = gpio_set_bias(desc); if (ret) return ret; return gpiod_direction_output_raw_commit(desc, value); From 89ad556b7f96af54ae6762f561f0a09269265741 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Mar 2020 11:02:57 +0200 Subject: [PATCH 53/59] gpio: Avoid using pin ranges with !PINCTRL Do not use the struct gpio_device's .pin_ranges field if the PINCTRL Kconfig symbol is not selected to avoid build failures. Fixes: 2ab73c6d8323fa1e ("gpio: Support GPIO controllers without pin-ranges") Reported-by: Stephen Rothwell Reported-by: kbuild test robot Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200330090257.2332864-1-thierry.reding@gmail.com Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8acb0c96fa4c..2951a8b595c3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2745,10 +2745,12 @@ static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) */ int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset) { - if (!list_empty(&chip->gpiodev->pin_ranges)) - return pinctrl_gpio_request(chip->gpiodev->base + offset); +#ifdef CONFIG_PINCTRL + if (list_empty(&chip->gpiodev->pin_ranges)) + return 0; +#endif - return 0; + return pinctrl_gpio_request(chip->gpiodev->base + offset); } EXPORT_SYMBOL_GPL(gpiochip_generic_request); From a0b66a73785ccc8fedbff00383ffe814df9f63c7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 29 Mar 2020 16:04:05 +0200 Subject: [PATCH 54/59] gpio: Rename variable in core APIs There is struct gpio *gc, *chip and *gpiochip, and yes I am responsible for some of the inconsistencies. I want this to be just gc everywhere for minimizing cognitive resistance when reading the code: more compact function signatures and less clutter. Purely syntactic changes intended. No semantic effects. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20200329140405.52276-1-linus.walleij@linaro.org Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 825 ++++++++++++++++++------------------ include/linux/gpio/driver.h | 138 +++--- 2 files changed, 482 insertions(+), 481 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2951a8b595c3..c2cc437ce831 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -81,14 +81,14 @@ LIST_HEAD(gpio_devices); static DEFINE_MUTEX(gpio_machine_hogs_mutex); static LIST_HEAD(gpio_machine_hogs); -static void gpiochip_free_hogs(struct gpio_chip *chip); -static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, +static void gpiochip_free_hogs(struct gpio_chip *gc); +static int gpiochip_add_irqchip(struct gpio_chip *gc, struct lock_class_key *lock_key, struct lock_class_key *request_key); -static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); -static int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip); -static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip); -static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip); +static void gpiochip_irqchip_remove(struct gpio_chip *gc); +static int gpiochip_irqchip_init_hw(struct gpio_chip *gc); +static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc); +static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc); static bool gpiolib_initialized; @@ -132,17 +132,17 @@ EXPORT_SYMBOL_GPL(gpio_to_desc); /** * gpiochip_get_desc - get the GPIO descriptor corresponding to the given * hardware number for this chip - * @chip: GPIO chip + * @gc: GPIO chip * @hwnum: hardware number of the GPIO for this chip * * Returns: * A pointer to the GPIO descriptor or ``ERR_PTR(-EINVAL)`` if no GPIO exists * in the given chip for the specified hardware number. */ -struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc, unsigned int hwnum) { - struct gpio_device *gdev = chip->gpiodev; + struct gpio_device *gdev = gc->gpiodev; if (hwnum >= gdev->ngpio) return ERR_PTR(-EINVAL); @@ -213,11 +213,11 @@ static int gpiochip_find_base(int ngpio) */ int gpiod_get_direction(struct gpio_desc *desc) { - struct gpio_chip *chip; + struct gpio_chip *gc; unsigned offset; int ret; - chip = gpiod_to_chip(desc); + gc = gpiod_to_chip(desc); offset = gpio_chip_hwgpio(desc); /* @@ -228,10 +228,10 @@ int gpiod_get_direction(struct gpio_desc *desc) test_bit(FLAG_IS_OUT, &desc->flags)) return 0; - if (!chip->get_direction) + if (!gc->get_direction) return -ENOTSUPP; - ret = chip->get_direction(chip, offset); + ret = gc->get_direction(gc, offset); if (ret < 0) return ret; @@ -359,16 +359,16 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) return 0; } -static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) +static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc) { unsigned long *p; - p = bitmap_alloc(chip->ngpio, GFP_KERNEL); + p = bitmap_alloc(gc->ngpio, GFP_KERNEL); if (!p) return NULL; /* Assume by default all GPIOs are valid */ - bitmap_fill(p, chip->ngpio); + bitmap_fill(p, gc->ngpio); return p; } @@ -395,10 +395,10 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gc) return 0; } -static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip) +static void gpiochip_free_valid_mask(struct gpio_chip *gc) { - bitmap_free(gpiochip->valid_mask); - gpiochip->valid_mask = NULL; + bitmap_free(gc->valid_mask); + gc->valid_mask = NULL; } static int gpiochip_add_pin_ranges(struct gpio_chip *gc) @@ -409,13 +409,13 @@ static int gpiochip_add_pin_ranges(struct gpio_chip *gc) return 0; } -bool gpiochip_line_is_valid(const struct gpio_chip *gpiochip, +bool gpiochip_line_is_valid(const struct gpio_chip *gc, unsigned int offset) { /* No mask means all valid */ - if (likely(!gpiochip->valid_mask)) + if (likely(!gc->valid_mask)) return true; - return test_bit(offset, gpiochip->valid_mask); + return test_bit(offset, gc->valid_mask); } EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); @@ -1156,7 +1156,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) static void gpio_desc_to_lineinfo(struct gpio_desc *desc, struct gpioline_info *info) { - struct gpio_chip *chip = desc->gdev->chip; + struct gpio_chip *gc = desc->gdev->chip; unsigned long flags; spin_lock_irqsave(&gpio_lock, flags); @@ -1185,7 +1185,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, test_bit(FLAG_USED_AS_IRQ, &desc->flags) || test_bit(FLAG_EXPORT, &desc->flags) || test_bit(FLAG_SYSFS, &desc->flags) || - !pinctrl_gpio_can_use_line(chip->base + info->line_offset)) + !pinctrl_gpio_can_use_line(gc->base + info->line_offset)) info->flags |= GPIOLINE_FLAG_KERNEL; if (test_bit(FLAG_IS_OUT, &desc->flags)) info->flags |= GPIOLINE_FLAG_IS_OUT; @@ -1222,13 +1222,13 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct gpio_chardev_data *priv = filp->private_data; struct gpio_device *gdev = priv->gdev; - struct gpio_chip *chip = gdev->chip; + struct gpio_chip *gc = gdev->chip; void __user *ip = (void __user *)arg; struct gpio_desc *desc; __u32 offset; /* We fail any subsequent ioctl():s when the chip is gone */ - if (!chip) + if (!gc) return -ENODEV; /* Fill in the struct and pass to userspace */ @@ -1254,7 +1254,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) return -EFAULT; - desc = gpiochip_get_desc(chip, lineinfo.line_offset); + desc = gpiochip_get_desc(gc, lineinfo.line_offset); if (IS_ERR(desc)) return PTR_ERR(desc); @@ -1275,7 +1275,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (copy_from_user(&offset, ip, sizeof(offset))) return -EFAULT; - desc = gpiochip_get_desc(chip, offset); + desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return PTR_ERR(desc); @@ -1518,12 +1518,12 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) return ret; } -static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog) +static void gpiochip_machine_hog(struct gpio_chip *gc, struct gpiod_hog *hog) { struct gpio_desc *desc; int rv; - desc = gpiochip_get_desc(chip, hog->chip_hwnum); + desc = gpiochip_get_desc(gc, hog->chip_hwnum); if (IS_ERR(desc)) { pr_err("%s: unable to get GPIO desc: %ld\n", __func__, PTR_ERR(desc)); @@ -1536,18 +1536,18 @@ static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog) rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags); if (rv) pr_err("%s: unable to hog GPIO line (%s:%u): %d\n", - __func__, chip->label, hog->chip_hwnum, rv); + __func__, gc->label, hog->chip_hwnum, rv); } -static void machine_gpiochip_add(struct gpio_chip *chip) +static void machine_gpiochip_add(struct gpio_chip *gc) { struct gpiod_hog *hog; mutex_lock(&gpio_machine_hogs_mutex); list_for_each_entry(hog, &gpio_machine_hogs, list) { - if (!strcmp(chip->label, hog->chip_label)) - gpiochip_machine_hog(chip, hog); + if (!strcmp(gc->label, hog->chip_label)) + gpiochip_machine_hog(gc, hog); } mutex_unlock(&gpio_machine_hogs_mutex); @@ -1566,14 +1566,14 @@ static void gpiochip_setup_devs(void) } } -int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, +int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, struct lock_class_key *lock_key, struct lock_class_key *request_key) { unsigned long flags; int ret = 0; unsigned i; - int base = chip->base; + int base = gc->base; struct gpio_device *gdev; /* @@ -1584,19 +1584,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (!gdev) return -ENOMEM; gdev->dev.bus = &gpio_bus_type; - gdev->chip = chip; - chip->gpiodev = gdev; - if (chip->parent) { - gdev->dev.parent = chip->parent; - gdev->dev.of_node = chip->parent->of_node; + gdev->chip = gc; + gc->gpiodev = gdev; + if (gc->parent) { + gdev->dev.parent = gc->parent; + gdev->dev.of_node = gc->parent->of_node; } #ifdef CONFIG_OF_GPIO /* If the gpiochip has an assigned OF node this takes precedence */ - if (chip->of_node) - gdev->dev.of_node = chip->of_node; + if (gc->of_node) + gdev->dev.of_node = gc->of_node; else - chip->of_node = gdev->dev.of_node; + gc->of_node = gdev->dev.of_node; #endif gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); @@ -1607,37 +1607,37 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id); device_initialize(&gdev->dev); dev_set_drvdata(&gdev->dev, gdev); - if (chip->parent && chip->parent->driver) - gdev->owner = chip->parent->driver->owner; - else if (chip->owner) + if (gc->parent && gc->parent->driver) + gdev->owner = gc->parent->driver->owner; + else if (gc->owner) /* TODO: remove chip->owner */ - gdev->owner = chip->owner; + gdev->owner = gc->owner; else gdev->owner = THIS_MODULE; - gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL); + gdev->descs = kcalloc(gc->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL); if (!gdev->descs) { ret = -ENOMEM; goto err_free_ida; } - if (chip->ngpio == 0) { - chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); + if (gc->ngpio == 0) { + chip_err(gc, "tried to insert a GPIO chip with zero lines\n"); ret = -EINVAL; goto err_free_descs; } - if (chip->ngpio > FASTPATH_NGPIO) - chip_warn(chip, "line cnt %u is greater than fast path cnt %u\n", - chip->ngpio, FASTPATH_NGPIO); + if (gc->ngpio > FASTPATH_NGPIO) + chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", + gc->ngpio, FASTPATH_NGPIO); - gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL); + gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL); if (!gdev->label) { ret = -ENOMEM; goto err_free_descs; } - gdev->ngpio = chip->ngpio; + gdev->ngpio = gc->ngpio; gdev->data = data; spin_lock_irqsave(&gpio_lock, flags); @@ -1650,7 +1650,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, * of the sysfs interface anyways. */ if (base < 0) { - base = gpiochip_find_base(chip->ngpio); + base = gpiochip_find_base(gc->ngpio); if (base < 0) { ret = base; spin_unlock_irqrestore(&gpio_lock, flags); @@ -1662,7 +1662,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, * see if anyone makes use of this, else drop this and assign * a poison instead. */ - chip->base = base; + gc->base = base; } gdev->base = base; @@ -1672,7 +1672,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, goto err_free_label; } - for (i = 0; i < chip->ngpio; i++) + for (i = 0; i < gc->ngpio; i++) gdev->descs[i].gdev = gdev; spin_unlock_irqrestore(&gpio_lock, flags); @@ -1683,51 +1683,51 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, INIT_LIST_HEAD(&gdev->pin_ranges); #endif - ret = gpiochip_set_desc_names(chip); + ret = gpiochip_set_desc_names(gc); if (ret) goto err_remove_from_list; - ret = gpiochip_alloc_valid_mask(chip); + ret = gpiochip_alloc_valid_mask(gc); if (ret) goto err_remove_from_list; - ret = of_gpiochip_add(chip); + ret = of_gpiochip_add(gc); if (ret) goto err_free_gpiochip_mask; - ret = gpiochip_init_valid_mask(chip); + ret = gpiochip_init_valid_mask(gc); if (ret) goto err_remove_of_chip; - for (i = 0; i < chip->ngpio; i++) { + for (i = 0; i < gc->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; - if (chip->get_direction && gpiochip_line_is_valid(chip, i)) { + if (gc->get_direction && gpiochip_line_is_valid(gc, i)) { assign_bit(FLAG_IS_OUT, - &desc->flags, !chip->get_direction(chip, i)); + &desc->flags, !gc->get_direction(gc, i)); } else { assign_bit(FLAG_IS_OUT, - &desc->flags, !chip->direction_input); + &desc->flags, !gc->direction_input); } } - ret = gpiochip_add_pin_ranges(chip); + ret = gpiochip_add_pin_ranges(gc); if (ret) goto err_remove_of_chip; - acpi_gpiochip_add(chip); + acpi_gpiochip_add(gc); - machine_gpiochip_add(chip); + machine_gpiochip_add(gc); - ret = gpiochip_irqchip_init_valid_mask(chip); + ret = gpiochip_irqchip_init_valid_mask(gc); if (ret) goto err_remove_acpi_chip; - ret = gpiochip_irqchip_init_hw(chip); + ret = gpiochip_irqchip_init_hw(gc); if (ret) goto err_remove_acpi_chip; - ret = gpiochip_add_irqchip(chip, lock_key, request_key); + ret = gpiochip_add_irqchip(gc, lock_key, request_key); if (ret) goto err_remove_irqchip_mask; @@ -1747,17 +1747,17 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, return 0; err_remove_irqchip: - gpiochip_irqchip_remove(chip); + gpiochip_irqchip_remove(gc); err_remove_irqchip_mask: - gpiochip_irqchip_free_valid_mask(chip); + gpiochip_irqchip_free_valid_mask(gc); err_remove_acpi_chip: - acpi_gpiochip_remove(chip); + acpi_gpiochip_remove(gc); err_remove_of_chip: - gpiochip_free_hogs(chip); - of_gpiochip_remove(chip); + gpiochip_free_hogs(gc); + of_gpiochip_remove(gc); err_free_gpiochip_mask: - gpiochip_remove_pin_ranges(chip); - gpiochip_free_valid_mask(chip); + gpiochip_remove_pin_ranges(gc); + gpiochip_free_valid_mask(gc); err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); list_del(&gdev->list); @@ -1772,7 +1772,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, /* failures here can mean systems won't boot... */ pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, gdev->base, gdev->base + gdev->ngpio - 1, - chip->label ? : "generic", ret); + gc->label ? : "generic", ret); kfree(gdev); return ret; } @@ -1780,39 +1780,39 @@ EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key); /** * gpiochip_get_data() - get per-subdriver data for the chip - * @chip: GPIO chip + * @gc: GPIO chip * * Returns: * The per-subdriver data for the chip. */ -void *gpiochip_get_data(struct gpio_chip *chip) +void *gpiochip_get_data(struct gpio_chip *gc) { - return chip->gpiodev->data; + return gc->gpiodev->data; } EXPORT_SYMBOL_GPL(gpiochip_get_data); /** * gpiochip_remove() - unregister a gpio_chip - * @chip: the chip to unregister + * @gc: the chip to unregister * * A gpio_chip with any GPIOs still requested may not be removed. */ -void gpiochip_remove(struct gpio_chip *chip) +void gpiochip_remove(struct gpio_chip *gc) { - struct gpio_device *gdev = chip->gpiodev; + struct gpio_device *gdev = gc->gpiodev; unsigned long flags; unsigned int i; /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ gpiochip_sysfs_unregister(gdev); - gpiochip_free_hogs(chip); + gpiochip_free_hogs(gc); /* Numb the device, cancelling all outstanding operations */ gdev->chip = NULL; - gpiochip_irqchip_remove(chip); - acpi_gpiochip_remove(chip); - of_gpiochip_remove(chip); - gpiochip_remove_pin_ranges(chip); - gpiochip_free_valid_mask(chip); + gpiochip_irqchip_remove(gc); + acpi_gpiochip_remove(gc); + of_gpiochip_remove(gc); + gpiochip_remove_pin_ranges(gc); + gpiochip_free_valid_mask(gc); /* * We accept no more calls into the driver from this point, so * NULL the driver data pointer @@ -1821,7 +1821,7 @@ void gpiochip_remove(struct gpio_chip *chip) spin_lock_irqsave(&gpio_lock, flags); for (i = 0; i < gdev->ngpio; i++) { - if (gpiochip_is_requested(chip, i)) + if (gpiochip_is_requested(gc, i)) break; } spin_unlock_irqrestore(&gpio_lock, flags); @@ -1853,31 +1853,31 @@ EXPORT_SYMBOL_GPL(gpiochip_remove); * more gpio_chips. */ struct gpio_chip *gpiochip_find(void *data, - int (*match)(struct gpio_chip *chip, + int (*match)(struct gpio_chip *gc, void *data)) { struct gpio_device *gdev; - struct gpio_chip *chip = NULL; + struct gpio_chip *gc = NULL; unsigned long flags; spin_lock_irqsave(&gpio_lock, flags); list_for_each_entry(gdev, &gpio_devices, list) if (gdev->chip && match(gdev->chip, data)) { - chip = gdev->chip; + gc = gdev->chip; break; } spin_unlock_irqrestore(&gpio_lock, flags); - return chip; + return gc; } EXPORT_SYMBOL_GPL(gpiochip_find); -static int gpiochip_match_name(struct gpio_chip *chip, void *data) +static int gpiochip_match_name(struct gpio_chip *gc, void *data) { const char *name = data; - return !strcmp(chip->label, name); + return !strcmp(gc->label, name); } static struct gpio_chip *find_chip_by_name(const char *name) @@ -1917,21 +1917,21 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) return 0; } -static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) +static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc) { - bitmap_free(gpiochip->irq.valid_mask); - gpiochip->irq.valid_mask = NULL; + bitmap_free(gc->irq.valid_mask); + gc->irq.valid_mask = NULL; } -bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc, unsigned int offset) { - if (!gpiochip_line_is_valid(gpiochip, offset)) + if (!gpiochip_line_is_valid(gc, offset)) return false; /* No mask means all valid */ - if (likely(!gpiochip->irq.valid_mask)) + if (likely(!gc->irq.valid_mask)) return true; - return test_bit(offset, gpiochip->irq.valid_mask); + return test_bit(offset, gc->irq.valid_mask); } EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid); @@ -1983,16 +1983,16 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gc, /** * gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip - * @gpiochip: the gpiochip to set the irqchip nested handler to + * @gc: the gpiochip to set the irqchip nested handler to * @irqchip: the irqchip to nest to the gpiochip * @parent_irq: the irq number corresponding to the parent IRQ for this * nested irqchip */ -void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip, +void gpiochip_set_nested_irqchip(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int parent_irq) { - gpiochip_set_cascaded_irqchip(gpiochip, parent_irq, NULL); + gpiochip_set_cascaded_irqchip(gc, parent_irq, NULL); } EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip); @@ -2169,7 +2169,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, return ret; } -static unsigned int gpiochip_child_offset_to_irq_noop(struct gpio_chip *chip, +static unsigned int gpiochip_child_offset_to_irq_noop(struct gpio_chip *gc, unsigned int offset) { return offset; @@ -2229,7 +2229,7 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) return !!gc->irq.parent_domain; } -void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, +void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type) { @@ -2239,7 +2239,7 @@ void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, if (!fwspec) return NULL; - fwspec->fwnode = chip->irq.parent_domain->fwnode; + fwspec->fwnode = gc->irq.parent_domain->fwnode; fwspec->param_count = 2; fwspec->param[0] = parent_hwirq; fwspec->param[1] = parent_type; @@ -2248,7 +2248,7 @@ void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); -void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, +void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type) { @@ -2258,7 +2258,7 @@ void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, if (!fwspec) return NULL; - fwspec->fwnode = chip->irq.parent_domain->fwnode; + fwspec->fwnode = gc->irq.parent_domain->fwnode; fwspec->param_count = 4; fwspec->param[0] = 0; fwspec->param[1] = parent_hwirq; @@ -2296,28 +2296,28 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { - struct gpio_chip *chip = d->host_data; + struct gpio_chip *gc = d->host_data; int ret = 0; - if (!gpiochip_irqchip_irq_valid(chip, hwirq)) + if (!gpiochip_irqchip_irq_valid(gc, hwirq)) return -ENXIO; - irq_set_chip_data(irq, chip); + irq_set_chip_data(irq, gc); /* * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion. */ - irq_set_lockdep_class(irq, chip->irq.lock_key, chip->irq.request_key); - irq_set_chip_and_handler(irq, chip->irq.chip, chip->irq.handler); + irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key); + irq_set_chip_and_handler(irq, gc->irq.chip, gc->irq.handler); /* Chips that use nested thread handlers have them marked */ - if (chip->irq.threaded) + if (gc->irq.threaded) irq_set_nested_thread(irq, 1); irq_set_noprobe(irq); - if (chip->irq.num_parents == 1) - ret = irq_set_parent(irq, chip->irq.parents[0]); - else if (chip->irq.map) - ret = irq_set_parent(irq, chip->irq.map[hwirq]); + if (gc->irq.num_parents == 1) + ret = irq_set_parent(irq, gc->irq.parents[0]); + else if (gc->irq.map) + ret = irq_set_parent(irq, gc->irq.map[hwirq]); if (ret < 0) return ret; @@ -2326,8 +2326,8 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, * No set-up of the hardware will happen if IRQ_TYPE_NONE * is passed as default type. */ - if (chip->irq.default_type != IRQ_TYPE_NONE) - irq_set_irq_type(irq, chip->irq.default_type); + if (gc->irq.default_type != IRQ_TYPE_NONE) + irq_set_irq_type(irq, gc->irq.default_type); return 0; } @@ -2335,9 +2335,9 @@ EXPORT_SYMBOL_GPL(gpiochip_irq_map); void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq) { - struct gpio_chip *chip = d->host_data; + struct gpio_chip *gc = d->host_data; - if (chip->irq.threaded) + if (gc->irq.threaded) irq_set_nested_thread(irq, 0); irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_data(irq, NULL); @@ -2369,9 +2369,9 @@ static const struct irq_domain_ops gpiochip_domain_ops = { int gpiochip_irq_domain_activate(struct irq_domain *domain, struct irq_data *data, bool reserve) { - struct gpio_chip *chip = domain->host_data; + struct gpio_chip *gc = domain->host_data; - return gpiochip_lock_as_irq(chip, data->hwirq); + return gpiochip_lock_as_irq(gc, data->hwirq); } EXPORT_SYMBOL_GPL(gpiochip_irq_domain_activate); @@ -2387,17 +2387,17 @@ EXPORT_SYMBOL_GPL(gpiochip_irq_domain_activate); void gpiochip_irq_domain_deactivate(struct irq_domain *domain, struct irq_data *data) { - struct gpio_chip *chip = domain->host_data; + struct gpio_chip *gc = domain->host_data; - return gpiochip_unlock_as_irq(chip, data->hwirq); + return gpiochip_unlock_as_irq(gc, data->hwirq); } EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate); -static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) +static int gpiochip_to_irq(struct gpio_chip *gc, unsigned offset) { - struct irq_domain *domain = chip->irq.domain; + struct irq_domain *domain = gc->irq.domain; - if (!gpiochip_irqchip_irq_valid(chip, offset)) + if (!gpiochip_irqchip_irq_valid(gc, offset)) return -ENXIO; #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY @@ -2406,7 +2406,7 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) spec.fwnode = domain->fwnode; spec.param_count = 2; - spec.param[0] = chip->irq.child_offset_to_irq(chip, offset); + spec.param[0] = gc->irq.child_offset_to_irq(gc, offset); spec.param[1] = IRQ_TYPE_NONE; return irq_create_fwspec_mapping(&spec); @@ -2418,50 +2418,50 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) static int gpiochip_irq_reqres(struct irq_data *d) { - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - return gpiochip_reqres_irq(chip, d->hwirq); + return gpiochip_reqres_irq(gc, d->hwirq); } static void gpiochip_irq_relres(struct irq_data *d) { - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - gpiochip_relres_irq(chip, d->hwirq); + gpiochip_relres_irq(gc, d->hwirq); } static void gpiochip_irq_enable(struct irq_data *d) { - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - gpiochip_enable_irq(chip, d->hwirq); - if (chip->irq.irq_enable) - chip->irq.irq_enable(d); + gpiochip_enable_irq(gc, d->hwirq); + if (gc->irq.irq_enable) + gc->irq.irq_enable(d); else - chip->irq.chip->irq_unmask(d); + gc->irq.chip->irq_unmask(d); } static void gpiochip_irq_disable(struct irq_data *d) { - struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - if (chip->irq.irq_disable) - chip->irq.irq_disable(d); + if (gc->irq.irq_disable) + gc->irq.irq_disable(d); else - chip->irq.chip->irq_mask(d); - gpiochip_disable_irq(chip, d->hwirq); + gc->irq.chip->irq_mask(d); + gpiochip_disable_irq(gc, d->hwirq); } -static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip) +static void gpiochip_set_irq_hooks(struct gpio_chip *gc) { - struct irq_chip *irqchip = gpiochip->irq.chip; + struct irq_chip *irqchip = gc->irq.chip; if (!irqchip->irq_request_resources && !irqchip->irq_release_resources) { irqchip->irq_request_resources = gpiochip_irq_reqres; irqchip->irq_release_resources = gpiochip_irq_relres; } - if (WARN_ON(gpiochip->irq.irq_enable)) + if (WARN_ON(gc->irq.irq_enable)) return; /* Check if the irqchip already has this hook... */ if (irqchip->irq_enable == gpiochip_irq_enable) { @@ -2469,27 +2469,27 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip) * ...and if so, give a gentle warning that this is bad * practice. */ - chip_info(gpiochip, + chip_info(gc, "detected irqchip that is shared with multiple gpiochips: please fix the driver.\n"); return; } - gpiochip->irq.irq_enable = irqchip->irq_enable; - gpiochip->irq.irq_disable = irqchip->irq_disable; + gc->irq.irq_enable = irqchip->irq_enable; + gc->irq.irq_disable = irqchip->irq_disable; irqchip->irq_enable = gpiochip_irq_enable; irqchip->irq_disable = gpiochip_irq_disable; } /** * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip - * @gpiochip: the GPIO chip to add the IRQ chip to + * @gc: the GPIO chip to add the IRQ chip to * @lock_key: lockdep class for IRQ lock * @request_key: lockdep class for IRQ request */ -static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, +static int gpiochip_add_irqchip(struct gpio_chip *gc, struct lock_class_key *lock_key, struct lock_class_key *request_key) { - struct irq_chip *irqchip = gpiochip->irq.chip; + struct irq_chip *irqchip = gc->irq.chip; const struct irq_domain_ops *ops = NULL; struct device_node *np; unsigned int type; @@ -2498,13 +2498,13 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, if (!irqchip) return 0; - if (gpiochip->irq.parent_handler && gpiochip->can_sleep) { - chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n"); + if (gc->irq.parent_handler && gc->can_sleep) { + chip_err(gc, "you cannot have chained interrupts on a chip that may sleep\n"); return -EINVAL; } - np = gpiochip->gpiodev->dev.of_node; - type = gpiochip->irq.default_type; + np = gc->gpiodev->dev.of_node; + type = gc->irq.default_type; /* * Specifying a default trigger is a terrible idea if DT or ACPI is @@ -2515,74 +2515,74 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, "%s: Ignoring %u default trigger\n", np->full_name, type)) type = IRQ_TYPE_NONE; - if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) { - acpi_handle_warn(ACPI_HANDLE(gpiochip->parent), + if (has_acpi_companion(gc->parent) && type != IRQ_TYPE_NONE) { + acpi_handle_warn(ACPI_HANDLE(gc->parent), "Ignoring %u default trigger\n", type); type = IRQ_TYPE_NONE; } - gpiochip->to_irq = gpiochip_to_irq; - gpiochip->irq.default_type = type; - gpiochip->irq.lock_key = lock_key; - gpiochip->irq.request_key = request_key; + gc->to_irq = gpiochip_to_irq; + gc->irq.default_type = type; + gc->irq.lock_key = lock_key; + gc->irq.request_key = request_key; /* If a parent irqdomain is provided, let's build a hierarchy */ - if (gpiochip_hierarchy_is_hierarchical(gpiochip)) { - int ret = gpiochip_hierarchy_add_domain(gpiochip); + if (gpiochip_hierarchy_is_hierarchical(gc)) { + int ret = gpiochip_hierarchy_add_domain(gc); if (ret) return ret; } else { /* Some drivers provide custom irqdomain ops */ - if (gpiochip->irq.domain_ops) - ops = gpiochip->irq.domain_ops; + if (gc->irq.domain_ops) + ops = gc->irq.domain_ops; if (!ops) ops = &gpiochip_domain_ops; - gpiochip->irq.domain = irq_domain_add_simple(np, - gpiochip->ngpio, - gpiochip->irq.first, - ops, gpiochip); - if (!gpiochip->irq.domain) + gc->irq.domain = irq_domain_add_simple(np, + gc->ngpio, + gc->irq.first, + ops, gc); + if (!gc->irq.domain) return -EINVAL; } - if (gpiochip->irq.parent_handler) { - void *data = gpiochip->irq.parent_handler_data ?: gpiochip; + if (gc->irq.parent_handler) { + void *data = gc->irq.parent_handler_data ?: gc; - for (i = 0; i < gpiochip->irq.num_parents; i++) { + for (i = 0; i < gc->irq.num_parents; i++) { /* * The parent IRQ chip is already using the chip_data * for this IRQ chip, so our callbacks simply use the * handler_data. */ - irq_set_chained_handler_and_data(gpiochip->irq.parents[i], - gpiochip->irq.parent_handler, + irq_set_chained_handler_and_data(gc->irq.parents[i], + gc->irq.parent_handler, data); } } - gpiochip_set_irq_hooks(gpiochip); + gpiochip_set_irq_hooks(gc); - acpi_gpiochip_request_interrupts(gpiochip); + acpi_gpiochip_request_interrupts(gc); return 0; } /** * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip - * @gpiochip: the gpiochip to remove the irqchip from + * @gc: the gpiochip to remove the irqchip from * * This is called only from gpiochip_remove() */ -static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) +static void gpiochip_irqchip_remove(struct gpio_chip *gc) { - struct irq_chip *irqchip = gpiochip->irq.chip; + struct irq_chip *irqchip = gc->irq.chip; unsigned int offset; - acpi_gpiochip_free_interrupts(gpiochip); + acpi_gpiochip_free_interrupts(gc); - if (irqchip && gpiochip->irq.parent_handler) { - struct gpio_irq_chip *irq = &gpiochip->irq; + if (irqchip && gc->irq.parent_handler) { + struct gpio_irq_chip *irq = &gc->irq; unsigned int i; for (i = 0; i < irq->num_parents; i++) @@ -2591,18 +2591,18 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) } /* Remove all IRQ mappings and delete the domain */ - if (gpiochip->irq.domain) { + if (gc->irq.domain) { unsigned int irq; - for (offset = 0; offset < gpiochip->ngpio; offset++) { - if (!gpiochip_irqchip_irq_valid(gpiochip, offset)) + for (offset = 0; offset < gc->ngpio; offset++) { + if (!gpiochip_irqchip_irq_valid(gc, offset)) continue; - irq = irq_find_mapping(gpiochip->irq.domain, offset); + irq = irq_find_mapping(gc->irq.domain, offset); irq_dispose_mapping(irq); } - irq_domain_remove(gpiochip->irq.domain); + irq_domain_remove(gc->irq.domain); } if (irqchip) { @@ -2611,20 +2611,20 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) irqchip->irq_release_resources = NULL; } if (irqchip->irq_enable == gpiochip_irq_enable) { - irqchip->irq_enable = gpiochip->irq.irq_enable; - irqchip->irq_disable = gpiochip->irq.irq_disable; + irqchip->irq_enable = gc->irq.irq_enable; + irqchip->irq_disable = gc->irq.irq_disable; } } - gpiochip->irq.irq_enable = NULL; - gpiochip->irq.irq_disable = NULL; - gpiochip->irq.chip = NULL; + gc->irq.irq_enable = NULL; + gc->irq.irq_disable = NULL; + gc->irq.chip = NULL; - gpiochip_irqchip_free_valid_mask(gpiochip); + gpiochip_irqchip_free_valid_mask(gc); } /** * gpiochip_irqchip_add_key() - adds an irqchip to a gpiochip - * @gpiochip: the gpiochip to add the irqchip to + * @gc: the gpiochip to add the irqchip to * @irqchip: the irqchip to add to the gpiochip * @first_irq: if not dynamically assigned, the base (first) IRQ to * allocate gpiochip irqs from @@ -2649,7 +2649,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) * the pins on the gpiochip can generate a unique IRQ. Everything else * need to be open coded. */ -int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, +int gpiochip_irqchip_add_key(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int first_irq, irq_flow_handler_t handler, @@ -2660,23 +2660,23 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, { struct device_node *of_node; - if (!gpiochip || !irqchip) + if (!gc || !irqchip) return -EINVAL; - if (!gpiochip->parent) { + if (!gc->parent) { pr_err("missing gpiochip .dev parent pointer\n"); return -EINVAL; } - gpiochip->irq.threaded = threaded; - of_node = gpiochip->parent->of_node; + gc->irq.threaded = threaded; + of_node = gc->parent->of_node; #ifdef CONFIG_OF_GPIO /* * If the gpiochip has an assigned OF node this takes precedence - * FIXME: get rid of this and use gpiochip->parent->of_node + * FIXME: get rid of this and use gc->parent->of_node * everywhere */ - if (gpiochip->of_node) - of_node = gpiochip->of_node; + if (gc->of_node) + of_node = gc->of_node; #endif /* * Specifying a default trigger is a terrible idea if DT or ACPI is @@ -2686,29 +2686,29 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, if (WARN(of_node && type != IRQ_TYPE_NONE, "%pOF: Ignoring %d default trigger\n", of_node, type)) type = IRQ_TYPE_NONE; - if (has_acpi_companion(gpiochip->parent) && type != IRQ_TYPE_NONE) { - acpi_handle_warn(ACPI_HANDLE(gpiochip->parent), + if (has_acpi_companion(gc->parent) && type != IRQ_TYPE_NONE) { + acpi_handle_warn(ACPI_HANDLE(gc->parent), "Ignoring %d default trigger\n", type); type = IRQ_TYPE_NONE; } - gpiochip->irq.chip = irqchip; - gpiochip->irq.handler = handler; - gpiochip->irq.default_type = type; - gpiochip->to_irq = gpiochip_to_irq; - gpiochip->irq.lock_key = lock_key; - gpiochip->irq.request_key = request_key; - gpiochip->irq.domain = irq_domain_add_simple(of_node, - gpiochip->ngpio, first_irq, - &gpiochip_domain_ops, gpiochip); - if (!gpiochip->irq.domain) { - gpiochip->irq.chip = NULL; + gc->irq.chip = irqchip; + gc->irq.handler = handler; + gc->irq.default_type = type; + gc->to_irq = gpiochip_to_irq; + gc->irq.lock_key = lock_key; + gc->irq.request_key = request_key; + gc->irq.domain = irq_domain_add_simple(of_node, + gc->ngpio, first_irq, + &gpiochip_domain_ops, gc); + if (!gc->irq.domain) { + gc->irq.chip = NULL; return -EINVAL; } - gpiochip_set_irq_hooks(gpiochip); + gpiochip_set_irq_hooks(gc); - acpi_gpiochip_request_interrupts(gpiochip); + acpi_gpiochip_request_interrupts(gc); return 0; } @@ -2716,65 +2716,65 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key); #else /* CONFIG_GPIOLIB_IRQCHIP */ -static inline int gpiochip_add_irqchip(struct gpio_chip *gpiochip, +static inline int gpiochip_add_irqchip(struct gpio_chip *gc, struct lock_class_key *lock_key, struct lock_class_key *request_key) { return 0; } -static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} +static void gpiochip_irqchip_remove(struct gpio_chip *gc) {} -static inline int gpiochip_irqchip_init_hw(struct gpio_chip *gpiochip) +static inline int gpiochip_irqchip_init_hw(struct gpio_chip *gc) { return 0; } -static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) +static inline int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) { return 0; } -static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) +static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc) { } #endif /* CONFIG_GPIOLIB_IRQCHIP */ /** * gpiochip_generic_request() - request the gpio function for a pin - * @chip: the gpiochip owning the GPIO + * @gc: the gpiochip owning the GPIO * @offset: the offset of the GPIO to request for GPIO function */ -int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset) +int gpiochip_generic_request(struct gpio_chip *gc, unsigned offset) { #ifdef CONFIG_PINCTRL - if (list_empty(&chip->gpiodev->pin_ranges)) + if (list_empty(&gc->gpiodev->pin_ranges)) return 0; #endif - return pinctrl_gpio_request(chip->gpiodev->base + offset); + return pinctrl_gpio_request(gc->gpiodev->base + offset); } EXPORT_SYMBOL_GPL(gpiochip_generic_request); /** * gpiochip_generic_free() - free the gpio function from a pin - * @chip: the gpiochip to request the gpio function for + * @gc: the gpiochip to request the gpio function for * @offset: the offset of the GPIO to free from GPIO function */ -void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset) +void gpiochip_generic_free(struct gpio_chip *gc, unsigned offset) { - pinctrl_gpio_free(chip->gpiodev->base + offset); + pinctrl_gpio_free(gc->gpiodev->base + offset); } EXPORT_SYMBOL_GPL(gpiochip_generic_free); /** * gpiochip_generic_config() - apply configuration for a pin - * @chip: the gpiochip owning the GPIO + * @gc: the gpiochip owning the GPIO * @offset: the offset of the GPIO to apply the configuration * @config: the configuration to be applied */ -int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, +int gpiochip_generic_config(struct gpio_chip *gc, unsigned offset, unsigned long config) { - return pinctrl_gpio_set_config(chip->gpiodev->base + offset, config); + return pinctrl_gpio_set_config(gc->gpiodev->base + offset, config); } EXPORT_SYMBOL_GPL(gpiochip_generic_config); @@ -2782,7 +2782,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_config); /** * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping - * @chip: the gpiochip to add the range for + * @gc: the gpiochip to add the range for * @pctldev: the pin controller to map to * @gpio_offset: the start offset in the current gpio_chip number space * @pin_group: name of the pin group inside the pin controller @@ -2792,24 +2792,24 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_config); * Documentation/devicetree/bindings/gpio/gpio.txt on how to * bind pinctrl and gpio drivers via the "gpio-ranges" property. */ -int gpiochip_add_pingroup_range(struct gpio_chip *chip, +int gpiochip_add_pingroup_range(struct gpio_chip *gc, struct pinctrl_dev *pctldev, unsigned int gpio_offset, const char *pin_group) { struct gpio_pin_range *pin_range; - struct gpio_device *gdev = chip->gpiodev; + struct gpio_device *gdev = gc->gpiodev; int ret; pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - chip_err(chip, "failed to allocate pin ranges\n"); + chip_err(gc, "failed to allocate pin ranges\n"); return -ENOMEM; } /* Use local offset as range ID */ pin_range->range.id = gpio_offset; - pin_range->range.gc = chip; - pin_range->range.name = chip->label; + pin_range->range.gc = gc; + pin_range->range.name = gc->label; pin_range->range.base = gdev->base + gpio_offset; pin_range->pctldev = pctldev; @@ -2823,7 +2823,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pinctrl_add_gpio_range(pctldev, &pin_range->range); - chip_dbg(chip, "created GPIO range %d->%d ==> %s PINGRP %s\n", + chip_dbg(gc, "created GPIO range %d->%d ==> %s PINGRP %s\n", gpio_offset, gpio_offset + pin_range->range.npins - 1, pinctrl_dev_get_devname(pctldev), pin_group); @@ -2835,7 +2835,7 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); /** * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping - * @chip: the gpiochip to add the range for + * @gc: the gpiochip to add the range for * @pinctl_name: the dev_name() of the pin controller to map to * @gpio_offset: the start offset in the current gpio_chip number space * @pin_offset: the start offset in the pin controller number space @@ -2850,24 +2850,24 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); * Documentation/devicetree/bindings/gpio/gpio.txt on how to * bind pinctrl and gpio drivers via the "gpio-ranges" property. */ -int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, +int gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins) { struct gpio_pin_range *pin_range; - struct gpio_device *gdev = chip->gpiodev; + struct gpio_device *gdev = gc->gpiodev; int ret; pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); if (!pin_range) { - chip_err(chip, "failed to allocate pin ranges\n"); + chip_err(gc, "failed to allocate pin ranges\n"); return -ENOMEM; } /* Use local offset as range ID */ pin_range->range.id = gpio_offset; - pin_range->range.gc = chip; - pin_range->range.name = chip->label; + pin_range->range.gc = gc; + pin_range->range.name = gc->label; pin_range->range.base = gdev->base + gpio_offset; pin_range->range.pin_base = pin_offset; pin_range->range.npins = npins; @@ -2875,11 +2875,11 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, &pin_range->range); if (IS_ERR(pin_range->pctldev)) { ret = PTR_ERR(pin_range->pctldev); - chip_err(chip, "could not create pin range\n"); + chip_err(gc, "could not create pin range\n"); kfree(pin_range); return ret; } - chip_dbg(chip, "created GPIO range %d->%d ==> %s PIN %d->%d\n", + chip_dbg(gc, "created GPIO range %d->%d ==> %s PIN %d->%d\n", gpio_offset, gpio_offset + npins - 1, pinctl_name, pin_offset, pin_offset + npins - 1); @@ -2892,12 +2892,12 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); /** * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings - * @chip: the chip to remove all the mappings for + * @gc: the chip to remove all the mappings for */ -void gpiochip_remove_pin_ranges(struct gpio_chip *chip) +void gpiochip_remove_pin_ranges(struct gpio_chip *gc) { struct gpio_pin_range *pin_range, *tmp; - struct gpio_device *gdev = chip->gpiodev; + struct gpio_device *gdev = gc->gpiodev; list_for_each_entry_safe(pin_range, tmp, &gdev->pin_ranges, node) { list_del(&pin_range->node); @@ -2916,7 +2916,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); */ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) { - struct gpio_chip *chip = desc->gdev->chip; + struct gpio_chip *gc = desc->gdev->chip; int ret; unsigned long flags; unsigned offset; @@ -2942,12 +2942,12 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) goto done; } - if (chip->request) { - /* chip->request may sleep */ + if (gc->request) { + /* gc->request may sleep */ spin_unlock_irqrestore(&gpio_lock, flags); offset = gpio_chip_hwgpio(desc); - if (gpiochip_line_is_valid(chip, offset)) - ret = chip->request(chip, offset); + if (gpiochip_line_is_valid(gc, offset)) + ret = gc->request(gc, offset); else ret = -EINVAL; spin_lock_irqsave(&gpio_lock, flags); @@ -2959,8 +2959,8 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) goto done; } } - if (chip->get_direction) { - /* chip->get_direction may sleep */ + if (gc->get_direction) { + /* gc->get_direction may sleep */ spin_unlock_irqrestore(&gpio_lock, flags); gpiod_get_direction(desc); spin_lock_irqsave(&gpio_lock, flags); @@ -3036,7 +3036,7 @@ static bool gpiod_free_commit(struct gpio_desc *desc) { bool ret = false; unsigned long flags; - struct gpio_chip *chip; + struct gpio_chip *gc; might_sleep(); @@ -3044,12 +3044,12 @@ static bool gpiod_free_commit(struct gpio_desc *desc) spin_lock_irqsave(&gpio_lock, flags); - chip = desc->gdev->chip; - if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { - if (chip->free) { + gc = desc->gdev->chip; + if (gc && test_bit(FLAG_REQUESTED, &desc->flags)) { + if (gc->free) { spin_unlock_irqrestore(&gpio_lock, flags); - might_sleep_if(chip->can_sleep); - chip->free(chip, gpio_chip_hwgpio(desc)); + might_sleep_if(gc->can_sleep); + gc->free(gc, gpio_chip_hwgpio(desc)); spin_lock_irqsave(&gpio_lock, flags); } kfree_const(desc->label); @@ -3087,7 +3087,7 @@ void gpiod_free(struct gpio_desc *desc) /** * gpiochip_is_requested - return string iff signal was requested - * @chip: controller managing the signal + * @gc: controller managing the signal * @offset: of signal within controller's 0..(ngpio - 1) range * * Returns NULL if the GPIO is not currently requested, else a string. @@ -3098,14 +3098,14 @@ void gpiod_free(struct gpio_desc *desc) * help with diagnostics, and knowing that the signal is used as a GPIO * can help avoid accidentally multiplexing it to another controller. */ -const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) +const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned offset) { struct gpio_desc *desc; - if (offset >= chip->ngpio) + if (offset >= gc->ngpio) return NULL; - desc = gpiochip_get_desc(chip, offset); + desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return NULL; @@ -3117,7 +3117,7 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); /** * gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor - * @chip: GPIO chip + * @gc: GPIO chip * @hwnum: hardware number of the GPIO for which to request the descriptor * @label: label for the GPIO * @lflags: lookup flags for this GPIO or 0 if default, this can be used to @@ -3136,17 +3136,17 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); * A pointer to the GPIO descriptor, or an ERR_PTR()-encoded negative error * code on failure. */ -struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, +struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, unsigned int hwnum, const char *label, enum gpio_lookup_flags lflags, enum gpiod_flags dflags) { - struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); + struct gpio_desc *desc = gpiochip_get_desc(gc, hwnum); int ret; if (IS_ERR(desc)) { - chip_err(chip, "failed to get GPIO descriptor\n"); + chip_err(gc, "failed to get GPIO descriptor\n"); return desc; } @@ -3156,7 +3156,7 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, ret = gpiod_configure_flags(desc, label, lflags, dflags); if (ret) { - chip_err(chip, "setup of own GPIO %s failed\n", label); + chip_err(gc, "setup of own GPIO %s failed\n", label); gpiod_free_commit(desc); return ERR_PTR(ret); } @@ -3200,7 +3200,7 @@ static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset, static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode) { - struct gpio_chip *chip = desc->gdev->chip; + struct gpio_chip *gc = desc->gdev->chip; unsigned long config; unsigned arg; @@ -3215,7 +3215,7 @@ static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode) } config = PIN_CONF_PACKED(mode, arg); - return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config); + return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config); } static int gpio_set_bias(struct gpio_desc *desc) @@ -3249,18 +3249,18 @@ static int gpio_set_bias(struct gpio_desc *desc) */ int gpiod_direction_input(struct gpio_desc *desc) { - struct gpio_chip *chip; + struct gpio_chip *gc; int ret = 0; VALIDATE_DESC(desc); - chip = desc->gdev->chip; + gc = desc->gdev->chip; /* * It is legal to have no .get() and .direction_input() specified if * the chip is output-only, but you can't specify .direction_input() * and not support the .get() operation, that doesn't make sense. */ - if (!chip->get && chip->direction_input) { + if (!gc->get && gc->direction_input) { gpiod_warn(desc, "%s: missing get() but have direction_input()\n", __func__); @@ -3273,10 +3273,10 @@ int gpiod_direction_input(struct gpio_desc *desc) * direction (if .get_direction() is supported) else we silently * assume we are in input mode after this. */ - if (chip->direction_input) { - ret = chip->direction_input(chip, gpio_chip_hwgpio(desc)); - } else if (chip->get_direction && - (chip->get_direction(chip, gpio_chip_hwgpio(desc)) != 1)) { + if (gc->direction_input) { + ret = gc->direction_input(gc, gpio_chip_hwgpio(desc)); + } else if (gc->get_direction && + (gc->get_direction(gc, gpio_chip_hwgpio(desc)) != 1)) { gpiod_warn(desc, "%s: missing direction_input() operation and line is output\n", __func__); @@ -3439,12 +3439,12 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output); */ int gpiod_set_config(struct gpio_desc *desc, unsigned long config) { - struct gpio_chip *chip; + struct gpio_chip *gc; VALIDATE_DESC(desc); - chip = desc->gdev->chip; + gc = desc->gdev->chip; - return gpio_do_set_config(chip, gpio_chip_hwgpio(desc), config); + return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config); } EXPORT_SYMBOL_GPL(gpiod_set_config); @@ -3476,7 +3476,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce); */ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) { - struct gpio_chip *chip; + struct gpio_chip *gc; unsigned long packed; int gpio; int rc; @@ -3489,14 +3489,14 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) assign_bit(FLAG_TRANSITORY, &desc->flags, transitory); /* If the driver supports it, set the persistence state now */ - chip = desc->gdev->chip; - if (!chip->set_config) + gc = desc->gdev->chip; + if (!gc->set_config) return 0; packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE, !transitory); gpio = gpio_chip_hwgpio(desc); - rc = gpio_do_set_config(chip, gpio, packed); + rc = gpio_do_set_config(gc, gpio, packed); if (rc == -ENOTSUPP) { dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n", gpio); @@ -3555,28 +3555,28 @@ EXPORT_SYMBOL_GPL(gpiod_toggle_active_low); static int gpiod_get_raw_value_commit(const struct gpio_desc *desc) { - struct gpio_chip *chip; + struct gpio_chip *gc; int offset; int value; - chip = desc->gdev->chip; + gc = desc->gdev->chip; offset = gpio_chip_hwgpio(desc); - value = chip->get ? chip->get(chip, offset) : -EIO; + value = gc->get ? gc->get(gc, offset) : -EIO; value = value < 0 ? value : !!value; trace_gpio_value(desc_to_gpio(desc), 1, value); return value; } -static int gpio_chip_get_multiple(struct gpio_chip *chip, +static int gpio_chip_get_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { - if (chip->get_multiple) { - return chip->get_multiple(chip, mask, bits); - } else if (chip->get) { + if (gc->get_multiple) { + return gc->get_multiple(gc, mask, bits); + } else if (gc->get) { int i, value; - for_each_set_bit(i, mask, chip->ngpio) { - value = chip->get(chip, i); + for_each_set_bit(i, mask, gc->ngpio) { + value = gc->get(gc, i); if (value < 0) return value; __assign_bit(i, bits, value); @@ -3624,26 +3624,26 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, } while (i < array_size) { - struct gpio_chip *chip = desc_array[i]->gdev->chip; + struct gpio_chip *gc = desc_array[i]->gdev->chip; unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; unsigned long *mask, *bits; int first, j, ret; - if (likely(chip->ngpio <= FASTPATH_NGPIO)) { + if (likely(gc->ngpio <= FASTPATH_NGPIO)) { mask = fastpath; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio), + mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), sizeof(*mask), can_sleep ? GFP_KERNEL : GFP_ATOMIC); if (!mask) return -ENOMEM; } - bits = mask + BITS_TO_LONGS(chip->ngpio); - bitmap_zero(mask, chip->ngpio); + bits = mask + BITS_TO_LONGS(gc->ngpio); + bitmap_zero(mask, gc->ngpio); if (!can_sleep) - WARN_ON(chip->can_sleep); + WARN_ON(gc->can_sleep); /* collect all inputs belonging to the same chip */ first = i; @@ -3658,9 +3658,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, i = find_next_zero_bit(array_info->get_mask, array_size, i); } while ((i < array_size) && - (desc_array[i]->gdev->chip == chip)); + (desc_array[i]->gdev->chip == gc)); - ret = gpio_chip_get_multiple(chip, mask, bits); + ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { if (mask != fastpath) kfree(mask); @@ -3798,13 +3798,13 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value); static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) { int ret = 0; - struct gpio_chip *chip = desc->gdev->chip; + struct gpio_chip *gc = desc->gdev->chip; int offset = gpio_chip_hwgpio(desc); if (value) { - ret = chip->direction_input(chip, offset); + ret = gc->direction_input(gc, offset); } else { - ret = chip->direction_output(chip, offset, 0); + ret = gc->direction_output(gc, offset, 0); if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); } @@ -3823,15 +3823,15 @@ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value) { int ret = 0; - struct gpio_chip *chip = desc->gdev->chip; + struct gpio_chip *gc = desc->gdev->chip; int offset = gpio_chip_hwgpio(desc); if (value) { - ret = chip->direction_output(chip, offset, 1); + ret = gc->direction_output(gc, offset, 1); if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); } else { - ret = chip->direction_input(chip, offset); + ret = gc->direction_input(gc, offset); } trace_gpio_direction(desc_to_gpio(desc), !value, ret); if (ret < 0) @@ -3842,33 +3842,34 @@ static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value static void gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value) { - struct gpio_chip *chip; + struct gpio_chip *gc; - chip = desc->gdev->chip; + gc = desc->gdev->chip; trace_gpio_value(desc_to_gpio(desc), 0, value); - chip->set(chip, gpio_chip_hwgpio(desc), value); + gc->set(gc, gpio_chip_hwgpio(desc), value); } /* * set multiple outputs on the same chip; * use the chip's set_multiple function if available; * otherwise set the outputs sequentially; + * @chip: the GPIO chip we operate on * @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word * defines which outputs are to be changed * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word * defines the values the outputs specified by mask are to be set to */ -static void gpio_chip_set_multiple(struct gpio_chip *chip, +static void gpio_chip_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { - if (chip->set_multiple) { - chip->set_multiple(chip, mask, bits); + if (gc->set_multiple) { + gc->set_multiple(gc, mask, bits); } else { unsigned int i; /* set outputs if the corresponding mask bit is set */ - for_each_set_bit(i, mask, chip->ngpio) - chip->set(chip, i, test_bit(i, bits)); + for_each_set_bit(i, mask, gc->ngpio) + gc->set(gc, i, test_bit(i, bits)); } } @@ -3907,26 +3908,26 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, } while (i < array_size) { - struct gpio_chip *chip = desc_array[i]->gdev->chip; + struct gpio_chip *gc = desc_array[i]->gdev->chip; unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; unsigned long *mask, *bits; int count = 0; - if (likely(chip->ngpio <= FASTPATH_NGPIO)) { + if (likely(gc->ngpio <= FASTPATH_NGPIO)) { mask = fastpath; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(chip->ngpio), + mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), sizeof(*mask), can_sleep ? GFP_KERNEL : GFP_ATOMIC); if (!mask) return -ENOMEM; } - bits = mask + BITS_TO_LONGS(chip->ngpio); - bitmap_zero(mask, chip->ngpio); + bits = mask + BITS_TO_LONGS(gc->ngpio); + bitmap_zero(mask, gc->ngpio); if (!can_sleep) - WARN_ON(chip->can_sleep); + WARN_ON(gc->can_sleep); do { struct gpio_desc *desc = desc_array[i]; @@ -3962,10 +3963,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, i = find_next_zero_bit(array_info->set_mask, array_size, i); } while ((i < array_size) && - (desc_array[i]->gdev->chip == chip)); + (desc_array[i]->gdev->chip == gc)); /* push collected bits to outputs */ if (count != 0) - gpio_chip_set_multiple(chip, mask, bits); + gpio_chip_set_multiple(gc, mask, bits); if (mask != fastpath) kfree(mask); @@ -4127,7 +4128,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_consumer_name); */ int gpiod_to_irq(const struct gpio_desc *desc) { - struct gpio_chip *chip; + struct gpio_chip *gc; int offset; /* @@ -4138,10 +4139,10 @@ int gpiod_to_irq(const struct gpio_desc *desc) if (!desc || IS_ERR(desc) || !desc->gdev || !desc->gdev->chip) return -EINVAL; - chip = desc->gdev->chip; + gc = desc->gdev->chip; offset = gpio_chip_hwgpio(desc); - if (chip->to_irq) { - int retirq = chip->to_irq(chip, offset); + if (gc->to_irq) { + int retirq = gc->to_irq(gc, offset); /* Zero means NO_IRQ */ if (!retirq) @@ -4155,17 +4156,17 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq); /** * gpiochip_lock_as_irq() - lock a GPIO to be used as IRQ - * @chip: the chip the GPIO to lock belongs to + * @gc: the chip the GPIO to lock belongs to * @offset: the offset of the GPIO to lock as IRQ * * This is used directly by GPIO drivers that want to lock down * a certain GPIO line to be used for IRQs. */ -int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) +int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; - desc = gpiochip_get_desc(chip, offset); + desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return PTR_ERR(desc); @@ -4173,18 +4174,18 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) * If it's fast: flush the direction setting if something changed * behind our back */ - if (!chip->can_sleep && chip->get_direction) { + if (!gc->can_sleep && gc->get_direction) { int dir = gpiod_get_direction(desc); if (dir < 0) { - chip_err(chip, "%s: cannot get GPIO direction\n", + chip_err(gc, "%s: cannot get GPIO direction\n", __func__); return dir; } } if (test_bit(FLAG_IS_OUT, &desc->flags)) { - chip_err(chip, + chip_err(gc, "%s: tried to flag a GPIO set as output for IRQ\n", __func__); return -EIO; @@ -4207,17 +4208,17 @@ EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq); /** * gpiochip_unlock_as_irq() - unlock a GPIO used as IRQ - * @chip: the chip the GPIO to lock belongs to + * @gc: the chip the GPIO to lock belongs to * @offset: the offset of the GPIO to lock as IRQ * * This is used directly by GPIO drivers that want to indicate * that a certain GPIO is no longer used exclusively for IRQ. */ -void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) +void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; - desc = gpiochip_get_desc(chip, offset); + desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return; @@ -4230,9 +4231,9 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq); -void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset) +void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset) { - struct gpio_desc *desc = gpiochip_get_desc(chip, offset); + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); if (!IS_ERR(desc) && !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) @@ -4240,9 +4241,9 @@ void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_disable_irq); -void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset) +void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset) { - struct gpio_desc *desc = gpiochip_get_desc(chip, offset); + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); if (!IS_ERR(desc) && !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) { @@ -4252,63 +4253,63 @@ void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_enable_irq); -bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset) +bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset) { - if (offset >= chip->ngpio) + if (offset >= gc->ngpio) return false; - return test_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); + return test_bit(FLAG_USED_AS_IRQ, &gc->gpiodev->descs[offset].flags); } EXPORT_SYMBOL_GPL(gpiochip_line_is_irq); -int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset) +int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset) { int ret; - if (!try_module_get(chip->gpiodev->owner)) + if (!try_module_get(gc->gpiodev->owner)) return -ENODEV; - ret = gpiochip_lock_as_irq(chip, offset); + ret = gpiochip_lock_as_irq(gc, offset); if (ret) { - chip_err(chip, "unable to lock HW IRQ %u for IRQ\n", offset); - module_put(chip->gpiodev->owner); + chip_err(gc, "unable to lock HW IRQ %u for IRQ\n", offset); + module_put(gc->gpiodev->owner); return ret; } return 0; } EXPORT_SYMBOL_GPL(gpiochip_reqres_irq); -void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset) +void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset) { - gpiochip_unlock_as_irq(chip, offset); - module_put(chip->gpiodev->owner); + gpiochip_unlock_as_irq(gc, offset); + module_put(gc->gpiodev->owner); } EXPORT_SYMBOL_GPL(gpiochip_relres_irq); -bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset) +bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset) { - if (offset >= chip->ngpio) + if (offset >= gc->ngpio) return false; - return test_bit(FLAG_OPEN_DRAIN, &chip->gpiodev->descs[offset].flags); + return test_bit(FLAG_OPEN_DRAIN, &gc->gpiodev->descs[offset].flags); } EXPORT_SYMBOL_GPL(gpiochip_line_is_open_drain); -bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset) +bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset) { - if (offset >= chip->ngpio) + if (offset >= gc->ngpio) return false; - return test_bit(FLAG_OPEN_SOURCE, &chip->gpiodev->descs[offset].flags); + return test_bit(FLAG_OPEN_SOURCE, &gc->gpiodev->descs[offset].flags); } EXPORT_SYMBOL_GPL(gpiochip_line_is_open_source); -bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset) +bool gpiochip_line_is_persistent(struct gpio_chip *gc, unsigned int offset) { - if (offset >= chip->ngpio) + if (offset >= gc->ngpio) return false; - return !test_bit(FLAG_TRANSITORY, &chip->gpiodev->descs[offset].flags); + return !test_bit(FLAG_TRANSITORY, &gc->gpiodev->descs[offset].flags); } EXPORT_SYMBOL_GPL(gpiochip_line_is_persistent); @@ -4546,7 +4547,7 @@ EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table); */ void gpiod_add_hogs(struct gpiod_hog *hogs) { - struct gpio_chip *chip; + struct gpio_chip *gc; struct gpiod_hog *hog; mutex_lock(&gpio_machine_hogs_mutex); @@ -4558,9 +4559,9 @@ void gpiod_add_hogs(struct gpiod_hog *hogs) * The chip may have been registered earlier, so check if it * exists and, if so, try to hog the line now. */ - chip = find_chip_by_name(hog->chip_label); - if (chip) - gpiochip_machine_hog(chip, hog); + gc = find_chip_by_name(hog->chip_label); + if (gc) + gpiochip_machine_hog(gc, hog); } mutex_unlock(&gpio_machine_hogs_mutex); @@ -4610,7 +4611,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return desc; for (p = &table->table[0]; p->chip_label; p++) { - struct gpio_chip *chip; + struct gpio_chip *gc; /* idx must always match exactly */ if (p->idx != idx) @@ -4620,9 +4621,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, if (p->con_id && (!con_id || strcmp(p->con_id, con_id))) continue; - chip = find_chip_by_name(p->chip_label); + gc = find_chip_by_name(p->chip_label); - if (!chip) { + if (!gc) { /* * As the lookup table indicates a chip with * p->chip_label should exist, assume it may @@ -4635,15 +4636,15 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return ERR_PTR(-EPROBE_DEFER); } - if (chip->ngpio <= p->chip_hwnum) { + if (gc->ngpio <= p->chip_hwnum) { dev_err(dev, "requested GPIO %u (%u) is out of range [0..%u] for chip %s\n", - idx, p->chip_hwnum, chip->ngpio - 1, - chip->label); + idx, p->chip_hwnum, gc->ngpio - 1, + gc->label); return ERR_PTR(-EINVAL); } - desc = gpiochip_get_desc(chip, p->chip_hwnum); + desc = gpiochip_get_desc(gc, p->chip_hwnum); *flags = p->flags; return desc; @@ -5038,20 +5039,20 @@ EXPORT_SYMBOL_GPL(gpiod_get_index_optional); int gpiod_hog(struct gpio_desc *desc, const char *name, unsigned long lflags, enum gpiod_flags dflags) { - struct gpio_chip *chip; + struct gpio_chip *gc; struct gpio_desc *local_desc; int hwnum; int ret; - chip = gpiod_to_chip(desc); + gc = gpiod_to_chip(desc); hwnum = gpio_chip_hwgpio(desc); - local_desc = gpiochip_request_own_desc(chip, hwnum, name, + local_desc = gpiochip_request_own_desc(gc, hwnum, name, lflags, dflags); if (IS_ERR(local_desc)) { ret = PTR_ERR(local_desc); pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n", - name, chip->label, hwnum, ret); + name, gc->label, hwnum, ret); return ret; } @@ -5069,15 +5070,15 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, /** * gpiochip_free_hogs - Scan gpio-controller chip and release GPIO hog - * @chip: gpio chip to act on + * @gc: gpio chip to act on */ -static void gpiochip_free_hogs(struct gpio_chip *chip) +static void gpiochip_free_hogs(struct gpio_chip *gc) { int id; - for (id = 0; id < chip->ngpio; id++) { - if (test_bit(FLAG_IS_HOGGED, &chip->gpiodev->descs[id].flags)) - gpiochip_free_own_desc(&chip->gpiodev->descs[id]); + for (id = 0; id < gc->ngpio; id++) { + if (test_bit(FLAG_IS_HOGGED, &gc->gpiodev->descs[id].flags)) + gpiochip_free_own_desc(&gc->gpiodev->descs[id]); } } @@ -5100,7 +5101,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, struct gpio_desc *desc; struct gpio_descs *descs; struct gpio_array *array_info = NULL; - struct gpio_chip *chip; + struct gpio_chip *gc; int count, bitmap_size; count = gpiod_count(dev, con_id); @@ -5120,7 +5121,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, descs->desc[descs->ndescs] = desc; - chip = gpiod_to_chip(desc); + gc = gpiod_to_chip(desc); /* * If pin hardware number of array member 0 is also 0, select * its chip as a candidate for fast bitmap processing path. @@ -5128,8 +5129,8 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, if (descs->ndescs == 0 && gpio_chip_hwgpio(desc) == 0) { struct gpio_descs *array; - bitmap_size = BITS_TO_LONGS(chip->ngpio > count ? - chip->ngpio : count); + bitmap_size = BITS_TO_LONGS(gc->ngpio > count ? + gc->ngpio : count); array = kzalloc(struct_size(descs, desc, count) + struct_size(array_info, invert_mask, @@ -5152,7 +5153,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, array_info->desc = descs->desc; array_info->size = count; - array_info->chip = chip; + array_info->chip = gc; bitmap_set(array_info->get_mask, descs->ndescs, count - descs->ndescs); bitmap_set(array_info->set_mask, descs->ndescs, @@ -5160,7 +5161,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, descs->info = array_info; } /* Unmark array members which don't belong to the 'fast' chip */ - if (array_info && array_info->chip != chip) { + if (array_info && array_info->chip != gc) { __clear_bit(descs->ndescs, array_info->get_mask); __clear_bit(descs->ndescs, array_info->set_mask); } @@ -5185,8 +5186,8 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev, } } else if (array_info) { /* Exclude open drain or open source from fast output */ - if (gpiochip_line_is_open_drain(chip, descs->ndescs) || - gpiochip_line_is_open_source(chip, descs->ndescs)) + if (gpiochip_line_is_open_drain(gc, descs->ndescs) || + gpiochip_line_is_open_source(gc, descs->ndescs)) __clear_bit(descs->ndescs, array_info->set_mask); /* Identify 'fast' pins which require invertion */ @@ -5292,7 +5293,7 @@ core_initcall(gpiolib_dev_init); static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) { unsigned i; - struct gpio_chip *chip = gdev->chip; + struct gpio_chip *gc = gdev->chip; unsigned gpio = gdev->base; struct gpio_desc *gdesc = &gdev->descs[0]; bool is_out; @@ -5315,7 +5316,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s%s", gpio, gdesc->name ? gdesc->name : "", gdesc->label, is_out ? "out" : "in ", - chip->get ? (chip->get(chip, i) ? "hi" : "lo") : "? ", + gc->get ? (gc->get(gc, i) ? "hi" : "lo") : "? ", is_irq ? "IRQ " : "", active_low ? "ACTIVE LOW" : ""); seq_printf(s, "\n"); @@ -5367,10 +5368,10 @@ static void gpiolib_seq_stop(struct seq_file *s, void *v) static int gpiolib_seq_show(struct seq_file *s, void *v) { struct gpio_device *gdev = v; - struct gpio_chip *chip = gdev->chip; + struct gpio_chip *gc = gdev->chip; struct device *parent; - if (!chip) { + if (!gc) { seq_printf(s, "%s%s: (dangling chip)", (char *)s->private, dev_name(&gdev->dev)); return 0; @@ -5379,19 +5380,19 @@ static int gpiolib_seq_show(struct seq_file *s, void *v) seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private, dev_name(&gdev->dev), gdev->base, gdev->base + gdev->ngpio - 1); - parent = chip->parent; + parent = gc->parent; if (parent) seq_printf(s, ", parent: %s/%s", parent->bus ? parent->bus->name : "no-bus", dev_name(parent)); - if (chip->label) - seq_printf(s, ", %s", chip->label); - if (chip->can_sleep) + if (gc->label) + seq_printf(s, ", %s", gc->label); + if (gc->can_sleep) seq_printf(s, ", can sleep"); seq_printf(s, ":\n"); - if (chip->dbg_show) - chip->dbg_show(s, chip); + if (gc->dbg_show) + gc->dbg_show(s, gc); else gpiolib_dbg_show(s, gdev); diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index ed65e00ee977..b8fc92c177eb 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -87,7 +87,7 @@ struct gpio_irq_chip { * @need_valid_mask to make these GPIO lines unavailable for * translation. */ - int (*child_to_parent_hwirq)(struct gpio_chip *chip, + int (*child_to_parent_hwirq)(struct gpio_chip *gc, unsigned int child_hwirq, unsigned int child_type, unsigned int *parent_hwirq, @@ -102,7 +102,7 @@ struct gpio_irq_chip { * variant named &gpiochip_populate_parent_fwspec_fourcell is also * available. */ - void *(*populate_parent_alloc_arg)(struct gpio_chip *chip, + void *(*populate_parent_alloc_arg)(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type); @@ -114,7 +114,7 @@ struct gpio_irq_chip { * callback. If this is not specified, then a default callback will be * provided that returns the line offset. */ - unsigned int (*child_offset_to_irq)(struct gpio_chip *chip, + unsigned int (*child_offset_to_irq)(struct gpio_chip *gc, unsigned int pin); /** @@ -209,7 +209,7 @@ struct gpio_irq_chip { * a particular driver wants to clear IRQ related registers * in order to avoid undesired events. */ - int (*init_hw)(struct gpio_chip *chip); + int (*init_hw)(struct gpio_chip *gc); /** * @init_valid_mask: optional routine to initialize @valid_mask, to be @@ -220,7 +220,7 @@ struct gpio_irq_chip { * then directly set some bits to "0" if they cannot be used for * interrupts. */ - void (*init_valid_mask)(struct gpio_chip *chip, + void (*init_valid_mask)(struct gpio_chip *gc, unsigned long *valid_mask, unsigned int ngpios); @@ -348,40 +348,40 @@ struct gpio_chip { struct device *parent; struct module *owner; - int (*request)(struct gpio_chip *chip, + int (*request)(struct gpio_chip *gc, unsigned offset); - void (*free)(struct gpio_chip *chip, + void (*free)(struct gpio_chip *gc, unsigned offset); - int (*get_direction)(struct gpio_chip *chip, + int (*get_direction)(struct gpio_chip *gc, unsigned offset); - int (*direction_input)(struct gpio_chip *chip, + int (*direction_input)(struct gpio_chip *gc, unsigned offset); - int (*direction_output)(struct gpio_chip *chip, + int (*direction_output)(struct gpio_chip *gc, unsigned offset, int value); - int (*get)(struct gpio_chip *chip, + int (*get)(struct gpio_chip *gc, unsigned offset); - int (*get_multiple)(struct gpio_chip *chip, + int (*get_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits); - void (*set)(struct gpio_chip *chip, + void (*set)(struct gpio_chip *gc, unsigned offset, int value); - void (*set_multiple)(struct gpio_chip *chip, + void (*set_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits); - int (*set_config)(struct gpio_chip *chip, + int (*set_config)(struct gpio_chip *gc, unsigned offset, unsigned long config); - int (*to_irq)(struct gpio_chip *chip, + int (*to_irq)(struct gpio_chip *gc, unsigned offset); void (*dbg_show)(struct seq_file *s, - struct gpio_chip *chip); + struct gpio_chip *gc); - int (*init_valid_mask)(struct gpio_chip *chip, + int (*init_valid_mask)(struct gpio_chip *gc, unsigned long *valid_mask, unsigned int ngpios); - int (*add_pin_ranges)(struct gpio_chip *chip); + int (*add_pin_ranges)(struct gpio_chip *gc); int base; u16 ngpio; @@ -458,11 +458,11 @@ struct gpio_chip { #endif /* CONFIG_OF_GPIO */ }; -extern const char *gpiochip_is_requested(struct gpio_chip *chip, +extern const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned offset); /* add/remove chips */ -extern int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, +extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, struct lock_class_key *lock_key, struct lock_class_key *request_key); @@ -490,43 +490,43 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, * Otherwise it returns zero as a success code. */ #ifdef CONFIG_LOCKDEP -#define gpiochip_add_data(chip, data) ({ \ +#define gpiochip_add_data(gc, data) ({ \ static struct lock_class_key lock_key; \ static struct lock_class_key request_key; \ - gpiochip_add_data_with_key(chip, data, &lock_key, \ + gpiochip_add_data_with_key(gc, data, &lock_key, \ &request_key); \ }) #else -#define gpiochip_add_data(chip, data) gpiochip_add_data_with_key(chip, data, NULL, NULL) +#define gpiochip_add_data(gc, data) gpiochip_add_data_with_key(gc, data, NULL, NULL) #endif /* CONFIG_LOCKDEP */ -static inline int gpiochip_add(struct gpio_chip *chip) +static inline int gpiochip_add(struct gpio_chip *gc) { - return gpiochip_add_data(chip, NULL); + return gpiochip_add_data(gc, NULL); } -extern void gpiochip_remove(struct gpio_chip *chip); -extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip, +extern void gpiochip_remove(struct gpio_chip *gc); +extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc, void *data); extern struct gpio_chip *gpiochip_find(void *data, - int (*match)(struct gpio_chip *chip, void *data)); + int (*match)(struct gpio_chip *gc, void *data)); -bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); -int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_enable_irq(struct gpio_chip *chip, unsigned int offset); +bool gpiochip_line_is_irq(struct gpio_chip *gc, unsigned int offset); +int gpiochip_reqres_irq(struct gpio_chip *gc, unsigned int offset); +void gpiochip_relres_irq(struct gpio_chip *gc, unsigned int offset); +void gpiochip_disable_irq(struct gpio_chip *gc, unsigned int offset); +void gpiochip_enable_irq(struct gpio_chip *gc, unsigned int offset); /* Line status inquiry for drivers */ -bool gpiochip_line_is_open_drain(struct gpio_chip *chip, unsigned int offset); -bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset); +bool gpiochip_line_is_open_drain(struct gpio_chip *gc, unsigned int offset); +bool gpiochip_line_is_open_source(struct gpio_chip *gc, unsigned int offset); /* Sleep persistence inquiry for drivers */ -bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset); -bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); +bool gpiochip_line_is_persistent(struct gpio_chip *gc, unsigned int offset); +bool gpiochip_line_is_valid(const struct gpio_chip *gc, unsigned int offset); /* get driver data */ -void *gpiochip_get_data(struct gpio_chip *chip); +void *gpiochip_get_data(struct gpio_chip *gc); struct bgpio_pdata { const char *label; @@ -536,23 +536,23 @@ struct bgpio_pdata { #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY -void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, +void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type); -void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, +void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type); #else -static inline void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, +static inline void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type) { return NULL; } -static inline void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, +static inline void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, unsigned int parent_hwirq, unsigned int parent_type) { @@ -583,11 +583,11 @@ int gpiochip_irq_domain_activate(struct irq_domain *domain, void gpiochip_irq_domain_deactivate(struct irq_domain *domain, struct irq_data *data); -void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip, +void gpiochip_set_nested_irqchip(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int parent_irq); -int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, +int gpiochip_irqchip_add_key(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int first_irq, irq_flow_handler_t handler, @@ -596,7 +596,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, struct lock_class_key *lock_key, struct lock_class_key *request_key); -bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gc, unsigned int offset); #ifdef CONFIG_LOCKDEP @@ -607,7 +607,7 @@ bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, * boilerplate static inlines provides such a key for each * unique instance. */ -static inline int gpiochip_irqchip_add(struct gpio_chip *gpiochip, +static inline int gpiochip_irqchip_add(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int first_irq, irq_flow_handler_t handler, @@ -616,12 +616,12 @@ static inline int gpiochip_irqchip_add(struct gpio_chip *gpiochip, static struct lock_class_key lock_key; static struct lock_class_key request_key; - return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq, + return gpiochip_irqchip_add_key(gc, irqchip, first_irq, handler, type, false, &lock_key, &request_key); } -static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, +static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int first_irq, irq_flow_handler_t handler, @@ -631,35 +631,35 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, static struct lock_class_key lock_key; static struct lock_class_key request_key; - return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq, + return gpiochip_irqchip_add_key(gc, irqchip, first_irq, handler, type, true, &lock_key, &request_key); } #else /* ! CONFIG_LOCKDEP */ -static inline int gpiochip_irqchip_add(struct gpio_chip *gpiochip, +static inline int gpiochip_irqchip_add(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int first_irq, irq_flow_handler_t handler, unsigned int type) { - return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq, + return gpiochip_irqchip_add_key(gc, irqchip, first_irq, handler, type, false, NULL, NULL); } -static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, +static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gc, struct irq_chip *irqchip, unsigned int first_irq, irq_flow_handler_t handler, unsigned int type) { - return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq, + return gpiochip_irqchip_add_key(gc, irqchip, first_irq, handler, type, true, NULL, NULL); } #endif /* CONFIG_LOCKDEP */ -int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); -void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); -int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, +int gpiochip_generic_request(struct gpio_chip *gc, unsigned offset); +void gpiochip_generic_free(struct gpio_chip *gc, unsigned offset); +int gpiochip_generic_config(struct gpio_chip *gc, unsigned offset, unsigned long config); /** @@ -676,25 +676,25 @@ struct gpio_pin_range { #ifdef CONFIG_PINCTRL -int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, +int gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins); -int gpiochip_add_pingroup_range(struct gpio_chip *chip, +int gpiochip_add_pingroup_range(struct gpio_chip *gc, struct pinctrl_dev *pctldev, unsigned int gpio_offset, const char *pin_group); -void gpiochip_remove_pin_ranges(struct gpio_chip *chip); +void gpiochip_remove_pin_ranges(struct gpio_chip *gc); #else /* ! CONFIG_PINCTRL */ static inline int -gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, +gpiochip_add_pin_range(struct gpio_chip *gc, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins) { return 0; } static inline int -gpiochip_add_pingroup_range(struct gpio_chip *chip, +gpiochip_add_pingroup_range(struct gpio_chip *gc, struct pinctrl_dev *pctldev, unsigned int gpio_offset, const char *pin_group) { @@ -702,27 +702,27 @@ gpiochip_add_pingroup_range(struct gpio_chip *chip, } static inline void -gpiochip_remove_pin_ranges(struct gpio_chip *chip) +gpiochip_remove_pin_ranges(struct gpio_chip *gc) { } #endif /* CONFIG_PINCTRL */ -struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, +struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, unsigned int hwnum, const char *label, enum gpio_lookup_flags lflags, enum gpiod_flags dflags); void gpiochip_free_own_desc(struct gpio_desc *desc); -void devprop_gpiochip_set_names(struct gpio_chip *chip, +void devprop_gpiochip_set_names(struct gpio_chip *gc, const struct fwnode_handle *fwnode); #ifdef CONFIG_GPIOLIB /* lock/unlock as IRQ */ -int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); +int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset); +void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset); struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); @@ -736,14 +736,14 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) return ERR_PTR(-ENODEV); } -static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, +static inline int gpiochip_lock_as_irq(struct gpio_chip *gc, unsigned int offset) { WARN_ON(1); return -EINVAL; } -static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, +static inline void gpiochip_unlock_as_irq(struct gpio_chip *gc, unsigned int offset) { WARN_ON(1); From e45ee71ae101bd271c3cd951cf66341dc8f504a0 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 30 Mar 2020 11:58:01 +0200 Subject: [PATCH 55/59] pinctrl: Define of_pinctrl_get() dummy for !PINCTRL Currently, the of_pinctrl_get() dummy is only defined for !OF, which can still cause build failures on configurations with OF enabled but PINCTRL disabled. Make sure to define the dummy if either OF or PINCTRL are not enabled. Reported-by: Stephen Rothwell Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200330095801.2421589-1-thierry.reding@gmail.com Signed-off-by: Linus Walleij --- include/linux/pinctrl/pinctrl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index 7ce23450a1cb..2aef59df93d7 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -186,7 +186,7 @@ extern int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group, const unsigned **pins, unsigned *num_pins); -#ifdef CONFIG_OF +#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PINCTRL) extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np); #else static inline From 33dd888263199676946f1c789e821d39a9a79d98 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 1 Apr 2020 15:19:04 +1100 Subject: [PATCH 56/59] gpio: export of_pinctrl_get to modules Signed-off-by: Stephen Rothwell Link: https://lore.kernel.org/r/20200401151904.6948af20@canb.auug.org.au Signed-off-by: Linus Walleij --- drivers/pinctrl/devicetree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index 9357f7c46cf3..01f71258f727 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -103,6 +103,7 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np) { return get_pinctrl_dev_from_of_node(np); } +EXPORT_SYMBOL_GPL(of_pinctrl_get); static int dt_to_map_one_config(struct pinctrl *p, struct pinctrl_dev *hog_pctldev, From f0254b51cbbfe040142cb824a1ff623de698ae8a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 1 Apr 2020 22:05:26 +0200 Subject: [PATCH 57/59] gpio: Unconditionally assign .request()/.free() The gpiochip_generic_request() and gpiochip_generic_free() functions can now deal properly with chips that don't have any pin-ranges defined, so they can be assigned unconditionally. Suggested-by: Linus Walleij Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200401200527.2982450-1-thierry.reding@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 7 ++----- drivers/gpio/gpio-mxc.c | 7 ++----- drivers/gpio/gpio-pl061.c | 7 ++----- drivers/gpio/gpio-pxa.c | 7 ++----- drivers/gpio/gpio-zx.c | 10 ++++------ 5 files changed, 12 insertions(+), 26 deletions(-) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index e0b025689625..085b874db2a9 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -259,11 +259,8 @@ static int davinci_gpio_probe(struct platform_device *pdev) chips->chip.of_gpio_n_cells = 2; chips->chip.parent = dev; chips->chip.of_node = dev->of_node; - - if (of_property_read_bool(dev->of_node, "gpio-ranges")) { - chips->chip.request = gpiochip_generic_request; - chips->chip.free = gpiochip_generic_free; - } + chips->chip.request = gpiochip_generic_request; + chips->chip.free = gpiochip_generic_free; #endif spin_lock_init(&chips->lock); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index c77d474185f3..64278a4756f0 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -485,11 +485,8 @@ static int mxc_gpio_probe(struct platform_device *pdev) if (err) goto out_bgio; - if (of_property_read_bool(np, "gpio-ranges")) { - port->gc.request = gpiochip_generic_request; - port->gc.free = gpiochip_generic_free; - } - + port->gc.request = gpiochip_generic_request; + port->gc.free = gpiochip_generic_free; port->gc.to_irq = mxc_gpio_to_irq; port->gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 : pdev->id * 32; diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 3439120f166a..e241fb884c12 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -298,11 +298,8 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(pl061->base); raw_spin_lock_init(&pl061->lock); - if (of_property_read_bool(dev->of_node, "gpio-ranges")) { - pl061->gc.request = gpiochip_generic_request; - pl061->gc.free = gpiochip_generic_free; - } - + pl061->gc.request = gpiochip_generic_request; + pl061->gc.free = gpiochip_generic_free; pl061->gc.base = -1; pl061->gc.get_direction = pl061_get_direction; pl061->gc.direction_input = pl061_direction_input; diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 567742d962ae..1361270ecf8c 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -361,11 +361,8 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, pchip->chip.set = pxa_gpio_set; pchip->chip.to_irq = pxa_gpio_to_irq; pchip->chip.ngpio = ngpio; - - if (pxa_gpio_has_pinctrl()) { - pchip->chip.request = gpiochip_generic_request; - pchip->chip.free = gpiochip_generic_free; - } + pchip->chip.request = gpiochip_generic_request; + pchip->chip.free = gpiochip_generic_free; #ifdef CONFIG_OF_GPIO pchip->chip.of_node = np; diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 98cbaf0e415e..64bfb722756a 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -226,13 +226,11 @@ static int zx_gpio_probe(struct platform_device *pdev) if (IS_ERR(chip->base)) return PTR_ERR(chip->base); - raw_spin_lock_init(&chip->lock); - if (of_property_read_bool(dev->of_node, "gpio-ranges")) { - chip->gc.request = gpiochip_generic_request; - chip->gc.free = gpiochip_generic_free; - } - id = of_alias_get_id(dev->of_node, "gpio"); + + raw_spin_lock_init(&chip->lock); + chip->gc.request = gpiochip_generic_request; + chip->gc.free = gpiochip_generic_free; chip->gc.direction_input = zx_direction_input; chip->gc.direction_output = zx_direction_output; chip->gc.get = zx_get_value; From d6471d6e09d436617c38293b55b6f0326e7a2d68 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 1 Apr 2020 22:05:27 +0200 Subject: [PATCH 58/59] pinctrl: Unconditionally assign .request()/.free() The gpiochip_generic_request() and gpiochip_generic_free() functions can now deal properly with chips that don't have any pin-ranges defined, so they can be assigned unconditionally. Suggested-by: Linus Walleij Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20200401200527.2982450-2-thierry.reding@gmail.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-ingenic.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 96f04d121ebd..bc7f6df850ed 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -2278,11 +2278,8 @@ static int __init ingenic_gpio_probe(struct ingenic_pinctrl *jzpc, jzgc->gc.direction_input = ingenic_gpio_direction_input; jzgc->gc.direction_output = ingenic_gpio_direction_output; jzgc->gc.get_direction = ingenic_gpio_get_direction; - - if (of_property_read_bool(node, "gpio-ranges")) { - jzgc->gc.request = gpiochip_generic_request; - jzgc->gc.free = gpiochip_generic_free; - } + jzgc->gc.request = gpiochip_generic_request; + jzgc->gc.free = gpiochip_generic_free; jzgc->irq = irq_of_parse_and_map(node, 0); if (!jzgc->irq) From 4ed7d7dd4890bb8120a3e77c16191a695fdfcc5a Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Wed, 1 Apr 2020 17:59:25 +0800 Subject: [PATCH 59/59] Revert "gpio: eic-sprd: Use devm_platform_ioremap_resource()" This reverts commit 0f5cb8cc27a266c81e6523b436479802e9aafc9e. This commit will cause below warnings, since our EIC controller can support differnt banks on different Spreadtrum SoCs, and each bank has its own base address, we will get invalid resource warning if the bank number is less than SPRD_EIC_MAX_BANK on some Spreadtrum SoCs. So we should not use devm_platform_ioremap_resource() here to remove the warnings. [ 1.118508] sprd-eic 40210000.gpio: invalid resource [ 1.118535] sprd-eic 40210000.gpio: invalid resource [ 1.119034] sprd-eic 40210080.gpio: invalid resource [ 1.119055] sprd-eic 40210080.gpio: invalid resource [ 1.119462] sprd-eic 402100a0.gpio: invalid resource [ 1.119482] sprd-eic 402100a0.gpio: invalid resource [ 1.119893] sprd-eic 402100c0.gpio: invalid resource [ 1.119913] sprd-eic 402100c0.gpio: invalid resource Signed-off-by: Baolin Wang Link: https://lore.kernel.org/r/8d3579f4b49bb675dc805035960f24852898be28.1585734060.git.baolin.wang7@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-eic-sprd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index bb287f35cf40..8c9757774010 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -569,6 +569,7 @@ static int sprd_eic_probe(struct platform_device *pdev) const struct sprd_eic_variant_data *pdata; struct gpio_irq_chip *irq; struct sprd_eic *sprd_eic; + struct resource *res; int ret, i; pdata = of_device_get_match_data(&pdev->dev); @@ -595,9 +596,13 @@ static int sprd_eic_probe(struct platform_device *pdev) * have one bank EIC, thus base[1] and base[2] can be * optional. */ - sprd_eic->base[i] = devm_platform_ioremap_resource(pdev, i); - if (IS_ERR(sprd_eic->base[i])) + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) continue; + + sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(sprd_eic->base[i])) + return PTR_ERR(sprd_eic->base[i]); } sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type];