From e735244e2cf068f98b6384681a38993e0517a838 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 1 Oct 2019 11:44:53 +0200 Subject: [PATCH 1/4] gpiolib: don't clear FLAG_IS_OUT when emulating open-drain/open-source When emulating open-drain/open-source by not actively driving the output lines - we're simply changing their mode to input. This is wrong as it will then make it impossible to change the value of such line - it's now considered to actually be in input mode. If we want to still use the direction_input() callback for simplicity then we need to set FLAG_IS_OUT manually in gpiod_direction_output() and not clear it in gpio_set_open_drain_value_commit() and gpio_set_open_source_value_commit(). Fixes: c663e5f56737 ("gpio: support native single-ended hardware drivers") Cc: stable@vger.kernel.org Reported-by: Kent Gibson Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bdbc1649eafa..5833e4f380d6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3070,8 +3070,10 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (!ret) goto set_output_value; /* Emulate open drain by not actively driving the line high */ - if (value) - return gpiod_direction_input(desc); + if (value) { + ret = gpiod_direction_input(desc); + goto set_output_flag; + } } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { ret = gpio_set_config(gc, gpio_chip_hwgpio(desc), @@ -3079,8 +3081,10 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) if (!ret) goto set_output_value; /* Emulate open source by not actively driving the line low */ - if (!value) - return gpiod_direction_input(desc); + if (!value) { + ret = gpiod_direction_input(desc); + goto set_output_flag; + } } else { gpio_set_config(gc, gpio_chip_hwgpio(desc), PIN_CONFIG_DRIVE_PUSH_PULL); @@ -3088,6 +3092,17 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) set_output_value: return gpiod_direction_output_raw_commit(desc, value); + +set_output_flag: + /* + * When emulating open-source or open-drain functionalities by not + * actively driving the line (setting mode to input) we still need to + * set the IS_OUT flag or otherwise we won't be able to set the line + * value anymore. + */ + if (ret == 0) + set_bit(FLAG_IS_OUT, &desc->flags); + return ret; } EXPORT_SYMBOL_GPL(gpiod_direction_output); @@ -3448,8 +3463,6 @@ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) if (value) { ret = chip->direction_input(chip, offset); - if (!ret) - clear_bit(FLAG_IS_OUT, &desc->flags); } else { ret = chip->direction_output(chip, offset, 0); if (!ret) @@ -3479,8 +3492,6 @@ static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value set_bit(FLAG_IS_OUT, &desc->flags); } else { ret = chip->direction_input(chip, offset); - if (!ret) - clear_bit(FLAG_IS_OUT, &desc->flags); } trace_gpio_direction(desc_to_gpio(desc), !value, ret); if (ret < 0) From be7ae45cfea97e787234e00e1a9eb341acacd84e Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Tue, 1 Oct 2019 11:49:21 +0200 Subject: [PATCH 2/4] gpio: fix getting nonexclusive gpiods from DT Since commit ec757001c818 ("gpio: Enable nonexclusive gpiods from DT nodes") we are able to get GPIOD_FLAGS_BIT_NONEXCLUSIVE marked gpios. Currently the gpiolib uses the wrong flags variable for the check. We need to check the gpiod_flags instead of the of_gpio_flags else we return -EBUSY for GPIOD_FLAGS_BIT_NONEXCLUSIVE marked and requested gpiod's. Fixes: ec757001c818 gpio: Enable nonexclusive gpiods from DT nodes Cc: stable@vger.kernel.org Signed-off-by: Marco Felsch [Bartosz: the function was moved to gpiolib-of.c so updated the patch] Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 1eea2c6c2e1d..80ea49f570f4 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -317,7 +317,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, transitory = flags & OF_GPIO_TRANSITORY; ret = gpiod_request(desc, label); - if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) + if (ret == -EBUSY && (dflags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) return desc; if (ret) return ERR_PTR(ret); From e91aafcb51f3c5001ae76c3ee027beb0b8506447 Mon Sep 17 00:00:00 2001 From: Bruce Chen Date: Mon, 16 Sep 2019 17:56:56 +0800 Subject: [PATCH 3/4] gpio: eic: sprd: Fix the incorrect EIC offset when toggling When toggling the level trigger to emulate the edge trigger, the EIC offset is incorrect without adding the corresponding bank index, thus fix it. Fixes: 7bf0d7f62282 ("gpio: eic: Add edge trigger emulation for EIC") Cc: stable@vger.kernel.org Signed-off-by: Bruce Chen Signed-off-by: Baolin Wang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-eic-sprd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index fe7a73f52329..bb287f35cf40 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -530,11 +530,12 @@ static void sprd_eic_handle_one_type(struct gpio_chip *chip) } for_each_set_bit(n, ®, SPRD_EIC_PER_BANK_NR) { - girq = irq_find_mapping(chip->irq.domain, - bank * SPRD_EIC_PER_BANK_NR + n); + u32 offset = bank * SPRD_EIC_PER_BANK_NR + n; + + girq = irq_find_mapping(chip->irq.domain, offset); generic_handle_irq(girq); - sprd_eic_toggle_trigger(chip, girq, n); + sprd_eic_toggle_trigger(chip, girq, offset); } } } From fffa6af94894126994a7600c6f6f09b892e89fa9 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 2 Oct 2019 14:28:23 +0200 Subject: [PATCH 4/4] gpio: max77620: Use correct unit for debounce times The gpiod_set_debounce() function takes the debounce time in microseconds. Adjust the switch/case values in the MAX77620 GPIO to use the correct unit. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20191002122825.3948322-1-thierry.reding@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max77620.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index 47d05e357e61..faf86ea9c51a 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -192,13 +192,13 @@ static int max77620_gpio_set_debounce(struct max77620_gpio *mgpio, case 0: val = MAX77620_CNFG_GPIO_DBNC_None; break; - case 1 ... 8: + case 1000 ... 8000: val = MAX77620_CNFG_GPIO_DBNC_8ms; break; - case 9 ... 16: + case 9000 ... 16000: val = MAX77620_CNFG_GPIO_DBNC_16ms; break; - case 17 ... 32: + case 17000 ... 32000: val = MAX77620_CNFG_GPIO_DBNC_32ms; break; default: