From 63c4acfb8031fbcd50cf51cb94aaadc816d99c7c Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Tue, 11 May 2021 07:05:08 +0200 Subject: [PATCH 01/57] dt-bindings: gpio: convert rk3328-grf-gpio.txt to YAML Current dts files with RK3328 GRF 'gpio' nodes are manually verified. In order to automate this process rk3328-grf-gpio.txt has to be converted to YAML. Rename 'grf-gpio' nodename to 'gpio'. Signed-off-by: Johan Jonker Reviewed-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- .../gpio/rockchip,rk3328-grf-gpio.txt | 32 ------------ .../gpio/rockchip,rk3328-grf-gpio.yaml | 50 +++++++++++++++++++ 2 files changed, 50 insertions(+), 32 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt create mode 100644 Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml diff --git a/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt b/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt deleted file mode 100644 index f9231df17c2b..000000000000 --- a/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt +++ /dev/null @@ -1,32 +0,0 @@ -Rockchip RK3328 GRF (General Register Files) GPIO controller. - -In Rockchip RK3328, the output only GPIO_MUTE pin, originally for codec mute -control, can also be used for general purpose. It is manipulated by the -GRF_SOC_CON10 register in GRF. Aside from the GPIO_MUTE pin, the HDMI pins can -also be set in the same way. - -Currently this GPIO controller only supports the mute pin. If needed in the -future, the HDMI pins support can also be added. - -Required properties: -- compatible: Should contain "rockchip,rk3328-grf-gpio". -- gpio-controller: Marks the device node as a gpio controller. -- #gpio-cells: Should be 2. The first cell is the pin number and - the second cell is used to specify the gpio polarity: - 0 = Active high, - 1 = Active low. - -Example: - - grf: syscon@ff100000 { - compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd"; - - grf_gpio: grf-gpio { - compatible = "rockchip,rk3328-grf-gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - -Note: The grf_gpio node should be declared as the child of the GRF (General -Register File) node. The GPIO_MUTE pin is referred to as <&grf_gpio 0>. diff --git a/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml b/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml new file mode 100644 index 000000000000..d8cce73ea0ae --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/rockchip,rk3328-grf-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3328 General Register Files GPIO controller + +description: + The Rockchip RK3328 General Register File (GRF) outputs only the + GPIO_MUTE pin, originally for codec mute control, but it can also be used + for general purpose. It is manipulated by the GRF_SOC_CON10 register. + If needed in the future support for the HDMI pins can also be added. + The GPIO node should be declared as the child of the GRF node. + + The GPIO_MUTE pin is referred to in the format + + <&grf_gpio 0 GPIO_ACTIVE_LOW> + + The first cell is the pin number and + the second cell is used to specify the GPIO polarity + 0 = Active high + 1 = Active low + +maintainers: + - Heiko Stuebner + +properties: + compatible: + const: rockchip,rk3328-grf-gpio + + gpio-controller: true + + "#gpio-cells": + const: 2 + +required: + - compatible + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + grf_gpio: gpio { + compatible = "rockchip,rk3328-grf-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; From c35fb576652dfa1c9692f0a2701b37d813ea75af Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 11 May 2021 18:06:46 +0800 Subject: [PATCH 02/57] gpio: logicvc: Remove redundant error printing in logicvc_gpio_probe() When devm_ioremap_resource() fails, a clear enough error message will be printed by its subfunction __devm_ioremap_resource(). The error information contains the device name, failure cause, and possibly resource information. Therefore, remove the error printing here to simplify code and reduce the binary size. Reported-by: Hulk Robot Signed-off-by: Zhen Lei Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-logicvc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-logicvc.c b/drivers/gpio/gpio-logicvc.c index 015632cf159f..992cc958a43f 100644 --- a/drivers/gpio/gpio-logicvc.c +++ b/drivers/gpio/gpio-logicvc.c @@ -114,10 +114,8 @@ static int logicvc_gpio_probe(struct platform_device *pdev) } base = devm_ioremap_resource(dev, &res); - if (IS_ERR(base)) { - dev_err(dev, "Failed to map I/O base\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } logicvc_gpio_regmap_config.max_register = resource_size(&res) - logicvc_gpio_regmap_config.reg_stride; From e7d8fde4ab50bfe354c4a1a55096b408ce0ffcec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 May 2021 22:52:52 +0300 Subject: [PATCH 03/57] gpio: mockup: Switch to use gpiochip_get_desc() Switch to use gpiochip_get_desc() helper. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mockup.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index d7e73876a3b9..0a9d746a0fe0 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -144,12 +144,9 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, unsigned int offset, int value) { + struct gpio_chip *gc = &chip->gc; + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); int curr, irq, irq_type, ret = 0; - struct gpio_desc *desc; - struct gpio_chip *gc; - - gc = &chip->gc; - desc = &gc->gpiodev->descs[offset]; mutex_lock(&chip->lock); @@ -369,7 +366,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, priv->chip = chip; priv->offset = i; - priv->desc = &gc->gpiodev->descs[i]; + priv->desc = gpiochip_get_desc(gc, i); debugfs_create_file(name, 0200, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); From f2e03ca3e839e2a2d80c4c764ab07b293ad5a576 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 May 2021 22:52:21 +0300 Subject: [PATCH 04/57] gpiolib: Drop duplicate offset check in gpiochip_is_requested() gpiochip_get_desc() already does the check, drop a duplicate in gpiochip_is_requested(). Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1427c1be749b..220a9d8dd4e3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2004,9 +2004,6 @@ const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; - if (offset >= gc->ngpio) - return NULL; - desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return NULL; From cde3d0f81e67f21f1f61fd895255f2e3b86f5bed Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 May 2021 22:46:29 +0300 Subject: [PATCH 05/57] bitmap: Make bitmap_remap() and bitmap_bitremap() available to users Currently the bitmap_remap() and bitmap_bitremap() are available only for CONFIG_NUMA=y case, while some users may benefit out of it and being independent to NUMA code. Make them available to users by moving out of ifdeffery and exporting for modules. Signed-off-by: Andy Shevchenko Tested-by: Neeli Srinivas Acked-by: Yury Norov Signed-off-by: Bartosz Golaszewski --- lib/bitmap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/bitmap.c b/lib/bitmap.c index 74ceb02f45e3..7b6b2a67a6a6 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -784,8 +784,6 @@ int bitmap_parse(const char *start, unsigned int buflen, } EXPORT_SYMBOL(bitmap_parse); - -#ifdef CONFIG_NUMA /** * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap * @buf: pointer to a bitmap @@ -894,6 +892,7 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src, set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst); } } +EXPORT_SYMBOL(bitmap_remap); /** * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit @@ -931,7 +930,9 @@ int bitmap_bitremap(int oldbit, const unsigned long *old, else return bitmap_ord_to_pos(new, n % w, bits); } +EXPORT_SYMBOL(bitmap_bitremap); +#ifdef CONFIG_NUMA /** * bitmap_onto - translate one bitmap relative to another * @dst: resulting translated bitmap From 043aa3db1cbb51251849c262c4c549b665ad93de Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 May 2021 22:46:31 +0300 Subject: [PATCH 06/57] gpio: xilinx: Introduce xgpio_read_chan() / xgpio_write_chan() With the new helpers, i.e. xgpio_read_chan() / xgpio_write_chan(), the code is easier to read and maintain. No functional changes intended. Signed-off-by: Andy Shevchenko Tested-by: Neeli Srinivas Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xilinx.c | 68 +++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index b411d3156e0b..5828743a9f1d 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -23,7 +23,8 @@ #define XGPIO_DATA_OFFSET (0x0) /* Data register */ #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ -#define XGPIO_CHANNEL_OFFSET 0x8 +#define XGPIO_CHANNEL0_OFFSET 0x0 +#define XGPIO_CHANNEL1_OFFSET 0x8 #define XGPIO_GIER_OFFSET 0x11c /* Global Interrupt Enable */ #define XGPIO_GIER_IE BIT(31) @@ -79,12 +80,26 @@ static inline int xgpio_index(struct xgpio_instance *chip, int gpio) return 0; } -static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio) +static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch) { - if (xgpio_index(chip, gpio)) - return XGPIO_CHANNEL_OFFSET; + switch (ch) { + case 0: + return XGPIO_CHANNEL0_OFFSET; + case 1: + return XGPIO_CHANNEL1_OFFSET; + default: + return -EINVAL; + } +} - return 0; +static inline u32 xgpio_read_chan(struct xgpio_instance *chip, int reg, int ch) +{ + return xgpio_readreg(chip->regs + reg + xgpio_regoffset(chip, ch)); +} + +static inline void xgpio_write_chan(struct xgpio_instance *chip, int reg, int ch, u32 v) +{ + xgpio_writereg(chip->regs + reg + xgpio_regoffset(chip, ch), v); } static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) @@ -109,12 +124,13 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct xgpio_instance *chip = gpiochip_get_data(gc); + int index = xgpio_index(chip, gpio); + int offset = xgpio_offset(chip, gpio); u32 val; - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio)); + val = xgpio_read_chan(chip, XGPIO_DATA_OFFSET, index); - return !!(val & BIT(xgpio_offset(chip, gpio))); + return !!(val & BIT(offset)); } /** @@ -141,8 +157,7 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) else chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, chip->gpio_state[index]); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -172,9 +187,8 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, break; /* Once finished with an index write it out to the register */ if (index != xgpio_index(chip, i)) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, - chip->gpio_state[index]); + xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, + chip->gpio_state[index]); spin_unlock_irqrestore(&chip->gpio_lock, flags); index = xgpio_index(chip, i); spin_lock_irqsave(&chip->gpio_lock, flags); @@ -188,8 +202,7 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, } } - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, chip->gpio_state[index]); + xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, chip->gpio_state[index]); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -214,8 +227,7 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) /* Set the GPIO bit in shadow register and set direction as input */ chip->gpio_dir[index] |= BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + xgpio_write_chan(chip, XGPIO_TRI_OFFSET, index, chip->gpio_dir[index]); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -248,13 +260,11 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) chip->gpio_state[index] |= BIT(offset); else chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, chip->gpio_state[index]); /* Clear the GPIO bit in shadow register and set direction as output */ chip->gpio_dir[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + xgpio_write_chan(chip, XGPIO_TRI_OFFSET, index, chip->gpio_dir[index]); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -267,16 +277,14 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) */ static void xgpio_save_regs(struct xgpio_instance *chip) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); + xgpio_write_chan(chip, XGPIO_DATA_OFFSET, 0, chip->gpio_state[0]); + xgpio_write_chan(chip, XGPIO_TRI_OFFSET, 0, chip->gpio_dir[0]); if (!chip->gpio_width[1]) return; - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_state[1]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_dir[1]); + xgpio_write_chan(chip, XGPIO_DATA_OFFSET, 1, chip->gpio_state[1]); + xgpio_write_chan(chip, XGPIO_TRI_OFFSET, 1, chip->gpio_dir[1]); } static int xgpio_request(struct gpio_chip *chip, unsigned int offset) @@ -434,8 +442,7 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); /* Update GPIO IRQ read data before enabling interrupt*/ - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); + val = xgpio_read_chan(chip, XGPIO_DATA_OFFSET, index); chip->gpio_last_irq_read[index] = val; /* Enable per channel interrupt */ @@ -512,8 +519,7 @@ static void xgpio_irqhandler(struct irq_desc *desc) unsigned int irq; spin_lock_irqsave(&chip->gpio_lock, flags); - data = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); + data = xgpio_read_chan(chip, XGPIO_DATA_OFFSET, index); rising_events = data & ~chip->gpio_last_irq_read[index] & chip->irq_enable[index] & From 02b3f84d9080b0f4297f31258307f626a43faba5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 May 2021 22:46:32 +0300 Subject: [PATCH 07/57] gpio: xilinx: Switch to use bitmap APIs It seems that Xilinx GPIO driver operates with bit arrays longer than 32 and thus can leverage bitmap APIs for that. It makes code better to understand. The ->probe() function is modified to try read properties for both channels since is_dual check makes only sense for the amount of pins used for the second channel. On top of that kzalloc() guarantees zero initial values for the fields in the private data structure, hence drop unneeded conditionals and assignments. The change is inspired by Syed Nayyar Waris' ideas about bitmap API extension. Signed-off-by: Andy Shevchenko Tested-by: Neeli Srinivas Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xilinx.c | 352 ++++++++++++++++++------------------- 1 file changed, 176 insertions(+), 176 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 5828743a9f1d..01e6459b27e6 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -5,6 +5,7 @@ * Copyright 2008 - 2013 Xilinx, Inc. */ +#include #include #include #include @@ -44,40 +45,61 @@ * struct xgpio_instance - Stores information about GPIO device * @gc: GPIO chip * @regs: register block - * @gpio_width: GPIO width for every channel - * @gpio_state: GPIO write state shadow register - * @gpio_last_irq_read: GPIO read state register from last interrupt - * @gpio_dir: GPIO direction shadow register + * @hw_map: GPIO pin mapping on hardware side + * @sw_map: GPIO pin mapping on software side + * @state: GPIO write state shadow register + * @last_irq_read: GPIO read state register from last interrupt + * @dir: GPIO direction shadow register * @gpio_lock: Lock used for synchronization * @irq: IRQ used by GPIO device * @irqchip: IRQ chip - * @irq_enable: GPIO IRQ enable/disable bitfield - * @irq_rising_edge: GPIO IRQ rising edge enable/disable bitfield - * @irq_falling_edge: GPIO IRQ falling edge enable/disable bitfield + * @enable: GPIO IRQ enable/disable bitfield + * @rising_edge: GPIO IRQ rising edge enable/disable bitfield + * @falling_edge: GPIO IRQ falling edge enable/disable bitfield * @clk: clock resource for this driver */ struct xgpio_instance { struct gpio_chip gc; void __iomem *regs; - unsigned int gpio_width[2]; - u32 gpio_state[2]; - u32 gpio_last_irq_read[2]; - u32 gpio_dir[2]; + DECLARE_BITMAP(hw_map, 64); + DECLARE_BITMAP(sw_map, 64); + DECLARE_BITMAP(state, 64); + DECLARE_BITMAP(last_irq_read, 64); + DECLARE_BITMAP(dir, 64); spinlock_t gpio_lock; /* For serializing operations */ int irq; struct irq_chip irqchip; - u32 irq_enable[2]; - u32 irq_rising_edge[2]; - u32 irq_falling_edge[2]; + DECLARE_BITMAP(enable, 64); + DECLARE_BITMAP(rising_edge, 64); + DECLARE_BITMAP(falling_edge, 64); struct clk *clk; }; -static inline int xgpio_index(struct xgpio_instance *chip, int gpio) +static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit) { - if (gpio >= chip->gpio_width[0]) - return 1; + return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64); +} - return 0; +static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio) +{ + return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64); +} + +static inline u32 xgpio_get_value32(const unsigned long *map, int bit) +{ + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); + + return (map[index] >> offset) & 0xFFFFFFFFul; +} + +static inline void xgpio_set_value32(unsigned long *map, int bit, u32 v) +{ + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); + + map[index] &= ~(0xFFFFFFFFul << offset); + map[index] |= v << offset; } static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch) @@ -92,22 +114,32 @@ static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch) } } -static inline u32 xgpio_read_chan(struct xgpio_instance *chip, int reg, int ch) +static void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) { - return xgpio_readreg(chip->regs + reg + xgpio_regoffset(chip, ch)); + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_set_value32(a, bit, xgpio_readreg(addr)); } -static inline void xgpio_write_chan(struct xgpio_instance *chip, int reg, int ch, u32 v) +static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) { - xgpio_writereg(chip->regs + reg + xgpio_regoffset(chip, ch), v); + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_writereg(addr, xgpio_get_value32(a, bit)); } -static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) +static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) { - if (xgpio_index(chip, gpio)) - return gpio - chip->gpio_width[0]; + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); - return gpio; + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_read_ch(chip, reg, bit, a); +} + +static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); + + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_write_ch(chip, reg, bit, a); } /** @@ -124,13 +156,12 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); - u32 val; + int bit = xgpio_to_bit(chip, gpio); + DECLARE_BITMAP(state, 64); - val = xgpio_read_chan(chip, XGPIO_DATA_OFFSET, index); + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state); - return !!(val & BIT(offset)); + return test_bit(bit, state); } /** @@ -146,18 +177,14 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write to GPIO signal and set its direction to output */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); + __assign_bit(bit, chip->state, val); - xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, chip->gpio_state[index]); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -174,35 +201,22 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { + DECLARE_BITMAP(hw_mask, 64); + DECLARE_BITMAP(hw_bits, 64); + DECLARE_BITMAP(state, 64); unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, 0); - int offset, i; + + bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64); + bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64); spin_lock_irqsave(&chip->gpio_lock, flags); - /* Write to GPIO signals */ - for (i = 0; i < gc->ngpio; i++) { - if (*mask == 0) - break; - /* Once finished with an index write it out to the register */ - if (index != xgpio_index(chip, i)) { - xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, - chip->gpio_state[index]); - spin_unlock_irqrestore(&chip->gpio_lock, flags); - index = xgpio_index(chip, i); - spin_lock_irqsave(&chip->gpio_lock, flags); - } - if (__test_and_clear_bit(i, mask)) { - offset = xgpio_offset(chip, i); - if (test_bit(i, bits)) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - } - } + bitmap_replace(state, chip->state, hw_bits, hw_mask, 64); - xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, chip->gpio_state[index]); + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state); + + bitmap_copy(chip->state, state, 64); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -220,14 +234,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Set the GPIO bit in shadow register and set direction as input */ - chip->gpio_dir[index] |= BIT(offset); - xgpio_write_chan(chip, XGPIO_TRI_OFFSET, index, chip->gpio_dir[index]); + __set_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -250,21 +263,17 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write state of GPIO signal */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - xgpio_write_chan(chip, XGPIO_DATA_OFFSET, index, chip->gpio_state[index]); + __assign_bit(bit, chip->state, val); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); /* Clear the GPIO bit in shadow register and set direction as output */ - chip->gpio_dir[index] &= ~BIT(offset); - xgpio_write_chan(chip, XGPIO_TRI_OFFSET, index, chip->gpio_dir[index]); + __clear_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -277,14 +286,8 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) */ static void xgpio_save_regs(struct xgpio_instance *chip) { - xgpio_write_chan(chip, XGPIO_DATA_OFFSET, 0, chip->gpio_state[0]); - xgpio_write_chan(chip, XGPIO_TRI_OFFSET, 0, chip->gpio_dir[0]); - - if (!chip->gpio_width[1]) - return; - - xgpio_write_chan(chip, XGPIO_DATA_OFFSET, 1, chip->gpio_state[1]); - xgpio_write_chan(chip, XGPIO_TRI_OFFSET, 1, chip->gpio_dir[1]); + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, chip->state); + xgpio_write_ch_all(chip, XGPIO_TRI_OFFSET, chip->dir); } static int xgpio_request(struct gpio_chip *chip, unsigned int offset) @@ -399,18 +402,17 @@ static void xgpio_irq_mask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); + u32 mask = BIT(bit / 32), temp; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] &= ~BIT(offset); + __clear_bit(bit, chip->enable); - if (!chip->irq_enable[index]) { + if (xgpio_get_value32(chip->enable, bit) == 0) { /* Disable per channel interrupt */ - u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - - temp &= ~BIT(index); + temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); + temp &= ~mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); } spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -425,29 +427,26 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); - u32 old_enable = chip->irq_enable[index]; + int bit = xgpio_to_bit(chip, irq_offset); + u32 old_enable = xgpio_get_value32(chip->enable, bit); + u32 mask = BIT(bit / 32), val; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] |= BIT(offset); + __set_bit(bit, chip->enable); - if (!old_enable) { + if (old_enable == 0) { /* Clear any existing per-channel interrupts */ - u32 val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET) & - BIT(index); - - if (val) - xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); + val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); + val &= mask; + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); /* Update GPIO IRQ read data before enabling interrupt*/ - val = xgpio_read_chan(chip, XGPIO_DATA_OFFSET, index); - chip->gpio_last_irq_read[index] = val; + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, chip->last_irq_read); /* Enable per channel interrupt */ val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - val |= BIT(index); + val |= mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val); } @@ -466,8 +465,7 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) { struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); /* * The Xilinx GPIO hardware provides a single interrupt status @@ -477,16 +475,16 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) */ switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __set_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_RISING: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] &= ~BIT(offset); + __set_bit(bit, chip->rising_edge); + __clear_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_FALLING: - chip->irq_rising_edge[index] &= ~BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __clear_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; default: return -EINVAL; @@ -503,45 +501,45 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) static void xgpio_irqhandler(struct irq_desc *desc) { struct xgpio_instance *chip = irq_desc_get_handler_data(desc); + struct gpio_chip *gc = &chip->gc; struct irq_chip *irqchip = irq_desc_get_chip(desc); - u32 num_channels = chip->gpio_width[1] ? 2 : 1; - u32 offset = 0, index; - u32 status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); + DECLARE_BITMAP(rising, 64); + DECLARE_BITMAP(falling, 64); + DECLARE_BITMAP(all, 64); + int irq_offset; + u32 status; + u32 bit; + unsigned long flags; + status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status); chained_irq_enter(irqchip, desc); - for (index = 0; index < num_channels; index++) { - if ((status & BIT(index))) { - unsigned long rising_events, falling_events, all_events; - unsigned long flags; - u32 data, bit; - unsigned int irq; - spin_lock_irqsave(&chip->gpio_lock, flags); - data = xgpio_read_chan(chip, XGPIO_DATA_OFFSET, index); - rising_events = data & - ~chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_rising_edge[index]; - falling_events = ~data & - chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_falling_edge[index]; - dev_dbg(chip->gc.parent, - "IRQ chan %u rising 0x%lx falling 0x%lx\n", - index, rising_events, falling_events); - all_events = rising_events | falling_events; - chip->gpio_last_irq_read[index] = data; - spin_unlock_irqrestore(&chip->gpio_lock, flags); + spin_lock_irqsave(&chip->gpio_lock, flags); - for_each_set_bit(bit, &all_events, 32) { - irq = irq_find_mapping(chip->gc.irq.domain, - offset + bit); - generic_handle_irq(irq); - } - } - offset += chip->gpio_width[index]; + xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all); + + bitmap_complement(rising, chip->last_irq_read, 64); + bitmap_and(rising, rising, all, 64); + bitmap_and(rising, rising, chip->enable, 64); + bitmap_and(rising, rising, chip->rising_edge, 64); + + bitmap_complement(falling, all, 64); + bitmap_and(falling, falling, chip->last_irq_read, 64); + bitmap_and(falling, falling, chip->enable, 64); + bitmap_and(falling, falling, chip->falling_edge, 64); + + bitmap_copy(chip->last_irq_read, all, 64); + bitmap_or(all, rising, falling, 64); + + spin_unlock_irqrestore(&chip->gpio_lock, flags); + + dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling); + + for_each_set_bit(bit, all, 64) { + irq_offset = xgpio_from_bit(chip, bit); + generic_handle_irq(irq_find_mapping(gc->irq.domain, irq_offset)); } chained_irq_exit(irqchip, desc); @@ -562,6 +560,9 @@ static int xgpio_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; u32 is_dual = 0; u32 cells = 2; + u32 width[2]; + u32 state[2]; + u32 dir[2]; struct gpio_irq_chip *girq; u32 temp; @@ -571,13 +572,25 @@ static int xgpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + /* First, check if the device is dual-channel */ + of_property_read_u32(np, "xlnx,is-dual", &is_dual); + + /* Setup defaults */ + memset32(width, 0, ARRAY_SIZE(width)); + memset32(state, 0, ARRAY_SIZE(state)); + memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir)); + /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0])) - chip->gpio_state[0] = 0x0; + of_property_read_u32(np, "xlnx,dout-default", &state[0]); + of_property_read_u32(np, "xlnx,dout-default-2", &state[1]); + + bitmap_from_arr32(chip->state, state, 64); /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) - chip->gpio_dir[0] = 0xFFFFFFFF; + of_property_read_u32(np, "xlnx,tri-default", &dir[0]); + of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]); + + bitmap_from_arr32(chip->dir, dir, 64); /* Update cells with gpio-cells value */ if (of_property_read_u32(np, "#gpio-cells", &cells)) @@ -592,42 +605,29 @@ static int xgpio_probe(struct platform_device *pdev) * Check device node and parent device node for device width * and assume default width of 32 */ - if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0])) - chip->gpio_width[0] = 32; + if (of_property_read_u32(np, "xlnx,gpio-width", &width[0])) + width[0] = 32; - if (chip->gpio_width[0] > 32) + if (width[0] > 32) return -EINVAL; + if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1])) + width[1] = 32; + + if (width[1] > 32) + return -EINVAL; + + /* Setup software pin mapping */ + bitmap_set(chip->sw_map, 0, width[0] + width[1]); + + /* Setup hardware pin mapping */ + bitmap_set(chip->hw_map, 0, width[0]); + bitmap_set(chip->hw_map, 32, width[1]); + spin_lock_init(&chip->gpio_lock); - if (of_property_read_u32(np, "xlnx,is-dual", &is_dual)) - is_dual = 0; - - if (is_dual) { - /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default-2", - &chip->gpio_state[1])) - chip->gpio_state[1] = 0x0; - - /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default-2", - &chip->gpio_dir[1])) - chip->gpio_dir[1] = 0xFFFFFFFF; - - /* - * Check device node and parent device node for device width - * and assume default width of 32 - */ - if (of_property_read_u32(np, "xlnx,gpio2-width", - &chip->gpio_width[1])) - chip->gpio_width[1] = 32; - - if (chip->gpio_width[1] > 32) - return -EINVAL; - } - chip->gc.base = -1; - chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; + chip->gc.ngpio = bitmap_weight(chip->hw_map, 64); chip->gc.parent = &pdev->dev; chip->gc.direction_input = xgpio_dir_in; chip->gc.direction_output = xgpio_dir_out; From 6453b9532b5f77d19837b159c4d074f0af9f141b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 10 May 2021 22:46:33 +0300 Subject: [PATCH 08/57] gpio: xilinx: No need to disable IRQs in the handler In IRQ handler interrupts are already disabled, hence no need to repeat it. Even in the threaded case, it is not a problem because IRQ framework keeps interrupt disabled there as well. Remove disabling IRQ part in the handler. Signed-off-by: Andy Shevchenko Tested-by: Neeli Srinivas Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xilinx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 01e6459b27e6..0c43baa54b5b 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -509,14 +509,13 @@ static void xgpio_irqhandler(struct irq_desc *desc) int irq_offset; u32 status; u32 bit; - unsigned long flags; status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status); chained_irq_enter(irqchip, desc); - spin_lock_irqsave(&chip->gpio_lock, flags); + spin_lock(&chip->gpio_lock); xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all); @@ -533,7 +532,7 @@ static void xgpio_irqhandler(struct irq_desc *desc) bitmap_copy(chip->last_irq_read, all, 64); bitmap_or(all, rising, falling, 64); - spin_unlock_irqrestore(&chip->gpio_lock, flags); + spin_unlock(&chip->gpio_lock); dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling); From 2a9a2ccaab99d6f8bbe92f01839dfd1cd4a33ddf Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sun, 16 May 2021 09:14:25 +0300 Subject: [PATCH 09/57] gpio: stmpe: fully use convert probe to device-managed The IRQ is registered via devm_request_threaded_irq(), making the driver only partially device-managed. This changeset converts the entire driver to using only devres APIs. This change also removes platform_set_drvdata() since the information is never retrieved to be used in the driver. Signed-off-by: Alexandru Ardelean Reviewed-by: Linus Walleij [Bart: tweaked the commit message] Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-stmpe.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index b94ef8181428..dd4d58b4ae49 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -449,6 +449,11 @@ static void stmpe_init_irq_valid_mask(struct gpio_chip *gc, } } +static void stmpe_gpio_disable(void *stmpe) +{ + stmpe_disable(stmpe, STMPE_BLOCK_GPIO); +} + static int stmpe_gpio_probe(struct platform_device *pdev) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); @@ -461,7 +466,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) return -EINVAL; } - stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL); + stmpe_gpio = devm_kzalloc(&pdev->dev, sizeof(*stmpe_gpio), GFP_KERNEL); if (!stmpe_gpio) return -ENOMEM; @@ -489,7 +494,11 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); if (ret) - goto out_free; + return ret; + + ret = devm_add_action_or_reset(&pdev->dev, stmpe_gpio_disable, stmpe); + if (ret) + return ret; if (irq > 0) { struct gpio_irq_chip *girq; @@ -499,7 +508,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) "stmpe-gpio", stmpe_gpio); if (ret) { dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_disable; + return ret; } girq = &stmpe_gpio->chip.irq; @@ -514,22 +523,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) girq->init_valid_mask = stmpe_init_irq_valid_mask; } - ret = gpiochip_add_data(&stmpe_gpio->chip, stmpe_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - goto out_disable; - } - - platform_set_drvdata(pdev, stmpe_gpio); - - return 0; - -out_disable: - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); - gpiochip_remove(&stmpe_gpio->chip); -out_free: - kfree(stmpe_gpio); - return ret; + return devm_gpiochip_add_data(&pdev->dev, &stmpe_gpio->chip, stmpe_gpio); } static struct platform_driver stmpe_gpio_driver = { From 1189827a2cf72162e37c16d309c47d941cfd1936 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 14 May 2021 12:23:32 +0300 Subject: [PATCH 10/57] gpio: da9055: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Acked-by: Adam Thomson Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-da9055.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 6ad0c37b862e..49446a030f10 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -133,7 +133,6 @@ static int da9055_gpio_probe(struct platform_device *pdev) { struct da9055_gpio *gpio; struct da9055_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -146,15 +145,7 @@ static int da9055_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9055_gpio_driver = { From fd80b8ba3aa5340a0bbfdc4b72bb6a2111cd54bf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 18 May 2021 11:46:19 +0300 Subject: [PATCH 11/57] gpiolib: Make use of assign_bit() API (part 2) We have for some time the assign_bit() API to replace open coded if (foo) set_bit(n, bar); else clear_bit(n, bar); Use this API in GPIO library code. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-sysfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index ae49bb23c6ed..ae7acd6a4f28 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -312,10 +312,7 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) return 0; - if (value) - set_bit(FLAG_ACTIVE_LOW, &desc->flags); - else - clear_bit(FLAG_ACTIVE_LOW, &desc->flags); + assign_bit(FLAG_ACTIVE_LOW, &desc->flags, value); /* reconfigure poll(2) support if enabled on one edge only */ if (flags == GPIO_IRQF_TRIGGER_FALLING || From 9e23bf6b00fd060d9a6fdf8a43f427d09992a21d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 18 May 2021 15:09:17 +0300 Subject: [PATCH 12/57] gpiolib: Use sysfs_emit() in "show" functions The sysfs_emit() function was introduced to make it less ambiguous which function is preferred when writing to the output buffer in a "show" callback [1]. Convert the GPIO library sysfs interface from sprintf() to sysfs_emit() accordingly, as the latter is aware of the PAGE_SIZE buffer and correctly returns the number of bytes written into the buffer. No functional change intended. [1] Documentation/filesystems/sysfs.rst Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-sysfs.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index ae7acd6a4f28..4098bc7f88b7 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -66,9 +66,8 @@ static ssize_t direction_show(struct device *dev, mutex_lock(&data->mutex); gpiod_get_direction(desc); - status = sprintf(buf, "%s\n", - test_bit(FLAG_IS_OUT, &desc->flags) - ? "out" : "in"); + status = sysfs_emit(buf, "%s\n", + test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in"); mutex_unlock(&data->mutex); @@ -109,13 +108,9 @@ static ssize_t value_show(struct device *dev, mutex_lock(&data->mutex); status = gpiod_get_value_cansleep(desc); - if (status < 0) - goto err; + if (status >= 0) + status = sysfs_emit(buf, "%zd\n", status); - buf[0] = '0' + status; - buf[1] = '\n'; - status = 2; -err: mutex_unlock(&data->mutex); return status; @@ -249,11 +244,11 @@ static ssize_t edge_show(struct device *dev, mutex_lock(&data->mutex); for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { - if (data->irq_flags == trigger_types[i].flags) { - status = sprintf(buf, "%s\n", trigger_types[i].name); + if (data->irq_flags == trigger_types[i].flags) break; - } } + if (i < ARRAY_SIZE(trigger_types)) + status = sysfs_emit(buf, "%s\n", trigger_types[i].name); mutex_unlock(&data->mutex); @@ -333,8 +328,8 @@ static ssize_t active_low_show(struct device *dev, mutex_lock(&data->mutex); - status = sprintf(buf, "%d\n", - !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); + status = sysfs_emit(buf, "%d\n", + !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); mutex_unlock(&data->mutex); @@ -412,7 +407,7 @@ static ssize_t base_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", chip->base); + return sysfs_emit(buf, "%d\n", chip->base); } static DEVICE_ATTR_RO(base); @@ -421,7 +416,7 @@ static ssize_t label_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", chip->label ? : ""); + return sysfs_emit(buf, "%s\n", chip->label ?: ""); } static DEVICE_ATTR_RO(label); @@ -430,7 +425,7 @@ static ssize_t ngpio_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", chip->ngpio); + return sysfs_emit(buf, "%u\n", chip->ngpio); } static DEVICE_ATTR_RO(ngpio); From ec5aa31bbed6ca153b47f60af0d21032296b04ad Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 14 May 2021 11:55:00 +0300 Subject: [PATCH 13/57] gpio: visconti: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-visconti.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c index 0e3d19828eb1..47455810bdb9 100644 --- a/drivers/gpio/gpio-visconti.c +++ b/drivers/gpio/gpio-visconti.c @@ -187,15 +187,7 @@ static int visconti_gpio_probe(struct platform_device *pdev) girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; - ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); - if (ret) { - dev_err(dev, "failed to add GPIO chip\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - - return ret; + return devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); } static const struct of_device_id visconti_gpio_of_match[] = { From 6681db5ef540bc47a654c8d85d27042626edc6f8 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 14 May 2021 11:56:27 +0300 Subject: [PATCH 14/57] gpio: adp5520: cleanup probe error path + remove platform_set_drvdata() The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. This also means that the 'err' label can be removed and all goto statements replaced with direct returns (with error codes). Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-adp5520.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 0386ede53f3a..c55e821c63b6 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -113,10 +113,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (pdata->gpio_en_mask & (1 << i)) dev->lut[gpios++] = 1 << i; - if (gpios < 1) { - ret = -EINVAL; - goto err; - } + if (gpios < 1) + return -EINVAL; gc = &dev->gpio_chip; gc->direction_input = adp5520_gpio_direction_input; @@ -148,18 +146,10 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to write\n"); - goto err; + return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); - if (ret) - goto err; - - platform_set_drvdata(pdev, dev); - return 0; - -err: - return ret; + return devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); } static struct platform_driver adp5520_gpio_driver = { From aa93b0f39a079cc5582df6a016f08ba14469a19b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 14 May 2021 12:20:17 +0300 Subject: [PATCH 15/57] gpio: altera-a10sr: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-altera-a10sr.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index b5917c48e4dc..6af51feda06f 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -78,7 +78,6 @@ static const struct gpio_chip altr_a10sr_gc = { static int altr_a10sr_gpio_probe(struct platform_device *pdev) { struct altr_a10sr_gpio *gpio; - int ret; struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -91,15 +90,7 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev) gpio->gp.parent = pdev->dev.parent; gpio->gp.of_node = pdev->dev.of_node; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static const struct of_device_id altr_a10sr_gpio_of_match[] = { From 21dde316cac7e603d9b587640155cb7841a820f3 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 14 May 2021 12:26:14 +0300 Subject: [PATCH 16/57] gpio: bd9571mwv: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-bd9571mwv.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c index df6102b57734..9a4d55f703bb 100644 --- a/drivers/gpio/gpio-bd9571mwv.c +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -97,25 +97,16 @@ static const struct gpio_chip template_chip = { static int bd9571mwv_gpio_probe(struct platform_device *pdev) { struct bd9571mwv_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - platform_set_drvdata(pdev, gpio); - gpio->regmap = dev_get_regmap(pdev->dev.parent, NULL); gpio->chip = template_chip; gpio->chip.parent = pdev->dev.parent; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct platform_device_id bd9571mwv_gpio_id_table[] = { From 91d594b2db51f680ba52862d1bbe14801b4dcd54 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 14 May 2021 12:41:08 +0300 Subject: [PATCH 17/57] gpio: tps68470: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tps68470.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c index f7f5f770e0fb..423b7bc30ae8 100644 --- a/drivers/gpio/gpio-tps68470.c +++ b/drivers/gpio/gpio-tps68470.c @@ -125,7 +125,6 @@ static const char *tps68470_names[TPS68470_N_GPIO] = { static int tps68470_gpio_probe(struct platform_device *pdev) { struct tps68470_gpio_data *tps68470_gpio; - int ret; tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), GFP_KERNEL); @@ -146,16 +145,7 @@ static int tps68470_gpio_probe(struct platform_device *pdev) tps68470_gpio->gc.base = -1; tps68470_gpio->gc.parent = &pdev->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, - tps68470_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps68470_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio); } static struct platform_driver tps68470_gpio_driver = { From 94a7b66910ea6e4583addd8212aa8cd3f7a8c9c1 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 21 May 2021 21:10:42 +0300 Subject: [PATCH 18/57] gpio: xgene: simplify probe, return devm_gpiochip_add_data() directly The handling of the return value from devm_gpiochip_add_data() is a bit redundant. It prints messages on error and success cases. While the success message may be useful, it is more in the area of log spam, and these can be printed with other forms of kernel logging. This change does a direct return with devm_gpiochip_add_data() in the probe function. The platform_set_drvdata() is needed, as this driver uses the stored private date in the PM suspend/resume routines. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xgene.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index 532b0df8a1f2..fb4b0c67aeef 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -159,7 +159,6 @@ static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); static int xgene_gpio_probe(struct platform_device *pdev) { struct xgene_gpio *gpio; - int err = 0; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -183,15 +182,7 @@ static int xgene_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio); - err = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (err) { - dev_err(&pdev->dev, - "failed to register gpiochip.\n"); - return err; - } - - dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct of_device_id xgene_gpio_of_match[] = { From 4d2a72635b5552502f61ff8d3f6e7c78eadffc2b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 21 May 2021 21:13:55 +0300 Subject: [PATCH 19/57] gpio: da9052: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-da9052.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9aa59afdcbbf..559188d80c2b 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -196,7 +196,6 @@ static int da9052_gpio_probe(struct platform_device *pdev) { struct da9052_gpio *gpio; struct da9052_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -209,15 +208,7 @@ static int da9052_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9052_gpio_driver = { From 10a476164b08067f2094020f812af52c347542de Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sat, 15 May 2021 10:59:04 +0300 Subject: [PATCH 20/57] gpio: gpio-tegra186: remove empty remove hook The tegra186_gpio_remove hook simply does a return 0. Not defining it yields pretty much the same result. So, this can be removed. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tegra186.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 1bd9e44df718..10d3597e9ac2 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -750,11 +750,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev) return 0; } -static int tegra186_gpio_remove(struct platform_device *pdev) -{ - return 0; -} - #define TEGRA186_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ [TEGRA186_MAIN_GPIO_PORT_##_name] = { \ .name = #_name, \ @@ -924,7 +919,6 @@ static struct platform_driver tegra186_gpio_driver = { .of_match_table = tegra186_gpio_of_match, }, .probe = tegra186_gpio_probe, - .remove = tegra186_gpio_remove, }; module_platform_driver(tegra186_gpio_driver); From 6e153938b7f005fde4dd025e3998d94cb27e4148 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sat, 15 May 2021 10:59:05 +0300 Subject: [PATCH 21/57] gpio: gpio-tegra186: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tegra186.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 10d3597e9ac2..f54ae9d4254a 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -741,13 +741,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) offset += port->pins; } - platform_set_drvdata(pdev, gpio); - - err = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); - if (err < 0) - return err; - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); } #define TEGRA186_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ From cc7af0bfa0d953fc9aaf278f11ea6f9b17ac228b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sat, 15 May 2021 10:52:33 +0300 Subject: [PATCH 22/57] gpio: tps6586x: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tps6586x.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 9b6cc74f47c8..da0304b764a5 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -76,7 +76,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) { struct tps6586x_platform_data *pdata; struct tps6586x_gpio *tps6586x_gpio; - int ret; pdata = dev_get_platdata(pdev->dev.parent); tps6586x_gpio = devm_kzalloc(&pdev->dev, @@ -106,16 +105,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) else tps6586x_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, - tps6586x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps6586x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, + tps6586x_gpio); } static struct platform_driver tps6586x_gpio_driver = { From 3660660a8e864922613d6c798a0c99ff36092f45 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sat, 15 May 2021 13:58:31 +0300 Subject: [PATCH 23/57] gpio: tc3589x: emove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tc3589x.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 55b8dbd13d11..8d158492488f 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -357,16 +357,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, - tc3589x_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tc3589x_gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, tc3589x_gpio); } static struct platform_driver tc3589x_gpio_driver = { From 0cef30b8beafb2be1adf0e9b7487e5084eec2376 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sat, 15 May 2021 10:54:44 +0300 Subject: [PATCH 24/57] gpio: tps65218: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tps65218.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 43a1150055ce..3517debe2b0b 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -187,7 +187,6 @@ static int tps65218_gpio_probe(struct platform_device *pdev) { struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent); struct tps65218_gpio *tps65218_gpio; - int ret; tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio), GFP_KERNEL); @@ -201,16 +200,8 @@ static int tps65218_gpio_probe(struct platform_device *pdev) tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, - tps65218_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65218_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, + tps65218_gpio); } static const struct of_device_id tps65218_dt_match[] = { From effe3781b6cc8144d6b55b5159ec5bafd73639f7 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sat, 15 May 2021 10:52:57 +0300 Subject: [PATCH 25/57] gpio: tps65912: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tps65912.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 510d9ed9fd2a..fab771cb6a87 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -99,7 +99,6 @@ static int tps65912_gpio_probe(struct platform_device *pdev) { struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); struct tps65912_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -109,16 +108,7 @@ static int tps65912_gpio_probe(struct platform_device *pdev) gpio->gpio_chip = template_chip; gpio->gpio_chip.parent = tps->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, - gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); } static const struct platform_device_id tps65912_gpio_id_table[] = { From cd440753dc9e8803c945f67e4d45f6ea834c00ed Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 17 May 2021 14:37:07 +0300 Subject: [PATCH 26/57] gpio: ath79: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-ath79.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 678ddd375891..9b780dc5d390 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -234,7 +234,6 @@ static int ath79_gpio_probe(struct platform_device *pdev) ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; - platform_set_drvdata(pdev, ctrl); if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); @@ -290,13 +289,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) girq->handler = handle_simple_irq; } - err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); - if (err) { - dev_err(dev, - "cannot add AR71xx GPIO chip, error=%d", err); - return err; - } - return 0; + return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); } static struct platform_driver ath79_gpio_driver = { From 81933d3e485094fee38519e779d8e8f315f513c5 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sun, 16 May 2021 10:43:11 +0300 Subject: [PATCH 27/57] gpio: spear-spics: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. This change isn't removing the 'DT probe failed' message, as some may find it useful as a reason for the failed probe. But that can be part of another change if needed. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-spear-spics.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 6eca531b7d96..49aac2bb8d2c 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -122,7 +122,6 @@ static int spics_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spear_spics *spics; - int ret; spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); if (!spics) @@ -148,8 +147,6 @@ static int spics_gpio_probe(struct platform_device *pdev) &spics->cs_enable_shift)) goto err_dt_data; - platform_set_drvdata(pdev, spics); - spics->chip.ngpio = NUM_OF_GPIO; spics->chip.base = -1; spics->chip.request = spics_request; @@ -163,14 +160,7 @@ static int spics_gpio_probe(struct platform_device *pdev) spics->chip.owner = THIS_MODULE; spics->last_off = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); - if (ret) { - dev_err(&pdev->dev, "unable to add gpio chip\n"); - return ret; - } - - dev_info(&pdev->dev, "spear spics registered\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); err_dt_data: dev_err(&pdev->dev, "DT probe failed\n"); From 52f39cfee66d1878d91a3fdb97d47557af4da0f8 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sun, 16 May 2021 09:26:29 +0300 Subject: [PATCH 28/57] gpio: sprd: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-sprd.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 36ea8a3bd451..25c37edcbc6c 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -222,7 +222,6 @@ static int sprd_gpio_probe(struct platform_device *pdev) { struct gpio_irq_chip *irq; struct sprd_gpio *sprd_gpio; - int ret; sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL); if (!sprd_gpio) @@ -259,14 +258,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) irq->num_parents = 1; irq->parents = &sprd_gpio->irq; - ret = devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, sprd_gpio); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); } static const struct of_device_id sprd_gpio_of_match[] = { From f716f1fb84a48cc80c1dc486f52ebc092d8d834b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Sun, 16 May 2021 09:23:15 +0300 Subject: [PATCH 29/57] gpio: sta2x11: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-sta2x11.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index a74bb97a41e2..392fcab06ab8 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -398,15 +398,7 @@ static int gsta_probe(struct platform_device *dev) return err; } - err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); - if (err < 0) { - dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n", - -err); - return err; - } - - platform_set_drvdata(dev, chip); - return 0; + return devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); } static struct platform_driver sta2x11_gpio_platform_driver = { From 96a03e867c70c738eececcef343a40e60206e51f Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 21 May 2021 21:17:08 +0300 Subject: [PATCH 30/57] gpio: tps65910: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tps65910.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 0c0b445c75c0..7fa8c841081f 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -165,16 +165,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev) } skip_init: - ret = devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, - tps65910_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65910_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, + tps65910_gpio); } static struct platform_driver tps65910_gpio_driver = { From 14ebdaec6d004a7d0727a0713c30b89166179e41 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 17 May 2021 14:35:38 +0300 Subject: [PATCH 31/57] gpio: wm831x: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wm831x.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index a3a32a77041f..9cf1e5ebb352 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -261,7 +261,6 @@ static int wm831x_gpio_probe(struct platform_device *pdev) struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = &wm831x->pdata; struct wm831x_gpio *wm831x_gpio; - int ret; wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio), GFP_KERNEL); @@ -280,16 +279,7 @@ static int wm831x_gpio_probe(struct platform_device *pdev) wm831x_gpio->gpio_chip.of_node = wm831x->dev->of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, - wm831x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm831x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, wm831x_gpio); } static struct platform_driver wm831x_gpio_driver = { From e076aeda467d83dba43f8e3a9d43997aaaf970fe Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 17 May 2021 14:35:40 +0300 Subject: [PATCH 32/57] gpio: wm8994: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wm8994.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 9af89cf7f6bc..f4a474cef32d 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -263,7 +263,6 @@ static int wm8994_gpio_probe(struct platform_device *pdev) struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev); struct wm8994_gpio *wm8994_gpio; - int ret; wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio), GFP_KERNEL); @@ -279,17 +278,7 @@ static int wm8994_gpio_probe(struct platform_device *pdev) else wm8994_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, - wm8994_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - return ret; - } - - platform_set_drvdata(pdev, wm8994_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, wm8994_gpio); } static struct platform_driver wm8994_gpio_driver = { From 0533260687a76c48e6655f7d9eb0bd1811bd9353 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 17 May 2021 14:35:39 +0300 Subject: [PATCH 33/57] gpio: wm8350: remove platform_set_drvdata() + cleanup probe The platform_set_drvdata() call is only useful if we need to retrieve back the private information. Since the driver doesn't do that, it's not useful to have it. If this is removed, we can also just do a direct return on devm_gpiochip_add_data(). We don't need to print that this call failed as there are other ways to log/see this during probe. Signed-off-by: Alexandru Ardelean Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-wm8350.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index 460f0a4b04bd..b1b131fb9804 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -105,7 +105,6 @@ static int wm8350_gpio_probe(struct platform_device *pdev) struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent); struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev); struct wm8350_gpio_data *wm8350_gpio; - int ret; wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio), GFP_KERNEL); @@ -121,16 +120,7 @@ static int wm8350_gpio_probe(struct platform_device *pdev) else wm8350_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, - wm8350_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm8350_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, wm8350_gpio); } static struct platform_driver wm8350_gpio_driver = { From bc3aca5393c4d61d7f5ab1dd61b7f2b0536efec6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 25 May 2021 20:58:58 +0300 Subject: [PATCH 34/57] dt-bindings: gpio: omap: Convert to json-schema Convert the OMAP GPIO Device Tree binding documentation to json-schema. The GPIO hogs node names defined to end with a 'hog' suffix. Signed-off-by: Grygorii Strashko Reviewed-by: Rob Herring Signed-off-by: Bartosz Golaszewski --- .../devicetree/bindings/gpio/gpio-omap.txt | 45 -------- .../bindings/gpio/ti,omap-gpio.yaml | 108 ++++++++++++++++++ 2 files changed, 108 insertions(+), 45 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-omap.txt create mode 100644 Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-omap.txt b/Documentation/devicetree/bindings/gpio/gpio-omap.txt deleted file mode 100644 index e57b2cb28f6c..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-omap.txt +++ /dev/null @@ -1,45 +0,0 @@ -OMAP GPIO controller bindings - -Required properties: -- compatible: - - "ti,omap2-gpio" for OMAP2 controllers - - "ti,omap3-gpio" for OMAP3 controllers - - "ti,omap4-gpio" for OMAP4 controllers -- reg : Physical base address of the controller and length of memory mapped - region. -- gpio-controller : Marks the device node as a GPIO controller. -- #gpio-cells : Should be two. - - first cell is the pin number - - second cell is used to specify optional parameters (unused) -- interrupt-controller: Mark the device node as an interrupt controller. -- #interrupt-cells : Should be 2. - The first cell is the GPIO number. - The second cell is used to specify flags: - bits[3:0] trigger type and level flags: - 1 = low-to-high edge triggered. - 2 = high-to-low edge triggered. - 4 = active high level-sensitive. - 8 = active low level-sensitive. -- interrupts : The interrupt the controller is rising as output when an - interrupt occures - -OMAP specific properties: -- ti,hwmods: Name of the hwmod associated to the GPIO: - "gpio", being the 1-based instance number - from the HW spec. -- ti,gpio-always-on: Indicates if a GPIO bank is always powered and - so will never lose its logic state. - - -Example: - -gpio0: gpio@44e07000 { - compatible = "ti,omap4-gpio"; - reg = <0x44e07000 0x1000>; - ti,hwmods = "gpio1"; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <96>; -}; diff --git a/Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml b/Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml new file mode 100644 index 000000000000..7087e4a5013f --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/ti,omap-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: OMAP GPIO controller bindings + +maintainers: + - Grygorii Strashko + +description: | + The general-purpose interface combines general-purpose input/output (GPIO) banks. + Each GPIO banks provides up to 32 dedicated general-purpose pins with input + and output capabilities; interrupt generation in active mode and wake-up + request generation in idle mode upon the detection of external events. + +properties: + compatible: + oneOf: + - enum: + - ti,omap2-gpio + - ti,omap3-gpio + - ti,omap4-gpio + - items: + - const: ti,am4372-gpio + - const: ti,omap4-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + interrupts: + maxItems: 1 + + gpio-ranges: true + + gpio-line-names: + minItems: 1 + maxItems: 32 + + ti,gpio-always-on: + $ref: /schemas/types.yaml#/definitions/flag + description: + Indicates if a GPIO bank is always powered and will never lose its logic state. + + ti,hwmods: + $ref: /schemas/types.yaml#/definitions/string + deprecated: true + description: + Name of the hwmod associated with the GPIO. Needed on some legacy OMAP + SoCs which have not been converted to the ti,sysc interconnect hierarachy. + + ti,no-reset-on-init: + $ref: /schemas/types.yaml#/definitions/flag + deprecated: true + description: + Do not reset on init. Used with ti,hwmods on some legacy OMAP SoCs which + have not been converted to the ti,sysc interconnect hierarachy. + +patternProperties: + "^(.+-hog(-[0-9]+)?)$": + type: object + + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + - interrupts + +additionalProperties: false + +examples: + - | + #include + + gpio0: gpio@0 { + compatible = "ti,omap4-gpio"; + reg = <0x0 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <96>; + ti,gpio-always-on; + + ls-buf-en-hog { + gpio-hog; + gpios = <10 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "LS_BUF_EN"; + }; + }; From c80c44352ddadc257410c89a8e044c1804c4f6d2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 25 May 2021 21:35:17 +0300 Subject: [PATCH 35/57] gpiolib: Split fastpath array to two Split fastpath array to two, i.e. for mask and for bits. At the same time declare them as bitmaps. This makes code better to read and gives a clue about use of bitmap API. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 220a9d8dd4e3..170de786c02f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2540,21 +2540,24 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int first, j; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { 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(gc->ngpio); } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2577,7 +2580,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { - if (mask != fastpath) + if (mask != fastpath_mask) kfree(mask); return ret; } @@ -2598,7 +2601,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, j); } - if (mask != fastpath) + if (mask != fastpath_mask) kfree(mask); } return 0; @@ -2823,21 +2826,24 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int count = 0; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { 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(gc->ngpio); } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2882,7 +2888,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, if (count != 0) gpio_chip_set_multiple(gc, mask, bits); - if (mask != fastpath) + if (mask != fastpath_mask) kfree(mask); } return 0; From c354c29524eeabba63da51f30a09b85ec9dc853a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 25 May 2021 21:35:18 +0300 Subject: [PATCH 36/57] gpiolib: Switch to bitmap_alloc() Switch to bitmap_alloc() to show clearly what we are allocating. Besides that it returns pointer of bitmap type instead of opaque void *. Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 170de786c02f..27c07108496d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2549,13 +2549,17 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, mask = fastpath_mask; bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; - bits = mask + BITS_TO_LONGS(gc->ngpio); + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } bitmap_zero(mask, gc->ngpio); @@ -2581,7 +2585,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { if (mask != fastpath_mask) - kfree(mask); + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); return ret; } @@ -2602,7 +2608,9 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, } if (mask != fastpath_mask) - kfree(mask); + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } @@ -2835,13 +2843,17 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, mask = fastpath_mask; bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; - bits = mask + BITS_TO_LONGS(gc->ngpio); + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } bitmap_zero(mask, gc->ngpio); @@ -2889,7 +2901,9 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, gpio_chip_set_multiple(gc, mask, bits); if (mask != fastpath_mask) - kfree(mask); + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } From cc0f53d2bb422b555d76c1258dbe9aec9b1f416b Mon Sep 17 00:00:00 2001 From: Navin Sankar Velliangiri Date: Tue, 25 May 2021 10:27:17 +0530 Subject: [PATCH 37/57] gpio: 104-idio-16: Fix coding style issues Fixed multiple bare uses of 'unsigned' without int. Reported by checkpatch. Signed-off-by: Navin Sankar Velliangiri Acked-by: William Breathitt Gray Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-104-idio-16.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 50ad0280fd78..55b40299ebfa 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -44,11 +44,12 @@ struct idio_16_gpio { struct gpio_chip chip; raw_spinlock_t lock; unsigned long irq_mask; - unsigned base; - unsigned out_state; + unsigned int base; + unsigned int out_state; }; -static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) { if (offset > 15) return GPIO_LINE_DIRECTION_IN; @@ -56,22 +57,23 @@ static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) return GPIO_LINE_DIRECTION_OUT; } -static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) { return 0; } static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { chip->set(chip, offset, value); return 0; } -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset-16); + const unsigned int mask = BIT(offset-16); if (offset < 16) return -EINVAL; @@ -96,10 +98,11 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip, return 0; } -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset); + const unsigned int mask = BIT(offset); unsigned long flags; if (offset > 15) @@ -180,7 +183,7 @@ static void idio_16_irq_unmask(struct irq_data *data) } } -static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type) +static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) { /* The only valid irq types are none and both-edges */ if (flow_type != IRQ_TYPE_NONE && From 5a5bc826fed1d86212eb78114c86808c29b11b0a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Jun 2021 19:21:27 +0300 Subject: [PATCH 38/57] gpio: dwapb: Drop redundant check in dwapb_irq_set_type() For more than 15 years we may not get into ->irq_set_type() without any meaningful type provided. Drop redundant check in dwapb_irq_set_type(). See the commit e76de9f8eb67 ("[PATCH] genirq: add SA_TRIGGER support") out of curiosity. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-dwapb.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index d3233cc4b76b..939701c1465e 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -297,9 +297,6 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) irq_hw_number_t bit = irqd_to_hwirq(d); unsigned long level, polarity, flags; - if (type & ~IRQ_TYPE_SENSE_MASK) - return -EINVAL; - spin_lock_irqsave(&gc->bgpio_lock, flags); level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); polarity = dwapb_read(gpio, GPIO_INT_POLARITY); From bd56b051c96b9e0bbfaa7f79d3fad385fae2ac4b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 1 Jun 2021 19:21:28 +0300 Subject: [PATCH 39/57] gpio: dwapb: Switch to use fwnode_irq_get() We have open coded variant of fwnode_irq_get() in dwapb_get_irq(). Replace it with a simple call. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-dwapb.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 939701c1465e..7d61f5821e32 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -528,17 +528,13 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, struct dwapb_port_property *pp) { - struct device_node *np = NULL; - int irq = -ENXIO, j; - - if (fwnode_property_read_bool(fwnode, "interrupt-controller")) - np = to_of_node(fwnode); + int irq, j; for (j = 0; j < pp->ngpio; j++) { - if (np) - irq = of_irq_get(np, j); - else if (has_acpi_companion(dev)) + if (has_acpi_companion(dev)) irq = platform_get_irq_optional(to_platform_device(dev), j); + else + irq = fwnode_irq_get(fwnode, j); if (irq > 0) pp->irq[j] = irq; } From 40e568f9c88db8efe264b3a372faea940fc12a0f Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Thu, 3 Jun 2021 13:00:21 +0300 Subject: [PATCH 40/57] gpio: gpio-regmap: Use devm_add_action_or_reset() Slightly simplify the devm_gpio_regmap_register() by using the devm_add_action_or_reset(). Reviewed-by: Andy Shevchenko Reviewed-by: Michael Walle Signed-off-by: Matti Vaittinen Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-regmap.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 134cedf151a7..1ead1290eb3f 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -311,9 +311,9 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) } EXPORT_SYMBOL_GPL(gpio_regmap_unregister); -static void devm_gpio_regmap_unregister(struct device *dev, void *res) +static void devm_gpio_regmap_unregister(void *res) { - gpio_regmap_unregister(*(struct gpio_regmap **)res); + gpio_regmap_unregister(res); } /** @@ -330,20 +330,17 @@ static void devm_gpio_regmap_unregister(struct device *dev, void *res) struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, const struct gpio_regmap_config *config) { - struct gpio_regmap **ptr, *gpio; - - ptr = devres_alloc(devm_gpio_regmap_unregister, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct gpio_regmap *gpio; + int ret; gpio = gpio_regmap_register(config); - if (!IS_ERR(gpio)) { - *ptr = gpio; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + + if (IS_ERR(gpio)) + return gpio; + + ret = devm_add_action_or_reset(dev, devm_gpio_regmap_unregister, gpio); + if (ret) + return ERR_PTR(ret); return gpio; } From 043a0c9fe7a036ec5e1b85a8894d6f69bf996470 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 4 Jun 2021 21:50:13 +0300 Subject: [PATCH 41/57] gpio-dwapb: Drop unused headers and sort the rest Drop unused headers and drop the rest. Reported-by: kernel test robot Signed-off-by: Andy Shevchenko Reviewed-by: Linus Walleij Acked-by: Serge Semin Tested-by: Serge Semin Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-dwapb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 7d61f5821e32..3eb13d6d31ef 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -13,17 +13,15 @@ #include #include #include +#include #include #include -#include -#include -#include +#include #include #include #include -#include -#include #include +#include #include "gpiolib.h" #include "gpiolib-acpi.h" From 9b3c47f124b60770f7738710e95801284d69d24f Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Sat, 5 Jun 2021 00:58:57 +0200 Subject: [PATCH 42/57] gpio: regmap: move drvdata to config data Drop gpio_regmap_set_drvdata() and instead add it to the configuration data passed to gpio_regmap_register(). gpio_regmap_set_drvdata() can't really be used in a race free way. This is because the gpio_regmap object which is needed by _set_drvdata() is returned by gpio_regmap_register(). On the other hand, the callbacks which use the drvdata might already be called right after the gpiochip_add() call in gpio_regmap_register(). Therefore, we have to provide the drvdata early before we call gpiochip_add(). Signed-off-by: Matti Vaittinen Signed-off-by: Michael Walle Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-regmap.c | 7 +------ include/linux/gpio/regmap.h | 6 +++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 1ead1290eb3f..69c219742083 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -178,12 +178,6 @@ static int gpio_regmap_direction_output(struct gpio_chip *chip, return gpio_regmap_set_direction(chip, offset, true); } -void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data) -{ - gpio->driver_data = data; -} -EXPORT_SYMBOL_GPL(gpio_regmap_set_drvdata); - void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; @@ -226,6 +220,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config return ERR_PTR(-ENOMEM); gpio->parent = config->parent; + gpio->driver_data = config->drvdata; gpio->regmap = config->regmap; gpio->ngpio_per_reg = config->ngpio_per_reg; gpio->reg_stride = config->reg_stride; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index 334dd928042b..a9f7b7faf57b 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -37,6 +37,9 @@ struct regmap; * offset to a register/bitmask pair. If not * given the default gpio_regmap_simple_xlate() * is used. + * @drvdata: (Optional) Pointer to driver specific data which is + * not used by gpio-remap but is provided "as is" to the + * driver callback(s). * * The ->reg_mask_xlate translates a given base address and GPIO offset to * register and mask pair. The base address is one of the given register @@ -78,13 +81,14 @@ struct gpio_regmap_config { int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); + + void *drvdata; }; struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config); void gpio_regmap_unregister(struct gpio_regmap *gpio); struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, const struct gpio_regmap_config *config); -void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data); void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio); #endif /* _LINUX_GPIO_REGMAP_H */ From 4195926aedca79e7acd00ec6448726cae97675bc Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Fri, 14 May 2021 14:33:07 +0200 Subject: [PATCH 43/57] gpio: Add support for IDT 79RC3243x GPIO controller IDT 79RC3243x SoCs integrated a gpio controller, which handles up to 32 gpios. All gpios could be used as an interrupt source. Signed-off-by: Thomas Bogendoerfer Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 12 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-idt3243x.c | 206 +++++++++++++++++++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 drivers/gpio/gpio-idt3243x.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1dd0ec6727fd..ae2721967191 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -782,6 +782,18 @@ config GPIO_MSC313 Say Y here to support the main GPIO block on MStar/SigmaStar ARMv7 based SoCs. +config GPIO_IDT3243X + tristate "IDT 79RC3243X GPIO support" + depends on MIKROTIK_RB532 || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Select this option to enable GPIO driver for + IDT 79RC3243X based devices like Mikrotik RB532. + + To compile this driver as a module, choose M here: the module will + be called gpio-idt3243x. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d7c81e1611a4..32a32659866a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o +obj-$(CONFIG_GPIO_IDT3243X) += gpio-idt3243x.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c new file mode 100644 index 000000000000..e961acee1571 --- /dev/null +++ b/drivers/gpio/gpio-idt3243x.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Driver for IDT/Renesas 79RC3243x Interrupt Controller */ + +#include +#include +#include +#include +#include +#include +#include + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +#define IDT_GPIO_DIR 0x00 +#define IDT_GPIO_DATA 0x04 +#define IDT_GPIO_ILEVEL 0x08 +#define IDT_GPIO_ISTAT 0x0C + +struct idt_gpio_ctrl { + struct gpio_chip gc; + void __iomem *pic; + void __iomem *gpio; + u32 mask_cache; +}; + +static void idt_gpio_dispatch(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + unsigned int bit, virq; + unsigned long pending; + + chained_irq_enter(host_chip, desc); + + pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND); + pending &= ~ctrl->mask_cache; + for_each_set_bit(bit, &pending, gc->ngpio) { + virq = irq_linear_revmap(gc->irq.domain, bit); + if (virq) + generic_handle_irq(virq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned int sense = flow_type & IRQ_TYPE_SENSE_MASK; + unsigned long flags; + u32 ilevel; + + /* hardware only supports level triggered */ + if (sense == IRQ_TYPE_NONE || (sense & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ilevel = readl(ctrl->gpio + IDT_GPIO_ILEVEL); + if (sense & IRQ_TYPE_LEVEL_HIGH) + ilevel |= BIT(d->hwirq); + else if (sense & IRQ_TYPE_LEVEL_LOW) + ilevel &= ~BIT(d->hwirq); + + writel(ilevel, ctrl->gpio + IDT_GPIO_ILEVEL); + irq_set_handler_locked(d, handle_level_irq); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + return 0; +} + +static void idt_gpio_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + writel(~BIT(d->hwirq), ctrl->gpio + IDT_GPIO_ISTAT); +} + +static void idt_gpio_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache |= BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void idt_gpio_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache &= ~BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static int idt_gpio_irq_init_hw(struct gpio_chip *gc) +{ + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + /* Mask interrupts. */ + ctrl->mask_cache = 0xffffffff; + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + return 0; +} + +static struct irq_chip idt_gpio_irqchip = { + .name = "IDTGPIO", + .irq_mask = idt_gpio_mask, + .irq_ack = idt_gpio_ack, + .irq_unmask = idt_gpio_unmask, + .irq_set_type = idt_gpio_irq_set_type +}; + +static int idt_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; + struct idt_gpio_ctrl *ctrl; + unsigned int parent_irq; + int ngpios; + int ret; + + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->gpio = devm_platform_ioremap_resource_byname(pdev, "gpio"); + if (!ctrl->gpio) + return -ENOMEM; + + ctrl->gc.parent = dev; + + ret = bgpio_init(&ctrl->gc, &pdev->dev, 4, ctrl->gpio + IDT_GPIO_DATA, + NULL, NULL, ctrl->gpio + IDT_GPIO_DIR, NULL, 0); + if (ret) { + dev_err(dev, "bgpio_init failed\n"); + return ret; + } + + ret = device_property_read_u32(dev, "ngpios", &ngpios); + if (!ret) + ctrl->gc.ngpio = ngpios; + + if (device_property_read_bool(dev, "interrupt-controller")) { + ctrl->pic = devm_platform_ioremap_resource_byname(pdev, "pic"); + if (!ctrl->pic) + return -ENOMEM; + + parent_irq = platform_get_irq(pdev, 0); + if (!parent_irq) + return -EINVAL; + + girq = &ctrl->gc.irq; + girq->chip = &idt_gpio_irqchip; + girq->init_hw = idt_gpio_irq_init_hw; + girq->parent_handler = idt_gpio_dispatch; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + + girq->parents[0] = parent_irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + } + + return devm_gpiochip_add_data(&pdev->dev, &ctrl->gc, ctrl); +} + +static const struct of_device_id idt_gpio_of_match[] = { + { .compatible = "idt,32434-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, idt_gpio_of_match); + +static struct platform_driver idt_gpio_driver = { + .probe = idt_gpio_probe, + .driver = { + .name = "idt3243x-gpio", + .of_match_table = idt_gpio_of_match, + }, +}; +module_platform_driver(idt_gpio_driver); + +MODULE_DESCRIPTION("IDT 79RC3243x GPIO/PIC Driver"); +MODULE_AUTHOR("Thomas Bogendoerfer "); +MODULE_LICENSE("GPL"); From 03c36034ce19e5ad855bd6b72a3d6fb194ac4df4 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Fri, 14 May 2021 14:33:08 +0200 Subject: [PATCH 44/57] dt-bindings: gpio: Add devicetree binding for IDT 79RC32434 GPIO controller Add YAML devicetree binding for IDT 79RC32434 GPIO controller Signed-off-by: Thomas Bogendoerfer Reviewed-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- .../bindings/gpio/idt,32434-gpio.yaml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml diff --git a/Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml b/Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml new file mode 100644 index 000000000000..d38de8144656 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/idt,32434-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IDT 79RC32434 GPIO controller + +maintainers: + - Thomas Bogendoerfer + +properties: + compatible: + const: idt,32434-gpio + + reg: + maxItems: 2 + + reg-names: + items: + - const: gpio + - const: pic + + gpio-controller: true + + "#gpio-cells": + const: 2 + + ngpios: + minimum: 1 + maximum: 32 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - reg-names + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + gpio0: gpio@50004 { + compatible = "idt,32434-gpio"; + reg = <0x50004 0x10>, <0x38030 0x0c>; + reg-names = "gpio", "pic"; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ngpios = <14>; + }; From 354cb6465a9b04df1e99a43fdd22881ad5c91843 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 2 Jun 2021 17:43:16 +0200 Subject: [PATCH 45/57] MAINTAINERS: update ti,omap-gpio.yaml reference Changeset bc3aca5393c4 ("dt-bindings: gpio: omap: Convert to json-schema") renamed: Documentation/devicetree/bindings/gpio/gpio-omap.txt to: Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml. Update its cross-reference accordingly. Fixes: bc3aca5393c4 ("dt-bindings: gpio: omap: Convert to json-schema") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Bartosz Golaszewski --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index bd7aff0c120f..22d50c4d9061 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13325,7 +13325,7 @@ M: Santosh Shilimkar M: Kevin Hilman L: linux-omap@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/gpio/gpio-omap.txt +F: Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml F: drivers/gpio/gpio-omap.c OMAP HARDWARE SPINLOCK SUPPORT From 622096fdff79458436b7387a86a5c9f000785e4f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 8 Jun 2021 14:38:53 +0000 Subject: [PATCH 46/57] gpio: idt3243x: Fix return value check in idt_gpio_probe() In case of error, the function devm_platform_ioremap_resource_byname() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Fixes: 4195926aedca ("gpio: Add support for IDT 79RC3243x GPIO controller") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Acked-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-idt3243x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c index e961acee1571..50003ad2e589 100644 --- a/drivers/gpio/gpio-idt3243x.c +++ b/drivers/gpio/gpio-idt3243x.c @@ -142,8 +142,8 @@ static int idt_gpio_probe(struct platform_device *pdev) return -ENOMEM; ctrl->gpio = devm_platform_ioremap_resource_byname(pdev, "gpio"); - if (!ctrl->gpio) - return -ENOMEM; + if (IS_ERR(ctrl->gpio)) + return PTR_ERR(ctrl->gpio); ctrl->gc.parent = dev; @@ -160,8 +160,8 @@ static int idt_gpio_probe(struct platform_device *pdev) if (device_property_read_bool(dev, "interrupt-controller")) { ctrl->pic = devm_platform_ioremap_resource_byname(pdev, "pic"); - if (!ctrl->pic) - return -ENOMEM; + if (IS_ERR(ctrl->pic)) + return PTR_ERR(ctrl->pic); parent_irq = platform_get_irq(pdev, 0); if (!parent_irq) From c43ce4740249b485846093f8a66220b25fb86290 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Fri, 9 Apr 2021 19:38:04 +0530 Subject: [PATCH 47/57] gpio: zynq: use module_platform_driver to simplify the code module_platform_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Srinivas Neeli Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-zynq.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3521c1dc3ac0..bb1ac0c5cf26 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1020,22 +1020,7 @@ static struct platform_driver zynq_gpio_driver = { .remove = zynq_gpio_remove, }; -/** - * zynq_gpio_init - Initial driver registration call - * - * Return: value from platform_driver_register - */ -static int __init zynq_gpio_init(void) -{ - return platform_driver_register(&zynq_gpio_driver); -} -postcore_initcall(zynq_gpio_init); - -static void __exit zynq_gpio_exit(void) -{ - platform_driver_unregister(&zynq_gpio_driver); -} -module_exit(zynq_gpio_exit); +module_platform_driver(zynq_gpio_driver); MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); From a51b2fb94b04ab71e53a71b9fad03fa826941254 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Fri, 9 Apr 2021 19:38:05 +0530 Subject: [PATCH 48/57] gpio: zynq: Check return value of pm_runtime_get_sync Return value of "pm_runtime_get_sync" API was neither captured nor checked. Fixed it by capturing the return value and then checking for any warning. Addresses-Coverity: "check_return" Signed-off-by: Srinivas Neeli Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-zynq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index bb1ac0c5cf26..c91302a16c77 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1001,8 +1001,11 @@ err_pm_dis: static int zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret; - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); From 35d7b72a632bc7afb15356f44005554af8697904 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Fri, 9 Apr 2021 19:38:06 +0530 Subject: [PATCH 49/57] gpio: zynq: Check return value of irq_get_irq_data In two different instances the return value of "irq_get_irq_data" API was neither captured nor checked. Fixed it by capturing the return value and then checking for any error. Addresses-Coverity: "returned_null" Signed-off-by: Srinivas Neeli Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-zynq.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index c91302a16c77..f0cb8ccd03ed 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -736,6 +736,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) disable_irq(gpio->irq); @@ -753,6 +758,11 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) enable_irq(gpio->irq); From be4dc321a55cfee3099a1bd9399d0cd4ac080c23 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Thu, 3 Jun 2021 22:19:00 +0530 Subject: [PATCH 50/57] gpio: gpio-xilinx: update on suspend and resume calls Current AXI GPIO driver checking for interrupt data in suspend and resume path and reporting as error in case of no interrupt connection. As per AXI GPIO IP specification interrupt connection is optional, driver logic is updated in suspend and resume calls by reporting debug message and enable/disable clock in case of no connection. Signed-off-by: Srinivas Neeli Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-xilinx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 0c43baa54b5b..e10e7752460a 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -313,8 +313,8 @@ static int __maybe_unused xgpio_suspend(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_suspend(dev); } if (!irqd_is_wakeup_set(data)) @@ -359,8 +359,8 @@ static int __maybe_unused xgpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_resume(dev); } if (!irqd_is_wakeup_set(data)) From 6d49b3a0f351925b5ea5047166c112b7590b918a Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Sun, 13 Jun 2021 23:03:26 +0100 Subject: [PATCH 51/57] gpio: pca953x: Add support for the On Semi pca9655 The On Semi pca9655 is a 16 bit variant of the On Semi pca9654 GPIO expander, with 16 GPIOs and interrupt functionality. Signed-off-by: Peter Robinson [Bartosz: fixed indentation as noted by Andy] Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index c91d05651596..f5cfc0698799 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1241,6 +1241,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, { } From c830b87a761b942474a7de95acb7f57a366fe73b Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Mon, 24 May 2021 20:49:54 +0530 Subject: [PATCH 52/57] dt-bindings: gpio: gpio-davinci: Convert to json-schema Convert gpio-davinci dt-binding documentation from txt to yaml format. Signed-off-by: Aswath Govindraju Reviewed-by: Rob Herring Signed-off-by: Bartosz Golaszewski --- .../devicetree/bindings/gpio/gpio-davinci.txt | 167 ---------------- .../bindings/gpio/gpio-davinci.yaml | 185 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 186 insertions(+), 168 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-davinci.txt create mode 100644 Documentation/devicetree/bindings/gpio/gpio-davinci.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt b/Documentation/devicetree/bindings/gpio/gpio-davinci.txt deleted file mode 100644 index 696ea46227d1..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt +++ /dev/null @@ -1,167 +0,0 @@ -Davinci/Keystone GPIO controller bindings - -Required Properties: -- compatible: should be "ti,dm6441-gpio": for Davinci da850 SoCs - "ti,keystone-gpio": for Keystone 2 66AK2H/K, 66AK2L, - 66AK2E SoCs - "ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G - "ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654 - "ti,j721e-gpio", "ti,keystone-gpio": for J721E SoCs - "ti,am64-gpio", "ti,keystone-gpio": for AM64 SoCs - -- reg: Physical base address of the controller and the size of memory mapped - registers. - -- gpio-controller : Marks the device node as a gpio controller. - -- #gpio-cells : Should be two. - - first cell is the pin number - - second cell is used to specify optional parameters (unused) - -- interrupts: Array of GPIO interrupt number. Only banked or unbanked IRQs are - supported at a time. - -- ti,ngpio: The number of GPIO pins supported. - -- ti,davinci-gpio-unbanked: The number of GPIOs that have an individual interrupt - line to processor. - -- clocks: Should contain the device's input clock, and should be defined as per - the appropriate clock bindings consumer usage in, - - Documentation/devicetree/bindings/clock/keystone-gate.txt - for 66AK2HK/66AK2L/66AK2E SoCs or, - - Documentation/devicetree/bindings/clock/ti,sci-clk.txt - for 66AK2G SoCs - -- clock-names: Name should be "gpio"; - -Currently clock-names and clocks are needed for all keystone 2 platforms -Davinci platforms do not have DT clocks as of now. - -The GPIO controller also acts as an interrupt controller. It uses the default -two cells specifier as described in Documentation/devicetree/bindings/ -interrupt-controller/interrupts.txt. - -Example: - -gpio: gpio@1e26000 { - compatible = "ti,dm6441-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x226000 0x1000>; - interrupt-parent = <&intc>; - interrupts = <42 IRQ_TYPE_EDGE_BOTH 43 IRQ_TYPE_EDGE_BOTH - 44 IRQ_TYPE_EDGE_BOTH 45 IRQ_TYPE_EDGE_BOTH - 46 IRQ_TYPE_EDGE_BOTH 47 IRQ_TYPE_EDGE_BOTH - 48 IRQ_TYPE_EDGE_BOTH 49 IRQ_TYPE_EDGE_BOTH - 50 IRQ_TYPE_EDGE_BOTH>; - ti,ngpio = <144>; - ti,davinci-gpio-unbanked = <0>; - interrupt-controller; - #interrupt-cells = <2>; -}; - -leds { - compatible = "gpio-leds"; - - led1 { - label = "davinci:green:usr1"; - gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; - ... - }; - - led2 { - label = "davinci:red:debug1"; - gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; - ... - }; -}; - -Example for 66AK2G: - -gpio0: gpio@2603000 { - compatible = "ti,k2g-gpio", "ti,keystone-gpio"; - reg = <0x02603000 0x100>; - gpio-controller; - #gpio-cells = <2>; - interrupts = , - , - , - , - , - , - , - , - ; - interrupt-controller; - #interrupt-cells = <2>; - ti,ngpio = <144>; - ti,davinci-gpio-unbanked = <0>; - clocks = <&k2g_clks 0x001b 0x0>; - clock-names = "gpio"; -}; - -Example for 66AK2HK/66AK2L/66AK2E: - -gpio0: gpio@260bf00 { - compatible = "ti,keystone-gpio"; - reg = <0x0260bf00 0x100>; - gpio-controller; - #gpio-cells = <2>; - /* HW Interrupts mapped to GPIO pins */ - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; - clocks = <&clkgpio>; - clock-names = "gpio"; - ti,ngpio = <32>; - ti,davinci-gpio-unbanked = <32>; -}; - -Example for K3 AM654: - -wkup_gpio0: wkup_gpio0@42110000 { - compatible = "ti,am654-gpio", "ti,keystone-gpio"; - reg = <0x42110000 0x100>; - gpio-controller; - #gpio-cells = <2>; - interrupt-parent = <&intr_wkup_gpio>; - interrupts = <59 128>, <59 129>, <59 130>, <59 131>; - interrupt-controller; - #interrupt-cells = <2>; - ti,ngpio = <56>; - ti,davinci-gpio-unbanked = <0>; - clocks = <&k3_clks 59 0>; - clock-names = "gpio"; -}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-davinci.yaml b/Documentation/devicetree/bindings/gpio/gpio-davinci.yaml new file mode 100644 index 000000000000..f32e09ef937c --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-davinci.yaml @@ -0,0 +1,185 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-davinci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO controller for Davinci and keystone devices + +maintainers: + - Keerthy + +properties: + compatible: + oneOf: + - items: + - enum: + - ti,k2g-gpio + - ti,am654-gpio + - ti,j721e-gpio + - ti,am64-gpio + - const: ti,keystone-gpio + + - items: + - enum: + - ti,dm6441-gpio + - ti,keystone-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + gpio-ranges: true + + gpio-line-names: + description: strings describing the names of each gpio line. + minItems: 1 + maxItems: 100 + + "#gpio-cells": + const: 2 + description: + first cell is the pin number and second cell is used to specify optional parameters (unused). + + interrupts: + description: + The interrupts are specified as per the interrupt parent. Only banked + or unbanked IRQs are supported at a time. If the interrupts are + banked then provide list of interrupts corresponding to each bank, else + provide the list of interrupts for each gpio. + minItems: 1 + maxItems: 100 + + ti,ngpio: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The number of GPIO pins supported consecutively. + minimum: 1 + + ti,davinci-gpio-unbanked: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The number of GPIOs that have an individual interrupt line to processor. + minimum: 0 + + clocks: + maxItems: 1 + + clock-names: + const: gpio + + interrupt-controller: true + + power-domains: + maxItems: 1 + + "#interrupt-cells": + const: 2 + +patternProperties: + "^(.+-hog(-[0-9]+)?)$": + type: object + + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - interrupts + - ti,ngpio + - ti,davinci-gpio-unbanked + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + + gpio0: gpio@2603000 { + compatible = "ti,k2g-gpio", "ti,keystone-gpio"; + reg = <0x02603000 0x100>; + gpio-controller; + #gpio-cells = <2>; + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-controller; + #interrupt-cells = <2>; + ti,ngpio = <144>; + ti,davinci-gpio-unbanked = <0>; + clocks = <&k2g_clks 0x001b 0x0>; + clock-names = "gpio"; + }; + + - | + #include + + gpio1: gpio@260bf00 { + compatible = "ti,keystone-gpio"; + reg = <0x0260bf00 0x100>; + gpio-controller; + #gpio-cells = <2>; + /* HW Interrupts mapped to GPIO pins */ + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + clocks = <&clkgpio>; + clock-names = "gpio"; + ti,ngpio = <32>; + ti,davinci-gpio-unbanked = <32>; + }; + + - | + wkup_gpio0: gpio0@42110000 { + compatible = "ti,am654-gpio", "ti,keystone-gpio"; + reg = <0x42110000 0x100>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&intr_wkup_gpio>; + interrupts = <60>, <61>, <62>, <63>; + interrupt-controller; + #interrupt-cells = <2>; + ti,ngpio = <56>; + ti,davinci-gpio-unbanked = <0>; + clocks = <&k3_clks 59 0>; + clock-names = "gpio"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 22d50c4d9061..2e54ea8bc455 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18250,7 +18250,7 @@ TI DAVINCI SERIES GPIO DRIVER M: Keerthy L: linux-gpio@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/gpio/gpio-davinci.txt +F: Documentation/devicetree/bindings/gpio/gpio-davinci.yaml F: drivers/gpio/gpio-davinci.c TI DAVINCI SERIES MEDIA DRIVER From 45ca16072b700f1e62a908f2de4a12d39edbb49e Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 31 May 2021 21:07:53 +0900 Subject: [PATCH 53/57] dt-bindings: gpio: zynq: convert bindings to YAML Convert gpio for Xilinx Zynq SoC bindings documentation to YAML. Signed-off-by: Nobuhiro Iwamatsu Reviewed-by: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Bartosz Golaszewski --- .../devicetree/bindings/gpio/gpio-zynq.txt | 36 ----------- .../devicetree/bindings/gpio/gpio-zynq.yaml | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 36 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-zynq.txt create mode 100644 Documentation/devicetree/bindings/gpio/gpio-zynq.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt b/Documentation/devicetree/bindings/gpio/gpio-zynq.txt deleted file mode 100644 index f693e82b4c0f..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt +++ /dev/null @@ -1,36 +0,0 @@ -Xilinx Zynq GPIO controller Device Tree Bindings -------------------------------------------- - -Required properties: -- #gpio-cells : Should be two - - First cell is the GPIO line number - - Second cell is used to specify optional - parameters (unused) -- compatible : Should be "xlnx,zynq-gpio-1.0" or - "xlnx,zynqmp-gpio-1.0" or "xlnx,versal-gpio-1.0 - or "xlnx,pmc-gpio-1.0 -- clocks : Clock specifier (see clock bindings for details) -- gpio-controller : Marks the device node as a GPIO controller. -- interrupts : Interrupt specifier (see interrupt bindings for - details) -- interrupt-controller : Marks the device node as an interrupt controller. -- #interrupt-cells : Should be 2. The first cell is the GPIO number. - The second cell bits[3:0] is used to specify trigger type and level flags: - 1 = low-to-high edge triggered. - 2 = high-to-low edge triggered. - 4 = active high level-sensitive. - 8 = active low level-sensitive. -- reg : Address and length of the register set for the device - -Example: - gpio@e000a000 { - #gpio-cells = <2>; - compatible = "xlnx,zynq-gpio-1.0"; - clocks = <&clkc 42>; - gpio-controller; - interrupt-parent = <&intc>; - interrupts = <0 20 4>; - interrupt-controller; - #interrupt-cells = <2>; - reg = <0xe000a000 0x1000>; - }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml new file mode 100644 index 000000000000..378da2649e66 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-zynq.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx Zynq GPIO controller Device Tree Bindings + +maintainers: + - Michal Simek + +properties: + compatible: + const: xlnx,zynq-gpio-1.0 + + reg: + maxItems: 1 + + "#gpio-cells": + const: 2 + + interrupts: + maxItems: 1 + + gpio-controller: true + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - "#gpio-cells" + - interrupts + - gpio-controller + - interrupt-controller + - "#interrupt-cells" + - clocks + +additionalProperties: false + +examples: + - | + gpio@e000a000 { + #gpio-cells = <2>; + compatible = "xlnx,zynq-gpio-1.0"; + clocks = <&clkc 42>; + gpio-controller; + interrupt-parent = <&intc>; + interrupts = <0 20 4>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xe000a000 0x1000>; + }; From eda627f6be8aede0e4a80fd0274a2ba944d40f2c Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Thu, 3 Jun 2021 15:59:45 +0200 Subject: [PATCH 54/57] dt-bindings: gpio: stp: convert to json-schema Convert the Lantiq STP Device Tree binding documentation to json-schema. Add the missing pinctrl property to the example. Add missing lantiq,phy3 and lantiq,phy4 bindings for xRX300 and xRX330 SoCs. Signed-off-by: Aleksander Jan Bajkowski Acked-by: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Bartosz Golaszewski --- .../bindings/gpio/gpio-stp-xway.txt | 42 -------- .../bindings/gpio/gpio-stp-xway.yaml | 99 +++++++++++++++++++ 2 files changed, 99 insertions(+), 42 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt create mode 100644 Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt deleted file mode 100644 index 78458adbf4b7..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt +++ /dev/null @@ -1,42 +0,0 @@ -Lantiq SoC Serial To Parallel (STP) GPIO controller - -The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a -peripheral controller used to drive external shift register cascades. At most -3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem -to drive the 2 LSBs of the cascade automatically. - - -Required properties: -- compatible : Should be "lantiq,gpio-stp-xway" -- reg : Address and length of the register set for the device -- #gpio-cells : Should be two. The first cell is the pin number and - the second cell is used to specify optional parameters (currently - unused). -- gpio-controller : Marks the device node as a gpio controller. - -Optional properties: -- lantiq,shadow : The default value that we shall assume as already set on the - shift register cascade. -- lantiq,groups : Set the 3 bit mask to select which of the 3 groups are enabled - in the shift register cascade. -- lantiq,dsl : The dsl core can control the 2 LSBs of the gpio cascade. This 2 bit - property can enable this feature. -- lantiq,phy1 : The gphy1 core can control 3 bits of the gpio cascade. -- lantiq,phy2 : The gphy2 core can control 3 bits of the gpio cascade. -- lantiq,rising : use rising instead of falling edge for the shift register - -Example: - -gpio1: stp@e100bb0 { - compatible = "lantiq,gpio-stp-xway"; - reg = <0xE100BB0 0x40>; - #gpio-cells = <2>; - gpio-controller; - - lantiq,shadow = <0xffff>; - lantiq,groups = <0x7>; - lantiq,dsl = <0x3>; - lantiq,phy1 = <0x7>; - lantiq,phy2 = <0x7>; - /* lantiq,rising; */ -}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml new file mode 100644 index 000000000000..d565c4b63dbf --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-stp-xway.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lantiq SoC Serial To Parallel (STP) GPIO controller + +description: | + The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a + peripheral controller used to drive external shift register cascades. At most + 3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem + and Ethernet PHYs to drive some bytes of the cascade automatically. + +maintainers: + - John Crispin + +properties: + $nodename: + pattern: "^gpio@[0-9a-f]+$" + + compatible: + const: lantiq,gpio-stp-xway + + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + description: + The first cell is the pin number and the second cell is used to specify + consumer flags. + const: 2 + + lantiq,shadow: + description: + The default value that we shall assume as already set on the + shift register cascade. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x000000 + maximum: 0xffffff + + lantiq,groups: + description: + Set the 3 bit mask to select which of the 3 groups are enabled + in the shift register cascade. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x0 + maximum: 0x7 + + lantiq,dsl: + description: + The dsl core can control the 2 LSBs of the gpio cascade. This 2 bit + property can enable this feature. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x0 + maximum: 0x3 + + lantiq,rising: + description: + Use rising instead of falling edge for the shift register. + type: boolean + +patternProperties: + "^lantiq,phy[1-4]$": + description: + The gphy core can control 3 bits of the gpio cascade. In the xRX200 family + phy[1-2] are available, in xRX330 phy[1-3] and in XRX330 phy[1-4]. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x0 + maximum: 0x7 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + gpio@e100bb0 { + compatible = "lantiq,gpio-stp-xway"; + reg = <0xE100BB0 0x40>; + #gpio-cells = <2>; + gpio-controller; + + pinctrl-0 = <&stp_pins>; + pinctrl-names = "default"; + + lantiq,shadow = <0xffffff>; + lantiq,groups = <0x7>; + lantiq,dsl = <0x3>; + lantiq,phy1 = <0x7>; + lantiq,phy2 = <0x7>; + }; +... From cdee1d6222546e9ec886b1deb241ab9566517d97 Mon Sep 17 00:00:00 2001 From: Jinchao Wang Date: Thu, 24 Jun 2021 18:15:17 +0800 Subject: [PATCH 55/57] gpio: mxs: Prefer unsigned int to bare use of unsigned Fix checkpatch warnings: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' Signed-off-by: Jinchao Wang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mxs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 524b668eb1ac..31a336b86ff2 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -229,14 +229,14 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) return rv; } -static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); return irq_find_mapping(port->domain, offset); } -static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); u32 mask = 1 << offset; From d766dfee58e19d5781f6f9acb5092376742e7888 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 1 Jun 2021 17:25:47 +0200 Subject: [PATCH 56/57] dt-bindings: gpio: pcf857x: Convert to json-schema Convert the PCF857x-compatible I/O expanders Device Tree binding documentation to json-schema. Document missing compatible values, properties, and gpio hogs. Signed-off-by: Geert Uytterhoeven Reviewed-by: Rob Herring Reviewed-by: Linus Walleij Signed-off-by: Bartosz Golaszewski --- .../devicetree/bindings/gpio/gpio-pcf857x.txt | 69 ------------ .../devicetree/bindings/gpio/nxp,pcf8575.yaml | 103 ++++++++++++++++++ 2 files changed, 103 insertions(+), 69 deletions(-) delete mode 100644 Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt create mode 100644 Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt deleted file mode 100644 index a482455a205b..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt +++ /dev/null @@ -1,69 +0,0 @@ -* PCF857x-compatible I/O expanders - -The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be -driven high by a pull-up current source or driven low to ground. This combines -the direction and output level into a single bit per line, which can't be read -back. We can't actually know at initialization time whether a line is configured -(a) as output and driving the signal low/high, or (b) as input and reporting a -low/high value, without knowing the last value written since the chip came out -of reset (if any). The only reliable solution for setting up line direction is -thus to do it explicitly. - -Required Properties: - - - compatible: should be one of the following. - - "maxim,max7328": For the Maxim MAX7378 - - "maxim,max7329": For the Maxim MAX7329 - - "nxp,pca8574": For the NXP PCA8574 - - "nxp,pca8575": For the NXP PCA8575 - - "nxp,pca9670": For the NXP PCA9670 - - "nxp,pca9671": For the NXP PCA9671 - - "nxp,pca9672": For the NXP PCA9672 - - "nxp,pca9673": For the NXP PCA9673 - - "nxp,pca9674": For the NXP PCA9674 - - "nxp,pca9675": For the NXP PCA9675 - - "nxp,pcf8574": For the NXP PCF8574 - - "nxp,pcf8574a": For the NXP PCF8574A - - "nxp,pcf8575": For the NXP PCF8575 - - - reg: I2C slave address. - - - gpio-controller: Marks the device node as a gpio controller. - - #gpio-cells: Should be 2. The first cell is the GPIO number and the second - cell specifies GPIO flags, as defined in . Only the - GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported. - -Optional Properties: - - - lines-initial-states: Bitmask that specifies the initial state of each - line. When a bit is set to zero, the corresponding line will be initialized to - the input (pulled-up) state. When the bit is set to one, the line will be - initialized the low-level output state. If the property is not specified - all lines will be initialized to the input state. - - The I/O expander can detect input state changes, and thus optionally act as - an interrupt controller. When the expander interrupt line is connected all the - following properties must be set. For more information please see the - interrupt controller device tree bindings documentation available at - Documentation/devicetree/bindings/interrupt-controller/interrupts.txt. - - - interrupt-controller: Identifies the node as an interrupt controller. - - #interrupt-cells: Number of cells to encode an interrupt source, shall be 2. - - interrupts: Interrupt specifier for the controllers interrupt. - - -Please refer to gpio.txt in this directory for details of the common GPIO -bindings used by client devices. - -Example: PCF8575 I/O expander node - - pcf8575: gpio@20 { - compatible = "nxp,pcf8575"; - reg = <0x20>; - interrupt-parent = <&irqpin2>; - interrupts = <3 0>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - }; diff --git a/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml new file mode 100644 index 000000000000..f0ff66c4c74e --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/nxp,pcf8575.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PCF857x-compatible I/O expanders + +maintainers: + - Laurent Pinchart + +description: + The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be + driven high by a pull-up current source or driven low to ground. This + combines the direction and output level into a single bit per line, which + can't be read back. We can't actually know at initialization time whether a + line is configured (a) as output and driving the signal low/high, or (b) as + input and reporting a low/high value, without knowing the last value written + since the chip came out of reset (if any). The only reliable solution for + setting up line direction is thus to do it explicitly. + +properties: + compatible: + enum: + - maxim,max7328 + - maxim,max7329 + - nxp,pca8574 + - nxp,pca8575 + - nxp,pca9670 + - nxp,pca9671 + - nxp,pca9672 + - nxp,pca9673 + - nxp,pca9674 + - nxp,pca9675 + - nxp,pcf8574 + - nxp,pcf8574a + - nxp,pcf8575 + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + description: + The first cell is the GPIO number and the second cell specifies GPIO + flags, as defined in . Only the GPIO_ACTIVE_HIGH + and GPIO_ACTIVE_LOW flags are supported. + + lines-initial-states: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bitmask that specifies the initial state of each line. + When a bit is set to zero, the corresponding line will be initialized to + the input (pulled-up) state. + When the bit is set to one, the line will be initialized to the + low-level output state. + If the property is not specified all lines will be initialized to the + input state. + + interrupts: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + wakeup-source: true + +patternProperties: + "^(.+-hog(-[0-9]+)?)$": + type: object + + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - '#gpio-cells' + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pcf8575: gpio@20 { + compatible = "nxp,pcf8575"; + reg = <0x20>; + interrupt-parent = <&irqpin2>; + interrupts = <3 0>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; From c34c1228fc1cfe83aed909995f5b82e0ab7cb977 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Jun 2021 08:27:29 +0200 Subject: [PATCH 57/57] docs: driver-api: gpio: using-gpio.rst: avoid using ReST :doc:`foo` markup The :doc:`foo` tag is auto-generated via automarkup.py. So, use the filename at the sources, instead of :doc:`foo`. Reviewed-by: Linus Walleij Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Bartosz Golaszewski --- Documentation/driver-api/gpio/using-gpio.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/driver-api/gpio/using-gpio.rst b/Documentation/driver-api/gpio/using-gpio.rst index dda069444032..64c8d3f76c3a 100644 --- a/Documentation/driver-api/gpio/using-gpio.rst +++ b/Documentation/driver-api/gpio/using-gpio.rst @@ -9,13 +9,13 @@ with them. For examples of already existing generic drivers that will also be good examples for any other kernel drivers you want to author, refer to -:doc:`drivers-on-gpio` +Documentation/driver-api/gpio/drivers-on-gpio.rst For any kind of mass produced system you want to support, such as servers, laptops, phones, tablets, routers, and any consumer or office or business goods using appropriate kernel drivers is paramount. Submit your code for inclusion in the upstream Linux kernel when you feel it is mature enough and you will get -help to refine it, see :doc:`../../process/submitting-patches`. +help to refine it, see Documentation/process/submitting-patches.rst. In Linux GPIO lines also have a userspace ABI.