diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2020-09-21 23:39:50 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2020-09-21 23:39:50 +0200 |
commit | 36eccdb58fb55d2bea6a0e62932e4d7e5192d409 (patch) | |
tree | 08140adddc264c9445a9e6dd7cf9c92cb5de5a1a /drivers/gpio | |
parent | 0a2d411b56b7c661e753bbea568f6b04c4a961c5 (diff) | |
parent | 587823d39f85ff9777a862019eca720b97a16a52 (diff) |
Merge tag 'gpio-updates-for-v5.10-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into devel
gpio updates for v5.10 - part 1
- automatically drive GPHY leds in gpio-stp-xway
- refactor ->{get, set}_multiple() in gpio-aggregator
- add support for a new model in rcar-gpio DT bindings
- simplify several GPIO drivers with dev_err_probe()
- disable Direct KBD interrupts in gpio-tc35894
- use DEFINE_SEQ_ATTRIBUTE() in GPIO chardev to shrink code
- switch to using a simpler IDA API in gpiolib
- make devprop_gpiochip_set_names() more generic by using device properties
instead of using fwnode helpers
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-aggregator.c | 70 | ||||
-rw-r--r-- | drivers/gpio/gpio-bcm-kona.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-davinci.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-pisosr.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-stp-xway.c | 54 | ||||
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 18 | ||||
-rw-r--r-- | drivers/gpio/gpio-zynq.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 3 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-devprop.c | 63 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 84 |
14 files changed, 181 insertions, 161 deletions
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/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 424a3d25350b..dfd8a4876a27 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -333,20 +333,14 @@ static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset) return gpiod_get_value(fwd->descs[offset]); } -static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask, +static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, unsigned long *bits) { - struct gpiochip_fwd *fwd = gpiochip_get_data(chip); - unsigned long *values, flags = 0; struct gpio_desc **descs; + unsigned long *values; unsigned int i, j = 0; int error; - if (chip->can_sleep) - mutex_lock(&fwd->mlock); - else - spin_lock_irqsave(&fwd->slock, flags); - /* Both values bitmap and desc pointers are stored in tmp[] */ values = &fwd->tmp[0]; descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)]; @@ -356,16 +350,32 @@ static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask, descs[j++] = fwd->descs[i]; error = gpiod_get_array_value(j, descs, NULL, values); - if (!error) { - j = 0; - for_each_set_bit(i, mask, fwd->chip.ngpio) - __assign_bit(i, bits, test_bit(j++, values)); - } + if (error) + return error; - if (chip->can_sleep) + j = 0; + for_each_set_bit(i, mask, fwd->chip.ngpio) + __assign_bit(i, bits, test_bit(j++, values)); + + return 0; +} + +static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + unsigned long flags; + int error; + + if (chip->can_sleep) { + mutex_lock(&fwd->mlock); + error = gpio_fwd_get_multiple(fwd, mask, bits); mutex_unlock(&fwd->mlock); - else + } else { + spin_lock_irqsave(&fwd->slock, flags); + error = gpio_fwd_get_multiple(fwd, mask, bits); spin_unlock_irqrestore(&fwd->slock, flags); + } return error; } @@ -377,19 +387,13 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) gpiod_set_value(fwd->descs[offset], value); } -static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask, +static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, unsigned long *bits) { - struct gpiochip_fwd *fwd = gpiochip_get_data(chip); - unsigned long *values, flags = 0; struct gpio_desc **descs; + unsigned long *values; unsigned int i, j = 0; - if (chip->can_sleep) - mutex_lock(&fwd->mlock); - else - spin_lock_irqsave(&fwd->slock, flags); - /* Both values bitmap and desc pointers are stored in tmp[] */ values = &fwd->tmp[0]; descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)]; @@ -400,11 +404,23 @@ static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask, } gpiod_set_array_value(j, descs, NULL, values); +} - if (chip->can_sleep) +static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) +{ + struct gpiochip_fwd *fwd = gpiochip_get_data(chip); + unsigned long flags; + + if (chip->can_sleep) { + mutex_lock(&fwd->mlock); + gpio_fwd_set_multiple(fwd, mask, bits); mutex_unlock(&fwd->mlock); - else + } else { + spin_lock_irqsave(&fwd->slock, flags); + gpio_fwd_set_multiple(fwd, mask, bits); spin_unlock_irqrestore(&fwd->slock, flags); + } } static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset, @@ -470,9 +486,9 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev, chip->direction_input = gpio_fwd_direction_input; chip->direction_output = gpio_fwd_direction_output; chip->get = gpio_fwd_get; - chip->get_multiple = gpio_fwd_get_multiple; + chip->get_multiple = gpio_fwd_get_multiple_locked; chip->set = gpio_fwd_set; - chip->set_multiple = gpio_fwd_set_multiple; + chip->set_multiple = gpio_fwd_set_multiple_locked; chip->base = -1; chip->ngpio = ngpios; fwd->descs = descs; diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index cf3687a7925f..1e6b427f2c4a 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -590,10 +590,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) dev_err(dev, "Couldn't determine # GPIO banks\n"); return -ENOENT; } else if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Couldn't determine GPIO banks: (%pe)\n", - ERR_PTR(ret)); - return ret; + return dev_err_probe(dev, ret, "Couldn't determine GPIO banks\n"); } kona_gpio->num_bank = ret; diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 085b874db2a9..6f2138503726 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -237,12 +237,8 @@ static int davinci_gpio_probe(struct platform_device *pdev) for (i = 0; i < nirq; i++) { chips->irqs[i] = platform_get_irq(pdev, i); - if (chips->irqs[i] < 0) { - if (chips->irqs[i] != -EPROBE_DEFER) - dev_info(dev, "IRQ not populated, err = %d\n", - chips->irqs[i]); - return chips->irqs[i]; - } + if (chips->irqs[i] < 0) + return dev_err_probe(dev, chips->irqs[i], "IRQ not populated\n"); } chips->chip.label = dev_name(dev); diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 7fbe0c9e1fc1..2dc12f4addbd 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1394,10 +1394,7 @@ static int omap_gpio_probe(struct platform_device *pdev) if (bank->irq <= 0) { if (!bank->irq) bank->irq = -ENXIO; - if (bank->irq != -EPROBE_DEFER) - dev_err(dev, - "can't get irq resource ret=%d\n", bank->irq); - return bank->irq; + return dev_err_probe(dev, bank->irq, "can't get irq resource\n"); } bank->chip.parent = dev; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index bd2e96c34f82..b5c3e56613a7 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1000,12 +1000,9 @@ static int pca953x_probe(struct i2c_client *client, chip->client = client; reg = devm_regulator_get(&client->dev, "vcc"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - if (ret != -EPROBE_DEFER) - dev_err(&client->dev, "reg get err: %d\n", ret); - return ret; - } + if (IS_ERR(reg)) + return dev_err_probe(&client->dev, PTR_ERR(reg), "reg get err\n"); + ret = regulator_enable(reg); if (ret) { dev_err(&client->dev, "reg en err: %d\n", ret); diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c index 6698feabaced..8e04054cf07e 100644 --- a/drivers/gpio/gpio-pisosr.c +++ b/drivers/gpio/gpio-pisosr.c @@ -148,12 +148,9 @@ static int pisosr_gpio_probe(struct spi_device *spi) return -ENOMEM; gpio->load_gpio = devm_gpiod_get_optional(dev, "load", GPIOD_OUT_LOW); - if (IS_ERR(gpio->load_gpio)) { - ret = PTR_ERR(gpio->load_gpio); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Unable to allocate load GPIO\n"); - return ret; - } + if (IS_ERR(gpio->load_gpio)) + return dev_err_probe(dev, PTR_ERR(gpio->load_gpio), + "Unable to allocate load GPIO\n"); mutex_init(&gpio->lock); diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 9e23a5ae8108..0ce1543426a4 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -41,7 +41,10 @@ #define XWAY_STP_4HZ BIT(23) #define XWAY_STP_8HZ BIT(24) #define XWAY_STP_10HZ (BIT(24) | BIT(23)) -#define XWAY_STP_SPEED_MASK (0xf << 23) +#define XWAY_STP_SPEED_MASK (BIT(23) | BIT(24) | BIT(25) | BIT(26) | BIT(27)) + +#define XWAY_STP_FPIS_VALUE BIT(21) +#define XWAY_STP_FPIS_MASK (BIT(20) | BIT(21)) /* clock source for automatic update */ #define XWAY_STP_UPD_FPI BIT(31) @@ -54,7 +57,9 @@ /* 2 groups of 3 bits can be driven by the phys */ #define XWAY_STP_PHY_MASK 0x7 #define XWAY_STP_PHY1_SHIFT 27 -#define XWAY_STP_PHY2_SHIFT 15 +#define XWAY_STP_PHY2_SHIFT 3 +#define XWAY_STP_PHY3_SHIFT 6 +#define XWAY_STP_PHY4_SHIFT 15 /* STP has 3 groups of 8 bits */ #define XWAY_STP_GROUP0 BIT(0) @@ -80,6 +85,8 @@ struct xway_stp { u8 dsl; /* the 2 LSBs can be driven by the dsl core */ u8 phy1; /* 3 bits can be driven by phy1 */ u8 phy2; /* 3 bits can be driven by phy2 */ + u8 phy3; /* 3 bits can be driven by phy3 */ + u8 phy4; /* 3 bits can be driven by phy4 */ u8 reserved; /* mask out the hw driven bits in gpio_request */ }; @@ -114,7 +121,8 @@ static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val) else chip->shadow &= ~BIT(gpio); xway_stp_w32(chip->virt, chip->shadow, XWAY_STP_CPU0); - xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0); + if (!chip->reserved) + xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0); } /** @@ -188,16 +196,37 @@ static void xway_stp_hw_init(struct xway_stp *chip) chip->phy2 << XWAY_STP_PHY2_SHIFT, XWAY_STP_CON1); + if (of_machine_is_compatible("lantiq,grx390") + || of_machine_is_compatible("lantiq,ar10")) { + xway_stp_w32_mask(chip->virt, + XWAY_STP_PHY_MASK << XWAY_STP_PHY3_SHIFT, + chip->phy3 << XWAY_STP_PHY3_SHIFT, + XWAY_STP_CON1); + } + + if (of_machine_is_compatible("lantiq,grx390")) { + xway_stp_w32_mask(chip->virt, + XWAY_STP_PHY_MASK << XWAY_STP_PHY4_SHIFT, + chip->phy4 << XWAY_STP_PHY4_SHIFT, + XWAY_STP_CON1); + } + /* mask out the hw driven bits in gpio_request */ - chip->reserved = (chip->phy2 << 5) | (chip->phy1 << 2) | chip->dsl; + chip->reserved = (chip->phy4 << 11) | (chip->phy3 << 8) | (chip->phy2 << 5) + | (chip->phy1 << 2) | chip->dsl; /* * if we have pins that are driven by hw, we need to tell the stp what * clock to use as a timer. */ - if (chip->reserved) + if (chip->reserved) { xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK, XWAY_STP_UPD_FPI, XWAY_STP_CON1); + xway_stp_w32_mask(chip->virt, XWAY_STP_SPEED_MASK, + XWAY_STP_10HZ, XWAY_STP_CON1); + xway_stp_w32_mask(chip->virt, XWAY_STP_FPIS_MASK, + XWAY_STP_FPIS_VALUE, XWAY_STP_CON1); + } } static int xway_stp_probe(struct platform_device *pdev) @@ -242,13 +271,26 @@ static int xway_stp_probe(struct platform_device *pdev) /* find out which gpios are controlled by the phys */ if (of_machine_is_compatible("lantiq,ar9") || of_machine_is_compatible("lantiq,gr9") || - of_machine_is_compatible("lantiq,vr9")) { + of_machine_is_compatible("lantiq,vr9") || + of_machine_is_compatible("lantiq,ar10") || + of_machine_is_compatible("lantiq,grx390")) { if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy1", &phy)) chip->phy1 = phy & XWAY_STP_PHY_MASK; if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy2", &phy)) chip->phy2 = phy & XWAY_STP_PHY_MASK; } + if (of_machine_is_compatible("lantiq,ar10") || + of_machine_is_compatible("lantiq,grx390")) { + if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy3", &phy)) + chip->phy3 = phy & XWAY_STP_PHY_MASK; + } + + if (of_machine_is_compatible("lantiq,grx390")) { + if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy4", &phy)) + chip->phy4 = phy & XWAY_STP_PHY_MASK; + } + /* check which edge trigger we should use, default to a falling edge */ if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL)) chip->edge = XWAY_STP_FALLING; 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/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 53d1387592fd..0b5a17ab996f 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -929,11 +929,9 @@ static int zynq_gpio_probe(struct platform_device *pdev) /* Retrieve GPIO clock */ gpio->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(gpio->clk)) { - if (PTR_ERR(gpio->clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "input clock not found.\n"); - return PTR_ERR(gpio->clk); - } + if (IS_ERR(gpio->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(gpio->clk), "input clock not found.\n"); + ret = clk_prepare_enable(gpio->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable clock.\n"); 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 deleted file mode 100644 index 26741032fa9e..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 <mika.westerberg@linux.intel.com> - */ - -#include <linux/property.h> -#include <linux/slab.h> -#include <linux/gpio/consumer.h> -#include <linux/gpio/driver.h> -#include <linux/export.h> - -#include "gpiolib.h" - -/** - * 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 - * by the caller. - */ -void devprop_gpiochip_set_names(struct gpio_chip *chip, - const struct fwnode_handle *fwnode) -{ - struct gpio_device *gdev = chip->gpiodev; - const char **names; - int ret, i; - int count; - - count = fwnode_property_read_string_array(fwnode, "gpio-line-names", - NULL, 0); - if (count < 0) - return; - - 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; - - ret = fwnode_property_read_string_array(fwnode, "gpio-line-names", - names, count); - if (ret < 0) { - dev_warn(&gdev->dev, "failed to read GPIO line names\n"); - kfree(names); - return; - } - - for (i = 0; i < count; i++) - gdev->descs[i].name = names[i]; - - kfree(names); -} -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 80137c1b3cdc..dfcff5d24b18 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; @@ -361,6 +358,57 @@ 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; + + /* GPIO chip may not have a parent device whose properties we inspect. */ + if (!dev) + return 0; + + 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; @@ -426,7 +474,7 @@ static void gpiodevice_release(struct device *dev) struct gpio_device *gdev = dev_get_drvdata(dev); list_del(&gdev->list); - ida_simple_remove(&gpio_ida, gdev->id); + ida_free(&gpio_ida, gdev->id); kfree_const(gdev->label); kfree(gdev->descs); kfree(gdev); @@ -537,7 +585,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, gc->of_node = gdev->dev.of_node; #endif - gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); + gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL); if (gdev->id < 0) { ret = gdev->id; goto err_free_gdev; @@ -621,7 +669,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; @@ -705,7 +756,7 @@ err_free_label: err_free_descs: kfree(gdev->descs); err_free_ida: - ida_simple_remove(&gpio_ida, gdev->id); + ida_free(&gpio_ida, gdev->id); err_free_gdev: /* failures here can mean systems won't boot... */ pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, @@ -4402,31 +4453,18 @@ static int gpiolib_seq_show(struct seq_file *s, void *v) return 0; } -static const struct seq_operations gpiolib_seq_ops = { +static const struct seq_operations gpiolib_sops = { .start = gpiolib_seq_start, .next = gpiolib_seq_next, .stop = gpiolib_seq_stop, .show = gpiolib_seq_show, }; - -static int gpiolib_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &gpiolib_seq_ops); -} - -static const struct file_operations gpiolib_operations = { - .owner = THIS_MODULE, - .open = gpiolib_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; +DEFINE_SEQ_ATTRIBUTE(gpiolib); static int __init gpiolib_debugfs_init(void) { /* /sys/kernel/debug/gpio */ - debugfs_create_file("gpio", S_IFREG | S_IRUGO, NULL, NULL, - &gpiolib_operations); + debugfs_create_file("gpio", 0444, NULL, NULL, &gpiolib_fops); return 0; } subsys_initcall(gpiolib_debugfs_init); |