From f9f890ba2b13ea9ccfffd0e7354c7b64d9109790 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Thu, 30 Jul 2020 18:28:01 +0300 Subject: gpio: dwapb: Add max GPIOs macro Add a new macro DWAPB_MAX_GPIOS which defines the maximum possible number of GPIO lines corresponding to the maximum DW APB GPIO controller port width. Use the new macro instead of number literal 32 where it's applicable. Suggested-by: Andy Shevchenko Signed-off-by: Serge Semin Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200730152808.2955-5-Sergey.Semin@baikalelectronics.ru Signed-off-by: Linus Walleij --- include/linux/platform_data/gpio-dwapb.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/platform_data/gpio-dwapb.h b/include/linux/platform_data/gpio-dwapb.h index ff1be737bad6..0aa5c6720259 100644 --- a/include/linux/platform_data/gpio-dwapb.h +++ b/include/linux/platform_data/gpio-dwapb.h @@ -6,12 +6,14 @@ #ifndef GPIO_DW_APB_H #define GPIO_DW_APB_H +#define DWAPB_MAX_GPIOS 32 + struct dwapb_port_property { struct fwnode_handle *fwnode; unsigned int idx; unsigned int ngpio; unsigned int gpio_base; - int irq[32]; + int irq[DWAPB_MAX_GPIOS]; bool irq_shared; }; -- cgit v1.2.3 From d284c16f84c9f8facdde25c9c077cfdcb66163d5 Mon Sep 17 00:00:00 2001 From: dillon min Date: Thu, 3 Sep 2020 15:30:22 +0800 Subject: gpio: tc35894: Disable Direct KBD interrupts to enable gpio irq On tc35894, have to disable direct keypad interrupts to make it as general purpose interrupts functionality work. if not, after chip reset, IRQST(0x91) will always 0x20, IRQN always low level, can't be clear. Configure DIRECTx to enable general purpose gpio mode, else read GPIOMISx register always zero in irq routine. verified on tc35894, need more test on other tc3589x. Signed-off-by: dillon min Acked-by: Lee Jones Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-tc3589x.c | 18 ++++++++++++++++-- include/linux/mfd/tc3589x.h | 6 ++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 58b0da9eb76f..79d285b845dc 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -19,9 +19,9 @@ * These registers are modified under the irq bus lock and cached to avoid * unnecessary writes in bus_sync_unlock. */ -enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; +enum { REG_IBE, REG_IEV, REG_IS, REG_IE, REG_DIRECT }; -#define CACHE_NR_REGS 4 +#define CACHE_NR_REGS 5 #define CACHE_NR_BANKS 3 struct tc3589x_gpio { @@ -200,6 +200,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) [REG_IEV] = TC3589x_GPIOIEV0, [REG_IS] = TC3589x_GPIOIS0, [REG_IE] = TC3589x_GPIOIE0, + [REG_DIRECT] = TC3589x_DIRECT0, }; int i, j; @@ -228,6 +229,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d) int mask = BIT(offset % 8); tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; + tc3589x_gpio->regs[REG_DIRECT][regoffset] |= mask; } static void tc3589x_gpio_irq_unmask(struct irq_data *d) @@ -239,6 +241,7 @@ static void tc3589x_gpio_irq_unmask(struct irq_data *d) int mask = BIT(offset % 8); tc3589x_gpio->regs[REG_IE][regoffset] |= mask; + tc3589x_gpio->regs[REG_DIRECT][regoffset] &= ~mask; } static struct irq_chip tc3589x_gpio_irq_chip = { @@ -334,6 +337,17 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) if (ret < 0) return ret; + /* For tc35894, have to disable Direct KBD interrupts, + * else IRQST will always be 0x20, IRQN low level, can't + * clear the irq status. + * TODO: need more test on other tc3589x chip. + * + */ + ret = tc3589x_reg_write(tc3589x, TC3589x_DKBDMSK, + TC3589x_DKBDMSK_ELINT | TC3589x_DKBDMSK_EINT); + if (ret < 0) + return ret; + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT, "tc3589x-gpio", diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h index bb2b19599761..b84955410e03 100644 --- a/include/linux/mfd/tc3589x.h +++ b/include/linux/mfd/tc3589x.h @@ -19,6 +19,9 @@ enum tx3589x_block { #define TC3589x_RSTCTRL_KBDRST (1 << 1) #define TC3589x_RSTCTRL_GPIRST (1 << 0) +#define TC3589x_DKBDMSK_ELINT (1 << 1) +#define TC3589x_DKBDMSK_EINT (1 << 0) + /* Keyboard Configuration Registers */ #define TC3589x_KBDSETTLE_REG 0x01 #define TC3589x_KBDBOUNCE 0x02 @@ -101,6 +104,9 @@ enum tx3589x_block { #define TC3589x_GPIOODM2 0xE4 #define TC3589x_GPIOODE2 0xE5 +#define TC3589x_DIRECT0 0xEC +#define TC3589x_DKBDMSK 0xF3 + #define TC3589x_INT_GPIIRQ 0 #define TC3589x_INT_TI0IRQ 1 #define TC3589x_INT_TI1IRQ 2 -- cgit v1.2.3 From 6b6ff4acb310a0351005474673f1e09a90020efd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Sep 2020 10:54:24 +0200 Subject: device: property: add helpers to count items in string arrays Instead of doing the following: count = device_property_read_string_array(dev, propname, NULL, 0); Let's provide inline helpers with hardcoded arguments for counting strings in property arrays. Suggested-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski Reviewed-by: Mika Westerberg Reviewed-by: Andy Shevchenko --- include/linux/property.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/linux') diff --git a/include/linux/property.h b/include/linux/property.h index 9f805c442819..75c178055bc9 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -170,6 +170,12 @@ static inline int device_property_count_u64(struct device *dev, const char *prop return device_property_read_u64_array(dev, propname, NULL, 0); } +static inline int device_property_string_array_count(struct device *dev, + const char *propname) +{ + return device_property_read_string_array(dev, propname, NULL, 0); +} + static inline bool fwnode_property_read_bool(const struct fwnode_handle *fwnode, const char *propname) { @@ -224,6 +230,13 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode, return fwnode_property_read_u64_array(fwnode, propname, NULL, 0); } +static inline int +fwnode_property_string_array_count(const struct fwnode_handle *fwnode, + const char *propname) +{ + return fwnode_property_read_string_array(fwnode, propname, NULL, 0); +} + struct software_node; /** -- cgit v1.2.3 From 7cba1a4d5e1628e099728d849918de50dab2e24e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Sep 2020 10:54:25 +0200 Subject: gpiolib: generalize devprop_gpiochip_set_names() for device properties devprop_gpiochip_set_names() is overly complicated with taking the fwnode argument (which requires using dev_fwnode() & of_fwnode_handle() in ACPI and OF GPIO code respectively). Let's just switch to using the generic device properties. This allows us to pull the code setting line names directly into gpiochip_add_data_with_key() instead of handling it separately for ACPI and OF. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko Reviewed-by: Mika Westerberg --- drivers/gpio/gpiolib-acpi.c | 3 --- drivers/gpio/gpiolib-devprop.c | 20 ++++++++++---------- drivers/gpio/gpiolib-of.c | 5 ----- drivers/gpio/gpiolib.c | 8 ++++---- include/linux/gpio/driver.h | 3 +-- 5 files changed, 15 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 9276051663da..e8dc58f771d8 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -1221,9 +1221,6 @@ void acpi_gpiochip_add(struct gpio_chip *chip) return; } - if (!chip->names) - devprop_gpiochip_set_names(chip, dev_fwnode(chip->parent)); - acpi_gpiochip_request_regions(acpi_gpio); acpi_gpiochip_scan_gpios(acpi_gpio); acpi_walk_dep_device_list(handle); diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c index 26741032fa9e..31599d89a85d 100644 --- a/drivers/gpio/gpiolib-devprop.c +++ b/drivers/gpio/gpiolib-devprop.c @@ -17,25 +17,23 @@ /** * devprop_gpiochip_set_names - Set GPIO line names using device properties * @chip: GPIO chip whose lines should be named, if possible - * @fwnode: Property Node containing the gpio-line-names property * * Looks for device property "gpio-line-names" and if it exists assigns * GPIO line names for the chip. The memory allocated for the assigned - * names belong to the underlying firmware node and should not be released + * names belong to the underlying software node and should not be released * by the caller. */ -void devprop_gpiochip_set_names(struct gpio_chip *chip, - const struct fwnode_handle *fwnode) +int devprop_gpiochip_set_names(struct gpio_chip *chip) { struct gpio_device *gdev = chip->gpiodev; + struct device *dev = chip->parent; const char **names; int ret, i; int count; - count = fwnode_property_read_string_array(fwnode, "gpio-line-names", - NULL, 0); + count = device_property_string_array_count(dev, "gpio-line-names"); if (count < 0) - return; + return 0; if (count > gdev->ngpio) { dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d", @@ -45,19 +43,21 @@ void devprop_gpiochip_set_names(struct gpio_chip *chip, names = kcalloc(count, sizeof(*names), GFP_KERNEL); if (!names) - return; + return -ENOMEM; - ret = fwnode_property_read_string_array(fwnode, "gpio-line-names", + ret = device_property_read_string_array(dev, "gpio-line-names", names, count); if (ret < 0) { dev_warn(&gdev->dev, "failed to read GPIO line names\n"); kfree(names); - return; + return ret; } for (i = 0; i < count; i++) gdev->descs[i].name = names[i]; kfree(names); + + return 0; } EXPORT_SYMBOL_GPL(devprop_gpiochip_set_names); diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index bd31dd3b6a75..2f895a2b8411 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -1026,11 +1026,6 @@ int of_gpiochip_add(struct gpio_chip *chip) if (ret) return ret; - /* If the chip defines names itself, these take precedence */ - if (!chip->names) - devprop_gpiochip_set_names(chip, - of_fwnode_handle(chip->of_node)); - of_node_get(chip->of_node); ret = of_gpiochip_scan_gpios(chip); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 03543b8f7ab4..d50e111b0d95 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -340,9 +340,6 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) struct gpio_device *gdev = gc->gpiodev; int i; - if (!gc->names) - return 0; - /* First check all names if they are unique */ for (i = 0; i != gc->ngpio; ++i) { struct gpio_desc *gpio; @@ -621,7 +618,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, INIT_LIST_HEAD(&gdev->pin_ranges); #endif - ret = gpiochip_set_desc_names(gc); + if (gc->names) + ret = gpiochip_set_desc_names(gc); + else + ret = devprop_gpiochip_set_names(gc); if (ret) goto err_remove_from_list; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index d1cef5c2715c..56485a040b82 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -756,8 +756,7 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, enum gpiod_flags dflags); void gpiochip_free_own_desc(struct gpio_desc *desc); -void devprop_gpiochip_set_names(struct gpio_chip *gc, - const struct fwnode_handle *fwnode); +int devprop_gpiochip_set_names(struct gpio_chip *gc); #ifdef CONFIG_GPIOLIB -- cgit v1.2.3 From 32fc5aa2df12c7a95dbd1c2c9ee3eb8d7f920d9e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 9 Sep 2020 10:54:26 +0200 Subject: gpiolib: unexport devprop_gpiochip_set_names() Now that devprop_gpiochip_set_names() is only used in a single place inside drivers/gpio/gpiolib.c, there's no need anymore for it to be exported or to even live in its own source file. Pull this function into the core source file for gpiolib. Signed-off-by: Bartosz Golaszewski Reviewed-by: Mika Westerberg Reviewed-by: Andy Shevchenko --- drivers/gpio/Makefile | 1 - drivers/gpio/gpiolib-devprop.c | 63 ------------------------------------------ drivers/gpio/gpiolib.c | 47 +++++++++++++++++++++++++++++++ include/linux/gpio/driver.h | 2 -- 4 files changed, 47 insertions(+), 66 deletions(-) delete mode 100644 drivers/gpio/gpiolib-devprop.c (limited to 'include/linux') diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4f9abff4f2dc..639275eb4e4d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -6,7 +6,6 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIOLIB) += gpiolib-devres.o obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o -obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o obj-$(CONFIG_GPIOLIB) += gpiolib-cdev.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c deleted file mode 100644 index 31599d89a85d..000000000000 --- a/drivers/gpio/gpiolib-devprop.c +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Device property helpers for GPIO chips. - * - * Copyright (C) 2016, Intel Corporation - * Author: Mika Westerberg - */ - -#include -#include -#include -#include -#include - -#include "gpiolib.h" - -/** - * devprop_gpiochip_set_names - Set GPIO line names using device properties - * @chip: GPIO chip whose lines should be named, if possible - * - * Looks for device property "gpio-line-names" and if it exists assigns - * GPIO line names for the chip. The memory allocated for the assigned - * names belong to the underlying software node and should not be released - * by the caller. - */ -int devprop_gpiochip_set_names(struct gpio_chip *chip) -{ - struct gpio_device *gdev = chip->gpiodev; - struct device *dev = chip->parent; - const char **names; - int ret, i; - int count; - - count = device_property_string_array_count(dev, "gpio-line-names"); - if (count < 0) - return 0; - - if (count > gdev->ngpio) { - dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d", - count, gdev->ngpio); - count = gdev->ngpio; - } - - names = kcalloc(count, sizeof(*names), GFP_KERNEL); - if (!names) - return -ENOMEM; - - ret = device_property_read_string_array(dev, "gpio-line-names", - names, count); - if (ret < 0) { - dev_warn(&gdev->dev, "failed to read GPIO line names\n"); - kfree(names); - return ret; - } - - for (i = 0; i < count; i++) - gdev->descs[i].name = names[i]; - - kfree(names); - - return 0; -} -EXPORT_SYMBOL_GPL(devprop_gpiochip_set_names); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d50e111b0d95..b7b608ef9e6b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -358,6 +358,53 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) return 0; } +/* + * devprop_gpiochip_set_names - Set GPIO line names using device properties + * @chip: GPIO chip whose lines should be named, if possible + * + * Looks for device property "gpio-line-names" and if it exists assigns + * GPIO line names for the chip. The memory allocated for the assigned + * names belong to the underlying software node and should not be released + * by the caller. + */ +static int devprop_gpiochip_set_names(struct gpio_chip *chip) +{ + struct gpio_device *gdev = chip->gpiodev; + struct device *dev = chip->parent; + const char **names; + int ret, i; + int count; + + count = device_property_string_array_count(dev, "gpio-line-names"); + if (count < 0) + return 0; + + if (count > gdev->ngpio) { + dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d", + count, gdev->ngpio); + count = gdev->ngpio; + } + + names = kcalloc(count, sizeof(*names), GFP_KERNEL); + if (!names) + return -ENOMEM; + + ret = device_property_read_string_array(dev, "gpio-line-names", + names, count); + if (ret < 0) { + dev_warn(&gdev->dev, "failed to read GPIO line names\n"); + kfree(names); + return ret; + } + + for (i = 0; i < count; i++) + gdev->descs[i].name = names[i]; + + kfree(names); + + return 0; +} + static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc) { unsigned long *p; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 56485a040b82..4a7e295c3640 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -756,8 +756,6 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc, enum gpiod_flags dflags); void gpiochip_free_own_desc(struct gpio_desc *desc); -int devprop_gpiochip_set_names(struct gpio_chip *gc); - #ifdef CONFIG_GPIOLIB /* lock/unlock as IRQ */ -- cgit v1.2.3 From 0fd16012adc0a994a7ce980a78e22e4de6220778 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 29 Sep 2020 12:09:55 +0200 Subject: lib: string_helpers: provide kfree_strarray() There's a common pattern of dynamically allocating an array of char pointers and then also dynamically allocating each string in this array. Provide a helper for freeing such a string array with one call. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andy Shevchenko --- include/linux/string_helpers.h | 2 ++ lib/string_helpers.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'include/linux') diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index 86f150c2a6b6..fa06dcdc481e 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h @@ -94,4 +94,6 @@ char *kstrdup_quotable(const char *src, gfp_t gfp); char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp); char *kstrdup_quotable_file(struct file *file, gfp_t gfp); +void kfree_strarray(char **array, size_t n); + #endif diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 963050c0283e..7f2d5fbaf243 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -649,3 +649,26 @@ char *kstrdup_quotable_file(struct file *file, gfp_t gfp) return pathname; } EXPORT_SYMBOL_GPL(kstrdup_quotable_file); + +/** + * kfree_strarray - free a number of dynamically allocated strings contained + * in an array and the array itself + * + * @array: Dynamically allocated array of strings to free. + * @n: Number of strings (starting from the beginning of the array) to free. + * + * Passing a non-NULL @array and @n == 0 as well as NULL @array are valid + * use-cases. If @array is NULL, the function does nothing. + */ +void kfree_strarray(char **array, size_t n) +{ + unsigned int i; + + if (!array) + return; + + for (i = 0; i < n; i++) + kfree(array[i]); + kfree(array); +} +EXPORT_SYMBOL_GPL(kfree_strarray); -- cgit v1.2.3