2013-10-18 00:21:36 +07:00
|
|
|
#ifndef __LINUX_GPIO_DRIVER_H
|
|
|
|
#define __LINUX_GPIO_DRIVER_H
|
|
|
|
|
2015-10-20 16:10:38 +07:00
|
|
|
#include <linux/device.h>
|
2013-10-18 00:21:36 +07:00
|
|
|
#include <linux/types.h>
|
2013-11-25 16:34:24 +07:00
|
|
|
#include <linux/module.h>
|
2014-03-25 16:40:18 +07:00
|
|
|
#include <linux/irq.h>
|
|
|
|
#include <linux/irqchip/chained_irq.h>
|
|
|
|
#include <linux/irqdomain.h>
|
gpiolib: irqchip: use different lockdep class for each gpio irqchip
Since IRQ chip helpers were introduced drivers lose ability to
register separate lockdep classes for each registered GPIO IRQ
chip and the gpiolib now is using shared lockdep class for
all GPIO IRQ chips (gpiochip_irq_lock_class).
As result, lockdep will produce warning when there are min two
stacked GPIO chips and all of them are interrupt controllers.
HW configuration which generates lockdep warning (TI dra7-evm):
[SOC GPIO bankA.gpioX]
<- irq - [pcf875x.gpioY]
<- irq - DevZ.enable_irq_wake(pcf_gpioY_irq);
The issue was reported in [1] and discussed [2].
=============================================
[ INFO: possible recursive locking detected ]
4.2.0-rc6-00013-g5d050ed-dirty #55 Not tainted
---------------------------------------------
sh/63 is trying to acquire lock:
(class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
but task is already holding lock:
(class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(class);
lock(class);
*** DEADLOCK ***
May be due to missing lock nesting notation
7 locks held by sh/63:
#0: (sb_writers#4){.+.+.+}, at: [<c016bbb8>] vfs_write+0x13c/0x164
#1: (&of->mutex){+.+.+.}, at: [<c01debf4>] kernfs_fop_write+0x4c/0x1a0
#2: (s_active#36){.+.+.+}, at: [<c01debfc>] kernfs_fop_write+0x54/0x1a0
#3: (pm_mutex){+.+.+.}, at: [<c009758c>] pm_suspend+0xec/0x4c4
#4: (&dev->mutex){......}, at: [<c03f77f8>] __device_suspend+0xd4/0x398
#5: (&gpio->lock){+.+.+.}, at: [<c009b940>] __irq_get_desc_lock+0x74/0x94
#6: (class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
stack backtrace:
CPU: 0 PID: 63 Comm: sh Not tainted 4.2.0-rc6-00013-g5d050ed-dirty #55
Hardware name: Generic DRA74X (Flattened Device Tree)
[<c0016e24>] (unwind_backtrace) from [<c0013338>] (show_stack+0x10/0x14)
[<c0013338>] (show_stack) from [<c05f6b24>] (dump_stack+0x84/0x9c)
[<c05f6b24>] (dump_stack) from [<c00903f4>] (__lock_acquire+0x19c0/0x1e20)
[<c00903f4>] (__lock_acquire) from [<c0091098>] (lock_acquire+0xa8/0x128)
[<c0091098>] (lock_acquire) from [<c05fd61c>] (_raw_spin_lock_irqsave+0x38/0x4c)
[<c05fd61c>] (_raw_spin_lock_irqsave) from [<c009b91c>] (__irq_get_desc_lock+0x50/0x94)
[<c009b91c>] (__irq_get_desc_lock) from [<c009c4f4>] (irq_set_irq_wake+0x20/0xfc)
[<c009c4f4>] (irq_set_irq_wake) from [<c0393ac4>] (pcf857x_irq_set_wake+0x24/0x54)
[<c0393ac4>] (pcf857x_irq_set_wake) from [<c009c560>] (irq_set_irq_wake+0x8c/0xfc)
[<c009c560>] (irq_set_irq_wake) from [<c04a02ac>] (gpio_keys_suspend+0x70/0xd4)
[<c04a02ac>] (gpio_keys_suspend) from [<c03f6a00>] (dpm_run_callback+0x50/0x124)
[<c03f6a00>] (dpm_run_callback) from [<c03f7830>] (__device_suspend+0x10c/0x398)
[<c03f7830>] (__device_suspend) from [<c03f90f0>] (dpm_suspend+0x134/0x2f4)
[<c03f90f0>] (dpm_suspend) from [<c0096e20>] (suspend_devices_and_enter+0xa8/0x728)
[<c0096e20>] (suspend_devices_and_enter) from [<c00977cc>] (pm_suspend+0x32c/0x4c4)
[<c00977cc>] (pm_suspend) from [<c0096060>] (state_store+0x64/0xb8)
[<c0096060>] (state_store) from [<c01dec64>] (kernfs_fop_write+0xbc/0x1a0)
[<c01dec64>] (kernfs_fop_write) from [<c016b280>] (__vfs_write+0x20/0xd8)
[<c016b280>] (__vfs_write) from [<c016bb0c>] (vfs_write+0x90/0x164)
[<c016bb0c>] (vfs_write) from [<c016c330>] (SyS_write+0x44/0x9c)
[<c016c330>] (SyS_write) from [<c000f500>] (ret_fast_syscall+0x0/0x54)
Lets fix it by using separate lockdep class for each registered GPIO
IRQ Chip. This is done by wrapping gpiochip_irqchip_add call into macros.
The implementation of this patch inspired by solution done by Nicolas
Boichat for regmap [3]
[1] http://www.spinics.net/lists/linux-gpio/msg05844.html
[2] http://www.spinics.net/lists/linux-gpio/msg06021.html
[3] http://www.spinics.net/lists/arm-kernel/msg429834.html
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Roger Quadros <rogerq@ti.com>
Reported-by: Roger Quadros <rogerq@ti.com>
Tested-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-08-17 19:35:23 +07:00
|
|
|
#include <linux/lockdep.h>
|
2015-03-18 07:56:17 +07:00
|
|
|
#include <linux/pinctrl/pinctrl.h>
|
2015-12-04 20:02:58 +07:00
|
|
|
#include <linux/kconfig.h>
|
2013-10-18 00:21:36 +07:00
|
|
|
|
|
|
|
struct gpio_desc;
|
2013-11-25 16:34:24 +07:00
|
|
|
struct of_phandle_args;
|
|
|
|
struct device_node;
|
2013-10-28 21:06:23 +07:00
|
|
|
struct seq_file;
|
2015-10-20 16:10:38 +07:00
|
|
|
struct gpio_device;
|
2013-10-18 00:21:36 +07:00
|
|
|
|
2014-02-09 15:43:54 +07:00
|
|
|
#ifdef CONFIG_GPIOLIB
|
|
|
|
|
2013-10-18 00:21:36 +07:00
|
|
|
/**
|
|
|
|
* struct gpio_chip - abstract a GPIO controller
|
2016-02-12 20:48:23 +07:00
|
|
|
* @label: a functional name for the GPIO device, such as a part
|
|
|
|
* number or the name of the SoC IP-block implementing it.
|
2015-10-20 16:10:38 +07:00
|
|
|
* @gpiodev: the internal state holder, opaque struct
|
2015-11-04 15:56:26 +07:00
|
|
|
* @parent: optional parent device providing the GPIOs
|
2013-10-18 00:21:36 +07:00
|
|
|
* @owner: helps prevent removal of modules exporting active GPIOs
|
|
|
|
* @request: optional hook for chip-specific activation, such as
|
|
|
|
* enabling module power and clock; may sleep
|
|
|
|
* @free: optional hook for chip-specific deactivation, such as
|
|
|
|
* disabling module power and clock; may sleep
|
|
|
|
* @get_direction: returns direction for signal "offset", 0=out, 1=in,
|
|
|
|
* (same as GPIOF_DIR_XXX), or negative error
|
|
|
|
* @direction_input: configures signal "offset" as input, or returns error
|
|
|
|
* @direction_output: configures signal "offset" as output, or returns error
|
2015-12-22 21:37:28 +07:00
|
|
|
* @get: returns value for signal "offset", 0=low, 1=high, or negative error
|
2013-10-18 00:21:36 +07:00
|
|
|
* @set: assigns output value for signal "offset"
|
2014-11-04 23:12:06 +07:00
|
|
|
* @set_multiple: assigns output values for multiple signals defined by "mask"
|
2013-10-18 00:21:36 +07:00
|
|
|
* @set_debounce: optional hook for setting debounce time for specified gpio in
|
|
|
|
* interrupt triggered gpio chips
|
|
|
|
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
|
|
|
|
* implementation may not sleep
|
|
|
|
* @dbg_show: optional routine to show contents in debugfs; default code
|
|
|
|
* will be used when this is omitted, but custom code can show extra
|
|
|
|
* state (such as pullup/pulldown configuration).
|
2015-05-13 18:03:21 +07:00
|
|
|
* @base: identifies the first GPIO number handled by this chip;
|
|
|
|
* or, if negative during registration, requests dynamic ID allocation.
|
|
|
|
* DEPRECATION: providing anything non-negative and nailing the base
|
2015-06-15 18:31:33 +07:00
|
|
|
* offset of GPIO chips is deprecated. Please pass -1 as base to
|
2015-05-13 18:03:21 +07:00
|
|
|
* let gpiolib select the chip base in all possible cases. We want to
|
|
|
|
* get rid of the static GPIO number space in the long run.
|
2013-10-18 00:21:36 +07:00
|
|
|
* @ngpio: the number of GPIOs handled by this controller; the last GPIO
|
|
|
|
* handled is (base + ngpio - 1).
|
|
|
|
* @names: if set, must be an array of strings to use as alternative
|
|
|
|
* names for the GPIOs in this chip. Any entry in the array
|
|
|
|
* may be NULL if there is no alias for the GPIO, however the
|
|
|
|
* array must be @ngpio entries long. A name can include a single printk
|
|
|
|
* format specifier for an unsigned int. It is substituted by the actual
|
|
|
|
* number of the gpio.
|
2013-12-04 20:42:46 +07:00
|
|
|
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
|
2014-04-09 18:34:39 +07:00
|
|
|
* must while accessing GPIO expander chips over I2C or SPI. This
|
|
|
|
* implies that if the chip supports IRQs, these IRQs need to be threaded
|
|
|
|
* as the chip access may sleep when e.g. reading out the IRQ status
|
|
|
|
* registers.
|
2014-09-20 03:22:44 +07:00
|
|
|
* @irq_not_threaded: flag must be set if @can_sleep is set but the
|
|
|
|
* IRQs don't need to be threaded
|
2015-12-04 20:02:58 +07:00
|
|
|
* @read_reg: reader function for generic GPIO
|
|
|
|
* @write_reg: writer function for generic GPIO
|
|
|
|
* @pin2mask: some generic GPIO controllers work with the big-endian bits
|
|
|
|
* notation, e.g. in a 8-bits register, GPIO7 is the least significant
|
|
|
|
* bit. This callback assigns the right bit mask.
|
|
|
|
* @reg_dat: data (in) register for generic GPIO
|
|
|
|
* @reg_set: output set register (out=high) for generic GPIO
|
|
|
|
* @reg_clk: output clear register (out=low) for generic GPIO
|
|
|
|
* @reg_dir: direction setting register for generic GPIO
|
|
|
|
* @bgpio_bits: number of register bits used for a generic GPIO i.e.
|
|
|
|
* <register width> * 8
|
|
|
|
* @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep
|
|
|
|
* shadowed and real data registers writes together.
|
|
|
|
* @bgpio_data: shadowed data register for generic GPIO to clear/set bits
|
|
|
|
* safely.
|
|
|
|
* @bgpio_dir: shadowed direction register for generic GPIO to clear/set
|
|
|
|
* direction safely.
|
2015-08-17 19:35:24 +07:00
|
|
|
* @irqchip: GPIO IRQ chip impl, provided by GPIO driver
|
|
|
|
* @irqdomain: Interrupt translation domain; responsible for mapping
|
|
|
|
* between GPIO hwirq number and linux irq number
|
|
|
|
* @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated)
|
|
|
|
* @irq_handler: the irq handler to use (often a predefined irq core function)
|
|
|
|
* for GPIO IRQs, provided by GPIO driver
|
|
|
|
* @irq_default_type: default IRQ triggering type applied during GPIO driver
|
|
|
|
* initialization, provided by GPIO driver
|
|
|
|
* @irq_parent: GPIO IRQ chip parent/bank linux irq number,
|
|
|
|
* provided by GPIO driver
|
|
|
|
* @lock_key: per GPIO IRQ chip lockdep class
|
2013-10-18 00:21:36 +07:00
|
|
|
*
|
|
|
|
* A gpio_chip can help platforms abstract various sources of GPIOs so
|
|
|
|
* they can all be accessed through a common programing interface.
|
|
|
|
* Example sources would be SOC controllers, FPGAs, multifunction
|
|
|
|
* chips, dedicated GPIO expanders, and so on.
|
|
|
|
*
|
|
|
|
* Each chip controls a number of signals, identified in method calls
|
|
|
|
* by "offset" values in the range 0..(@ngpio - 1). When those signals
|
|
|
|
* are referenced through calls like gpio_get_value(gpio), the offset
|
|
|
|
* is calculated by subtracting @base from the gpio number.
|
|
|
|
*/
|
|
|
|
struct gpio_chip {
|
|
|
|
const char *label;
|
2015-10-20 16:10:38 +07:00
|
|
|
struct gpio_device *gpiodev;
|
2015-11-04 15:56:26 +07:00
|
|
|
struct device *parent;
|
2013-10-18 00:21:36 +07:00
|
|
|
struct module *owner;
|
|
|
|
|
|
|
|
int (*request)(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
void (*free)(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
int (*get_direction)(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
int (*direction_input)(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
int (*direction_output)(struct gpio_chip *chip,
|
|
|
|
unsigned offset, int value);
|
|
|
|
int (*get)(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
void (*set)(struct gpio_chip *chip,
|
|
|
|
unsigned offset, int value);
|
2014-11-04 23:12:06 +07:00
|
|
|
void (*set_multiple)(struct gpio_chip *chip,
|
|
|
|
unsigned long *mask,
|
|
|
|
unsigned long *bits);
|
2013-10-18 00:21:36 +07:00
|
|
|
int (*set_debounce)(struct gpio_chip *chip,
|
|
|
|
unsigned offset,
|
|
|
|
unsigned debounce);
|
|
|
|
|
|
|
|
int (*to_irq)(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
|
|
|
|
void (*dbg_show)(struct seq_file *s,
|
|
|
|
struct gpio_chip *chip);
|
|
|
|
int base;
|
|
|
|
u16 ngpio;
|
|
|
|
const char *const *names;
|
2013-12-04 20:42:46 +07:00
|
|
|
bool can_sleep;
|
2014-09-20 03:22:44 +07:00
|
|
|
bool irq_not_threaded;
|
2013-10-18 00:21:36 +07:00
|
|
|
|
2015-12-04 20:02:58 +07:00
|
|
|
#if IS_ENABLED(CONFIG_GPIO_GENERIC)
|
|
|
|
unsigned long (*read_reg)(void __iomem *reg);
|
|
|
|
void (*write_reg)(void __iomem *reg, unsigned long data);
|
|
|
|
unsigned long (*pin2mask)(struct gpio_chip *gc, unsigned int pin);
|
|
|
|
void __iomem *reg_dat;
|
|
|
|
void __iomem *reg_set;
|
|
|
|
void __iomem *reg_clr;
|
|
|
|
void __iomem *reg_dir;
|
|
|
|
int bgpio_bits;
|
|
|
|
spinlock_t bgpio_lock;
|
|
|
|
unsigned long bgpio_data;
|
|
|
|
unsigned long bgpio_dir;
|
|
|
|
#endif
|
|
|
|
|
2014-03-25 16:40:18 +07:00
|
|
|
#ifdef CONFIG_GPIOLIB_IRQCHIP
|
|
|
|
/*
|
2014-09-05 18:09:25 +07:00
|
|
|
* With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
|
2014-03-25 16:40:18 +07:00
|
|
|
* to handle IRQs for most practical cases.
|
|
|
|
*/
|
|
|
|
struct irq_chip *irqchip;
|
|
|
|
struct irq_domain *irqdomain;
|
2014-03-29 02:42:01 +07:00
|
|
|
unsigned int irq_base;
|
2014-03-25 16:40:18 +07:00
|
|
|
irq_flow_handler_t irq_handler;
|
|
|
|
unsigned int irq_default_type;
|
2015-05-13 00:12:23 +07:00
|
|
|
int irq_parent;
|
gpiolib: irqchip: use different lockdep class for each gpio irqchip
Since IRQ chip helpers were introduced drivers lose ability to
register separate lockdep classes for each registered GPIO IRQ
chip and the gpiolib now is using shared lockdep class for
all GPIO IRQ chips (gpiochip_irq_lock_class).
As result, lockdep will produce warning when there are min two
stacked GPIO chips and all of them are interrupt controllers.
HW configuration which generates lockdep warning (TI dra7-evm):
[SOC GPIO bankA.gpioX]
<- irq - [pcf875x.gpioY]
<- irq - DevZ.enable_irq_wake(pcf_gpioY_irq);
The issue was reported in [1] and discussed [2].
=============================================
[ INFO: possible recursive locking detected ]
4.2.0-rc6-00013-g5d050ed-dirty #55 Not tainted
---------------------------------------------
sh/63 is trying to acquire lock:
(class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
but task is already holding lock:
(class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(class);
lock(class);
*** DEADLOCK ***
May be due to missing lock nesting notation
7 locks held by sh/63:
#0: (sb_writers#4){.+.+.+}, at: [<c016bbb8>] vfs_write+0x13c/0x164
#1: (&of->mutex){+.+.+.}, at: [<c01debf4>] kernfs_fop_write+0x4c/0x1a0
#2: (s_active#36){.+.+.+}, at: [<c01debfc>] kernfs_fop_write+0x54/0x1a0
#3: (pm_mutex){+.+.+.}, at: [<c009758c>] pm_suspend+0xec/0x4c4
#4: (&dev->mutex){......}, at: [<c03f77f8>] __device_suspend+0xd4/0x398
#5: (&gpio->lock){+.+.+.}, at: [<c009b940>] __irq_get_desc_lock+0x74/0x94
#6: (class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
stack backtrace:
CPU: 0 PID: 63 Comm: sh Not tainted 4.2.0-rc6-00013-g5d050ed-dirty #55
Hardware name: Generic DRA74X (Flattened Device Tree)
[<c0016e24>] (unwind_backtrace) from [<c0013338>] (show_stack+0x10/0x14)
[<c0013338>] (show_stack) from [<c05f6b24>] (dump_stack+0x84/0x9c)
[<c05f6b24>] (dump_stack) from [<c00903f4>] (__lock_acquire+0x19c0/0x1e20)
[<c00903f4>] (__lock_acquire) from [<c0091098>] (lock_acquire+0xa8/0x128)
[<c0091098>] (lock_acquire) from [<c05fd61c>] (_raw_spin_lock_irqsave+0x38/0x4c)
[<c05fd61c>] (_raw_spin_lock_irqsave) from [<c009b91c>] (__irq_get_desc_lock+0x50/0x94)
[<c009b91c>] (__irq_get_desc_lock) from [<c009c4f4>] (irq_set_irq_wake+0x20/0xfc)
[<c009c4f4>] (irq_set_irq_wake) from [<c0393ac4>] (pcf857x_irq_set_wake+0x24/0x54)
[<c0393ac4>] (pcf857x_irq_set_wake) from [<c009c560>] (irq_set_irq_wake+0x8c/0xfc)
[<c009c560>] (irq_set_irq_wake) from [<c04a02ac>] (gpio_keys_suspend+0x70/0xd4)
[<c04a02ac>] (gpio_keys_suspend) from [<c03f6a00>] (dpm_run_callback+0x50/0x124)
[<c03f6a00>] (dpm_run_callback) from [<c03f7830>] (__device_suspend+0x10c/0x398)
[<c03f7830>] (__device_suspend) from [<c03f90f0>] (dpm_suspend+0x134/0x2f4)
[<c03f90f0>] (dpm_suspend) from [<c0096e20>] (suspend_devices_and_enter+0xa8/0x728)
[<c0096e20>] (suspend_devices_and_enter) from [<c00977cc>] (pm_suspend+0x32c/0x4c4)
[<c00977cc>] (pm_suspend) from [<c0096060>] (state_store+0x64/0xb8)
[<c0096060>] (state_store) from [<c01dec64>] (kernfs_fop_write+0xbc/0x1a0)
[<c01dec64>] (kernfs_fop_write) from [<c016b280>] (__vfs_write+0x20/0xd8)
[<c016b280>] (__vfs_write) from [<c016bb0c>] (vfs_write+0x90/0x164)
[<c016bb0c>] (vfs_write) from [<c016c330>] (SyS_write+0x44/0x9c)
[<c016c330>] (SyS_write) from [<c000f500>] (ret_fast_syscall+0x0/0x54)
Lets fix it by using separate lockdep class for each registered GPIO
IRQ Chip. This is done by wrapping gpiochip_irqchip_add call into macros.
The implementation of this patch inspired by solution done by Nicolas
Boichat for regmap [3]
[1] http://www.spinics.net/lists/linux-gpio/msg05844.html
[2] http://www.spinics.net/lists/linux-gpio/msg06021.html
[3] http://www.spinics.net/lists/arm-kernel/msg429834.html
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Roger Quadros <rogerq@ti.com>
Reported-by: Roger Quadros <rogerq@ti.com>
Tested-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-08-17 19:35:23 +07:00
|
|
|
struct lock_class_key *lock_key;
|
2014-03-25 16:40:18 +07:00
|
|
|
#endif
|
|
|
|
|
2013-10-18 00:21:36 +07:00
|
|
|
#if defined(CONFIG_OF_GPIO)
|
|
|
|
/*
|
|
|
|
* If CONFIG_OF is enabled, then all GPIO controllers described in the
|
|
|
|
* device tree automatically may have an OF translation
|
|
|
|
*/
|
|
|
|
struct device_node *of_node;
|
|
|
|
int of_gpio_n_cells;
|
|
|
|
int (*of_xlate)(struct gpio_chip *gc,
|
|
|
|
const struct of_phandle_args *gpiospec, u32 *flags);
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
|
|
|
|
unsigned offset);
|
|
|
|
|
|
|
|
/* add/remove chips */
|
2015-12-03 21:14:13 +07:00
|
|
|
extern int gpiochip_add_data(struct gpio_chip *chip, void *data);
|
|
|
|
static inline int gpiochip_add(struct gpio_chip *chip)
|
|
|
|
{
|
|
|
|
return gpiochip_add_data(chip, NULL);
|
|
|
|
}
|
2014-07-05 23:28:50 +07:00
|
|
|
extern void gpiochip_remove(struct gpio_chip *chip);
|
2016-02-15 18:02:09 +07:00
|
|
|
extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
|
|
|
|
void *data);
|
|
|
|
extern void devm_gpiochip_remove(struct device *dev, struct gpio_chip *chip);
|
|
|
|
|
2013-10-18 00:21:36 +07:00
|
|
|
extern struct gpio_chip *gpiochip_find(void *data,
|
|
|
|
int (*match)(struct gpio_chip *chip, void *data));
|
|
|
|
|
|
|
|
/* lock/unlock as IRQ */
|
2014-10-23 15:27:07 +07:00
|
|
|
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
|
|
|
|
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
|
2016-02-12 02:16:45 +07:00
|
|
|
bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset);
|
2013-10-18 00:21:36 +07:00
|
|
|
|
2016-02-16 21:41:42 +07:00
|
|
|
/* 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);
|
|
|
|
|
2015-12-03 21:14:13 +07:00
|
|
|
/* get driver data */
|
2016-02-11 17:37:48 +07:00
|
|
|
void *gpiochip_get_data(struct gpio_chip *chip);
|
2015-12-03 21:14:13 +07:00
|
|
|
|
2014-02-09 15:43:54 +07:00
|
|
|
struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
|
|
|
|
|
2015-12-04 20:02:58 +07:00
|
|
|
struct bgpio_pdata {
|
|
|
|
const char *label;
|
|
|
|
int base;
|
|
|
|
int ngpio;
|
|
|
|
};
|
|
|
|
|
2016-01-10 04:16:42 +07:00
|
|
|
#if IS_ENABLED(CONFIG_GPIO_GENERIC)
|
|
|
|
|
2015-12-04 20:02:58 +07:00
|
|
|
int bgpio_init(struct gpio_chip *gc, struct device *dev,
|
|
|
|
unsigned long sz, void __iomem *dat, void __iomem *set,
|
|
|
|
void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
|
|
|
|
unsigned long flags);
|
|
|
|
|
|
|
|
#define BGPIOF_BIG_ENDIAN BIT(0)
|
|
|
|
#define BGPIOF_UNREADABLE_REG_SET BIT(1) /* reg_set is unreadable */
|
|
|
|
#define BGPIOF_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */
|
|
|
|
#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 */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2014-03-25 16:40:18 +07:00
|
|
|
#ifdef CONFIG_GPIOLIB_IRQCHIP
|
|
|
|
|
|
|
|
void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|
|
|
struct irq_chip *irqchip,
|
|
|
|
int parent_irq,
|
|
|
|
irq_flow_handler_t parent_handler);
|
|
|
|
|
gpiolib: irqchip: use different lockdep class for each gpio irqchip
Since IRQ chip helpers were introduced drivers lose ability to
register separate lockdep classes for each registered GPIO IRQ
chip and the gpiolib now is using shared lockdep class for
all GPIO IRQ chips (gpiochip_irq_lock_class).
As result, lockdep will produce warning when there are min two
stacked GPIO chips and all of them are interrupt controllers.
HW configuration which generates lockdep warning (TI dra7-evm):
[SOC GPIO bankA.gpioX]
<- irq - [pcf875x.gpioY]
<- irq - DevZ.enable_irq_wake(pcf_gpioY_irq);
The issue was reported in [1] and discussed [2].
=============================================
[ INFO: possible recursive locking detected ]
4.2.0-rc6-00013-g5d050ed-dirty #55 Not tainted
---------------------------------------------
sh/63 is trying to acquire lock:
(class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
but task is already holding lock:
(class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(class);
lock(class);
*** DEADLOCK ***
May be due to missing lock nesting notation
7 locks held by sh/63:
#0: (sb_writers#4){.+.+.+}, at: [<c016bbb8>] vfs_write+0x13c/0x164
#1: (&of->mutex){+.+.+.}, at: [<c01debf4>] kernfs_fop_write+0x4c/0x1a0
#2: (s_active#36){.+.+.+}, at: [<c01debfc>] kernfs_fop_write+0x54/0x1a0
#3: (pm_mutex){+.+.+.}, at: [<c009758c>] pm_suspend+0xec/0x4c4
#4: (&dev->mutex){......}, at: [<c03f77f8>] __device_suspend+0xd4/0x398
#5: (&gpio->lock){+.+.+.}, at: [<c009b940>] __irq_get_desc_lock+0x74/0x94
#6: (class){......}, at: [<c009b91c>] __irq_get_desc_lock+0x50/0x94
stack backtrace:
CPU: 0 PID: 63 Comm: sh Not tainted 4.2.0-rc6-00013-g5d050ed-dirty #55
Hardware name: Generic DRA74X (Flattened Device Tree)
[<c0016e24>] (unwind_backtrace) from [<c0013338>] (show_stack+0x10/0x14)
[<c0013338>] (show_stack) from [<c05f6b24>] (dump_stack+0x84/0x9c)
[<c05f6b24>] (dump_stack) from [<c00903f4>] (__lock_acquire+0x19c0/0x1e20)
[<c00903f4>] (__lock_acquire) from [<c0091098>] (lock_acquire+0xa8/0x128)
[<c0091098>] (lock_acquire) from [<c05fd61c>] (_raw_spin_lock_irqsave+0x38/0x4c)
[<c05fd61c>] (_raw_spin_lock_irqsave) from [<c009b91c>] (__irq_get_desc_lock+0x50/0x94)
[<c009b91c>] (__irq_get_desc_lock) from [<c009c4f4>] (irq_set_irq_wake+0x20/0xfc)
[<c009c4f4>] (irq_set_irq_wake) from [<c0393ac4>] (pcf857x_irq_set_wake+0x24/0x54)
[<c0393ac4>] (pcf857x_irq_set_wake) from [<c009c560>] (irq_set_irq_wake+0x8c/0xfc)
[<c009c560>] (irq_set_irq_wake) from [<c04a02ac>] (gpio_keys_suspend+0x70/0xd4)
[<c04a02ac>] (gpio_keys_suspend) from [<c03f6a00>] (dpm_run_callback+0x50/0x124)
[<c03f6a00>] (dpm_run_callback) from [<c03f7830>] (__device_suspend+0x10c/0x398)
[<c03f7830>] (__device_suspend) from [<c03f90f0>] (dpm_suspend+0x134/0x2f4)
[<c03f90f0>] (dpm_suspend) from [<c0096e20>] (suspend_devices_and_enter+0xa8/0x728)
[<c0096e20>] (suspend_devices_and_enter) from [<c00977cc>] (pm_suspend+0x32c/0x4c4)
[<c00977cc>] (pm_suspend) from [<c0096060>] (state_store+0x64/0xb8)
[<c0096060>] (state_store) from [<c01dec64>] (kernfs_fop_write+0xbc/0x1a0)
[<c01dec64>] (kernfs_fop_write) from [<c016b280>] (__vfs_write+0x20/0xd8)
[<c016b280>] (__vfs_write) from [<c016bb0c>] (vfs_write+0x90/0x164)
[<c016bb0c>] (vfs_write) from [<c016c330>] (SyS_write+0x44/0x9c)
[<c016c330>] (SyS_write) from [<c000f500>] (ret_fast_syscall+0x0/0x54)
Lets fix it by using separate lockdep class for each registered GPIO
IRQ Chip. This is done by wrapping gpiochip_irqchip_add call into macros.
The implementation of this patch inspired by solution done by Nicolas
Boichat for regmap [3]
[1] http://www.spinics.net/lists/linux-gpio/msg05844.html
[2] http://www.spinics.net/lists/linux-gpio/msg06021.html
[3] http://www.spinics.net/lists/arm-kernel/msg429834.html
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Roger Quadros <rogerq@ti.com>
Reported-by: Roger Quadros <rogerq@ti.com>
Tested-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-08-17 19:35:23 +07:00
|
|
|
int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
|
|
|
|
struct irq_chip *irqchip,
|
|
|
|
unsigned int first_irq,
|
|
|
|
irq_flow_handler_t handler,
|
|
|
|
unsigned int type,
|
|
|
|
struct lock_class_key *lock_key);
|
|
|
|
|
|
|
|
#ifdef CONFIG_LOCKDEP
|
|
|
|
#define gpiochip_irqchip_add(...) \
|
|
|
|
( \
|
|
|
|
({ \
|
|
|
|
static struct lock_class_key _key; \
|
|
|
|
_gpiochip_irqchip_add(__VA_ARGS__, &_key); \
|
|
|
|
}) \
|
|
|
|
)
|
|
|
|
#else
|
|
|
|
#define gpiochip_irqchip_add(...) \
|
|
|
|
_gpiochip_irqchip_add(__VA_ARGS__, NULL)
|
|
|
|
#endif
|
2014-03-25 16:40:18 +07:00
|
|
|
|
2014-09-05 18:09:25 +07:00
|
|
|
#endif /* CONFIG_GPIOLIB_IRQCHIP */
|
2014-03-25 16:40:18 +07:00
|
|
|
|
2015-10-11 22:34:15 +07:00
|
|
|
int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset);
|
|
|
|
void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset);
|
|
|
|
|
2015-03-18 07:56:17 +07:00
|
|
|
#ifdef CONFIG_PINCTRL
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct gpio_pin_range - pin range controlled by a gpio chip
|
|
|
|
* @head: list for maintaining set of pin ranges, used internally
|
|
|
|
* @pctldev: pinctrl device which handles corresponding pins
|
|
|
|
* @range: actual range of pins controlled by a gpio controller
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct gpio_pin_range {
|
|
|
|
struct list_head node;
|
|
|
|
struct pinctrl_dev *pctldev;
|
|
|
|
struct pinctrl_gpio_range range;
|
|
|
|
};
|
|
|
|
|
|
|
|
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
|
|
|
|
unsigned int gpio_offset, unsigned int pin_offset,
|
|
|
|
unsigned int npins);
|
|
|
|
int gpiochip_add_pingroup_range(struct gpio_chip *chip,
|
|
|
|
struct pinctrl_dev *pctldev,
|
|
|
|
unsigned int gpio_offset, const char *pin_group);
|
|
|
|
void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
gpiochip_add_pin_range(struct gpio_chip *chip, 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,
|
|
|
|
struct pinctrl_dev *pctldev,
|
|
|
|
unsigned int gpio_offset, const char *pin_group)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_PINCTRL */
|
|
|
|
|
2014-08-20 00:06:09 +07:00
|
|
|
struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum,
|
|
|
|
const char *label);
|
2014-07-22 22:01:01 +07:00
|
|
|
void gpiochip_free_own_desc(struct gpio_desc *desc);
|
|
|
|
|
2014-02-09 15:43:54 +07:00
|
|
|
#else /* CONFIG_GPIOLIB */
|
|
|
|
|
|
|
|
static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
|
|
|
|
{
|
|
|
|
/* GPIO can never have been requested */
|
|
|
|
WARN_ON(1);
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_GPIOLIB */
|
|
|
|
|
2013-10-18 00:21:36 +07:00
|
|
|
#endif
|