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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAl9jSlsACgkQEacuoBRx
 13K6cBAA2Drc9AwFpGzb+yE7bvKmxtbCbD8RZBQNg4Ljy56yQOQhNnQSE91YIeGj
 MlSNbn89nKGlkUje2qggJn6+ZE1InKI70d67fK4z/MiMDv31YLPN78Qei9kbTXgF
 dNiV6wnabavAJrpNPtNOU8SLotn9C3zVwTyXOuMqfGL6TqAWf79Xk2QHuV1l/Apz
 CozfTI/81p1eeuF3yMRz+ubGS/2Zpo862QmgA9CMWb439z7LNbQJ1vjFKMqvkW0P
 ey9ELjV/y5PFTA9fWYIukOjBqpsWyihdIW2K3R/7yR8OFqREUnvBzJZJLpghCkzO
 vpivVFlZu7eyMpdUU4ZH7ussFVX+GqYbV8Q42shabClQH7qJAfnO3nhPptWWWd/v
 CmDOEvsfg2CpXpWJmwxUxoUJEOto2NO3HOBM41XYKQhSs3pw1HheN2wxVOWWOrTa
 kJfJnyaWYT1qkolRuXMdLkauZHOpmAP3o+o+OtInd+NeM9lyaCjhdtQ11vBDk1Oc
 3jLskr29KyTIa9lNPLT+pcQWuF77dhtzTPUIeG1+BzWA/FBpiR2c0M2tmUdRGIKb
 IEPF0vkihiLy5rz/j1YYgADLDc6uxhEbiP/WKcbKySgc4kCQCHkgFQwa/DyMAROC
 ye7Yof9m6Yx1KMvioP0QpP/LU9mfooSoa2JU2iHGH8df+VJ1NFQ=
 =RbA2
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Walleij 2020-09-21 23:39:50 +02:00
commit 36eccdb58f
18 changed files with 201 additions and 164 deletions

View File

@ -37,6 +37,7 @@ properties:
- renesas,gpio-r8a774a1 # RZ/G2M
- renesas,gpio-r8a774b1 # RZ/G2N
- renesas,gpio-r8a774c0 # RZ/G2E
- renesas,gpio-r8a774e1 # RZ/G2H
- renesas,gpio-r8a7795 # R-Car H3
- renesas,gpio-r8a7796 # R-Car M3-W
- renesas,gpio-r8a77961 # R-Car M3-W+

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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",

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
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);

View File

@ -756,9 +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);
void devprop_gpiochip_set_names(struct gpio_chip *gc,
const struct fwnode_handle *fwnode);
#ifdef CONFIG_GPIOLIB
/* lock/unlock as IRQ */

View File

@ -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

View File

@ -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;
/**