1
0
Fork 0

gpio updates for v5.11-rc1

- several refactoring patches of the core gpiolib code
 - add support for NXP PCAL9554B/C to gpio-pca953x
 - allow probing mockup devices from device tree
 - refactoring and improvements to gpio-rcar
 - improvements to locking in gpio-tegra
 - code shrink in gpiolib devres
 - get the irq offset from device tree in gpio-sifive
 - major refactoring of gpio-exar
 - convert gpio-mvebu pwm access to regmap
 - create a new submenu for virtual GPIO drivers
 - fix clang fall-through warnings treewide
 - minor driver refactoring and tweaks sprinkled all over
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAl/QnM8ACgkQEacuoBRx
 13LkDw/+NKHc32hKgMJmSsLLFHgZ8XB+7Y775G5Ejxj+4Z0hVY9LdqL0zSYwrzCg
 D2dKwrKMtM83T8vf0bVbPdZ/9uuqrljvocGYt2CFmDqQa3sSlJkyDiSak2HAqjK/
 p9cgDQaUIlDrg2xh/1kSqELQoONmp4m82i++bItIwxIqAwPWfjSHVD7EQznDu0QD
 MJ7eYSuVlpeBhMwfyGCYSuUFhd4wN+nTkLTYw3nNlU4PHCKpdgYd7SBCJjSsLAhM
 8FOQ+PBspS6t8lPIEa4Mt+TOWUbbboGUBy40GPNU8QcUjbzj3TwPIBJu/0SIdSOy
 fBrk+GRjWtJ9shSlz0WQ19mG+qMjIiw4xLY1Jh3Tr4b75bQ3a4pk50aPWNE6bbHV
 NP1wZer/s06f1TQFKjfuDVFsOoRLyrTuOzlW0COAHoqFOdgimZi36xtjaS3AL3lE
 POBiBxFo9VaQ0enD99QMBt3940IP3ekRmlqRxeR1t8C0gE5np8IMZ5Dti8Fh4eCN
 hUQTDDuWQadluOdhMdLCBh5cA3VfZY8xksAMBzAYnSUHzM2D8TcKVjfJeegCEuZd
 kapAV3nLUv1/ZU36okFpMaHaKBL+xGDv8gtV2ro7rptkm6khNPQ3hxKvRbCRCG+S
 fO6IKThwozZEL/uVvsZLRKvN47g89oAGYYfasqq49932WChVKf8=
 =RmnM
 -----END PGP SIGNATURE-----

Merge tag 'gpio-updates-for-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into devel

gpio updates for v5.11-rc1

- several refactoring patches of the core gpiolib code
- add support for NXP PCAL9554B/C to gpio-pca953x
- allow probing mockup devices from device tree
- refactoring and improvements to gpio-rcar
- improvements to locking in gpio-tegra
- code shrink in gpiolib devres
- get the irq offset from device tree in gpio-sifive
- major refactoring of gpio-exar
- convert gpio-mvebu pwm access to regmap
- create a new submenu for virtual GPIO drivers
- fix clang fall-through warnings treewide
- minor driver refactoring and tweaks sprinkled all over
zero-sugar-mainline-defconfig
Linus Walleij 2020-12-09 15:17:24 +01:00
commit 40b37008eb
19 changed files with 280 additions and 229 deletions

View File

@ -48,6 +48,7 @@ properties:
- nxp,pcal6416
- nxp,pcal6524
- nxp,pcal9535
- nxp,pcal9554b
- nxp,pcal9555a
- onnn,cat9554
- onnn,pca9654

View File

@ -256,6 +256,7 @@ config GPIO_EP93XX
config GPIO_EXAR
tristate "Support for GPIO pins on XR17V352/354/358"
depends on SERIAL_8250_EXAR
select REGMAP_MMIO
help
Selecting this option will enable handling of GPIO pins present
on Exar XR17V352/354/358 chips.
@ -1602,6 +1603,8 @@ config GPIO_VIPERBOARD
endmenu
menu "Virtual GPIO drivers"
config GPIO_AGGREGATOR
tristate "GPIO Aggregator"
help
@ -1625,4 +1628,6 @@ config GPIO_MOCKUP
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
it.
endmenu
endif

View File

@ -123,6 +123,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
switch (flow_type) {
case IRQ_TYPE_EDGE_RISING:
polarity |= mask;
fallthrough;
case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_EDGE_BOTH:
break;

View File

@ -616,10 +616,9 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
int err;
gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);
if (IS_ERR(gpio->rst)) {
dev_err(gpio->dev, "Cannot get reset descriptor\n");
return PTR_ERR(gpio->rst);
}
if (IS_ERR(gpio->rst))
return dev_err_probe(gpio->dev, PTR_ERR(gpio->rst),
"Cannot get reset descriptor\n");
err = reset_control_deassert(gpio->rst);
if (err) {

View File

@ -4,14 +4,17 @@
*
* Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/gpio/driver.h>
#include <linux/idr.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define EXAR_OFFSET_MPIOLVL_LO 0x90
#define EXAR_OFFSET_MPIOSEL_LO 0x93
@ -24,60 +27,39 @@ static DEFINE_IDA(ida_index);
struct exar_gpio_chip {
struct gpio_chip gpio_chip;
struct mutex lock;
struct regmap *regmap;
int index;
void __iomem *regs;
char name[20];
unsigned int first_pin;
};
static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
unsigned int offset)
static unsigned int
exar_offset_to_sel_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
int temp;
mutex_lock(&exar_gpio->lock);
temp = readb(exar_gpio->regs + reg);
temp &= ~BIT(offset);
if (val)
temp |= BIT(offset);
writeb(temp, exar_gpio->regs + reg);
mutex_unlock(&exar_gpio->lock);
return (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOSEL_HI
: EXAR_OFFSET_MPIOSEL_LO;
}
static int exar_set_direction(struct gpio_chip *chip, int direction,
unsigned int offset)
static unsigned int
exar_offset_to_lvl_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
unsigned int bit = (offset + exar_gpio->first_pin) % 8;
exar_update(chip, addr, direction, bit);
return 0;
return (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOLVL_HI
: EXAR_OFFSET_MPIOLVL_LO;
}
static int exar_get(struct gpio_chip *chip, unsigned int reg)
static unsigned int
exar_offset_to_bit(struct exar_gpio_chip *exar_gpio, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
int value;
mutex_lock(&exar_gpio->lock);
value = readb(exar_gpio->regs + reg);
mutex_unlock(&exar_gpio->lock);
return value;
return (offset + exar_gpio->first_pin) % 8;
}
static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
unsigned int bit = (offset + exar_gpio->first_pin) % 8;
unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
if (exar_get(chip, addr) & BIT(bit))
if (regmap_test_bits(exar_gpio->regmap, addr, BIT(bit)))
return GPIO_LINE_DIRECTION_IN;
return GPIO_LINE_DIRECTION_OUT;
@ -86,39 +68,66 @@ static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
unsigned int bit = (offset + exar_gpio->first_pin) % 8;
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
return !!(exar_get(chip, addr) & BIT(bit));
return !!(regmap_test_bits(exar_gpio->regmap, addr, BIT(bit)));
}
static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
unsigned int bit = (offset + exar_gpio->first_pin) % 8;
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
exar_update(chip, addr, value, bit);
if (value)
regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
else
regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
}
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
exar_set_value(chip, offset, value);
return exar_set_direction(chip, 0, offset);
regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
return 0;
}
static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
{
return exar_set_direction(chip, 1, offset);
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
return 0;
}
static void exar_devm_ida_free(void *data)
{
struct exar_gpio_chip *exar_gpio = data;
ida_free(&ida_index, exar_gpio->index);
}
static const struct regmap_config exar_regmap_config = {
.name = "exar-gpio",
.reg_bits = 16,
.val_bits = 8,
};
static int gpio_exar_probe(struct platform_device *pdev)
{
struct pci_dev *pcidev = to_pci_dev(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct pci_dev *pcidev = to_pci_dev(dev->parent);
struct exar_gpio_chip *exar_gpio;
u32 first_pin, ngpios;
void __iomem *p;
@ -132,30 +141,37 @@ static int gpio_exar_probe(struct platform_device *pdev)
if (!p)
return -ENOMEM;
ret = device_property_read_u32(&pdev->dev, "exar,first-pin",
&first_pin);
ret = device_property_read_u32(dev, "exar,first-pin", &first_pin);
if (ret)
return ret;
ret = device_property_read_u32(&pdev->dev, "ngpios", &ngpios);
ret = device_property_read_u32(dev, "ngpios", &ngpios);
if (ret)
return ret;
exar_gpio = devm_kzalloc(&pdev->dev, sizeof(*exar_gpio), GFP_KERNEL);
exar_gpio = devm_kzalloc(dev, sizeof(*exar_gpio), GFP_KERNEL);
if (!exar_gpio)
return -ENOMEM;
mutex_init(&exar_gpio->lock);
/*
* We don't need to check the return values of mmio regmap operations (unless
* the regmap has a clock attached which is not the case here).
*/
exar_gpio->regmap = devm_regmap_init_mmio(dev, p, &exar_regmap_config);
if (IS_ERR(exar_gpio->regmap))
return PTR_ERR(exar_gpio->regmap);
index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
if (index < 0) {
ret = index;
goto err_mutex_destroy;
}
index = ida_alloc(&ida_index, GFP_KERNEL);
if (index < 0)
return index;
ret = devm_add_action_or_reset(dev, exar_devm_ida_free, exar_gpio);
if (ret)
return ret;
sprintf(exar_gpio->name, "exar_gpio%d", index);
exar_gpio->gpio_chip.label = exar_gpio->name;
exar_gpio->gpio_chip.parent = &pdev->dev;
exar_gpio->gpio_chip.parent = dev;
exar_gpio->gpio_chip.direction_output = exar_direction_output;
exar_gpio->gpio_chip.direction_input = exar_direction_input;
exar_gpio->gpio_chip.get_direction = exar_get_direction;
@ -163,39 +179,20 @@ static int gpio_exar_probe(struct platform_device *pdev)
exar_gpio->gpio_chip.set = exar_set_value;
exar_gpio->gpio_chip.base = -1;
exar_gpio->gpio_chip.ngpio = ngpios;
exar_gpio->regs = p;
exar_gpio->index = index;
exar_gpio->first_pin = first_pin;
ret = devm_gpiochip_add_data(&pdev->dev,
&exar_gpio->gpio_chip, exar_gpio);
ret = devm_gpiochip_add_data(dev, &exar_gpio->gpio_chip, exar_gpio);
if (ret)
goto err_destroy;
return ret;
platform_set_drvdata(pdev, exar_gpio);
return 0;
err_destroy:
ida_simple_remove(&ida_index, index);
err_mutex_destroy:
mutex_destroy(&exar_gpio->lock);
return ret;
}
static int gpio_exar_remove(struct platform_device *pdev)
{
struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev);
ida_simple_remove(&ida_index, exar_gpio->index);
mutex_destroy(&exar_gpio->lock);
return 0;
}
static struct platform_driver gpio_exar_driver = {
.probe = gpio_exar_probe,
.remove = gpio_exar_remove,
.driver = {
.name = DRIVER_NAME,
},

View File

@ -15,6 +15,7 @@
#include <linux/irq.h>
#include <linux/irq_sim.h>
#include <linux/irqdomain.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
@ -460,9 +461,16 @@ static int gpio_mockup_probe(struct platform_device *pdev)
return 0;
}
static const struct of_device_id gpio_mockup_of_match[] = {
{ .compatible = "gpio-mockup", },
{},
};
MODULE_DEVICE_TABLE(of, gpio_mockup_of_match);
static struct platform_driver gpio_mockup_driver = {
.driver = {
.name = "gpio-mockup",
.of_match_table = gpio_mockup_of_match,
},
.probe = gpio_mockup_probe,
};
@ -556,8 +564,7 @@ static int __init gpio_mockup_init(void)
{
int i, num_chips, err;
if ((gpio_mockup_num_ranges < 2) ||
(gpio_mockup_num_ranges % 2) ||
if ((gpio_mockup_num_ranges % 2) ||
(gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES))
return -EINVAL;

View File

@ -78,8 +78,7 @@
/*
* The Armada XP has per-CPU registers for interrupt cause, interrupt
* mask and interrupt level mask. Those are relative to the
* percpu_membase.
* mask and interrupt level mask. Those are in percpu_regs range.
*/
#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4)
@ -93,7 +92,7 @@
#define MVEBU_MAX_GPIO_PER_BANK 32
struct mvebu_pwm {
void __iomem *membase;
struct regmap *regs;
unsigned long clk_rate;
struct gpio_desc *gpiod;
struct pwm_chip chip;
@ -279,17 +278,17 @@ mvebu_gpio_write_level_mask(struct mvebu_gpio_chip *mvchip, u32 val)
}
/*
* Functions returning addresses of individual registers for a given
* Functions returning offsets of individual registers for a given
* PWM controller.
*/
static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
static unsigned int mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
{
return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF;
return PWM_BLINK_ON_DURATION_OFF;
}
static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
static unsigned int mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
{
return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF;
return PWM_BLINK_OFF_DURATION_OFF;
}
/*
@ -600,6 +599,13 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
static const struct regmap_config mvebu_gpio_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
};
/*
* Functions implementing the pwm_chip methods
*/
@ -660,9 +666,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
spin_lock_irqsave(&mvpwm->lock, flags);
val = (unsigned long long)
readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
val *= NSEC_PER_SEC;
regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), &u);
val = (unsigned long long) u * NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
if (val > UINT_MAX)
state->duty_cycle = UINT_MAX;
@ -671,9 +676,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
else
state->duty_cycle = 1;
val = (unsigned long long)
readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
val *= NSEC_PER_SEC;
regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
val = (unsigned long long) u * NSEC_PER_SEC;
do_div(val, mvpwm->clk_rate);
if (val < state->duty_cycle) {
state->period = 1;
@ -726,8 +730,8 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
spin_lock_irqsave(&mvpwm->lock, flags);
writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm));
writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm));
regmap_write(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm), on);
regmap_write(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), off);
if (state->enabled)
mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1);
else
@ -752,10 +756,10 @@ static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
regmap_read(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
&mvpwm->blink_select);
mvpwm->blink_on_duration =
readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
mvpwm->blink_off_duration =
readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
regmap_read(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm),
&mvpwm->blink_on_duration);
regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm),
&mvpwm->blink_off_duration);
}
static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
@ -764,10 +768,10 @@ static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
regmap_write(mvchip->regs, GPIO_BLINK_CNT_SELECT_OFF + mvchip->offset,
mvpwm->blink_select);
writel_relaxed(mvpwm->blink_on_duration,
mvebu_pwmreg_blink_on_duration(mvpwm));
writel_relaxed(mvpwm->blink_off_duration,
mvebu_pwmreg_blink_off_duration(mvpwm));
regmap_write(mvpwm->regs, mvebu_pwmreg_blink_on_duration(mvpwm),
mvpwm->blink_on_duration);
regmap_write(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm),
mvpwm->blink_off_duration);
}
static int mvebu_pwm_probe(struct platform_device *pdev,
@ -776,6 +780,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
{
struct device *dev = &pdev->dev;
struct mvebu_pwm *mvpwm;
void __iomem *base;
u32 set;
if (!of_device_is_compatible(mvchip->chip.of_node,
@ -813,9 +818,14 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
mvchip->mvpwm = mvpwm;
mvpwm->mvchip = mvchip;
mvpwm->membase = devm_platform_ioremap_resource_byname(pdev, "pwm");
if (IS_ERR(mvpwm->membase))
return PTR_ERR(mvpwm->membase);
base = devm_platform_ioremap_resource_byname(pdev, "pwm");
if (IS_ERR(base))
return PTR_ERR(base);
mvpwm->regs = devm_regmap_init_mmio(&pdev->dev, base,
&mvebu_gpio_regmap_config);
if (IS_ERR(mvpwm->regs))
return PTR_ERR(mvpwm->regs);
mvpwm->clk_rate = clk_get_rate(mvchip->clk);
if (!mvpwm->clk_rate) {
@ -1022,13 +1032,6 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
return 0;
}
static const struct regmap_config mvebu_gpio_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
};
static int mvebu_gpio_probe_raw(struct platform_device *pdev,
struct mvebu_gpio_chip *mvchip)
{

View File

@ -1049,11 +1049,8 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
irq->first = irq_base;
ret = gpiochip_add_data(&bank->chip, bank);
if (ret) {
dev_err(bank->chip.parent,
"Could not register gpio chip %d\n", ret);
return ret;
}
if (ret)
return dev_err_probe(bank->chip.parent, ret, "Could not register gpio chip\n");
ret = devm_request_irq(bank->chip.parent, bank->irq,
omap_gpio_irq_handler,

View File

@ -32,6 +32,11 @@ struct gpio_rcar_bank_info {
u32 intmsk;
};
struct gpio_rcar_info {
bool has_outdtsel;
bool has_both_edge_trigger;
};
struct gpio_rcar_priv {
void __iomem *base;
spinlock_t lock;
@ -40,24 +45,23 @@ struct gpio_rcar_priv {
struct irq_chip irq_chip;
unsigned int irq_parent;
atomic_t wakeup_path;
bool has_outdtsel;
bool has_both_edge_trigger;
struct gpio_rcar_info info;
struct gpio_rcar_bank_info bank_info;
};
#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
#define INOUTSEL 0x04 /* General Input/Output Switching Register */
#define OUTDT 0x08 /* General Output Register */
#define INDT 0x0c /* General Input Register */
#define INTDT 0x10 /* Interrupt Display Register */
#define INTCLR 0x14 /* Interrupt Clear Register */
#define INTMSK 0x18 /* Interrupt Mask Register */
#define MSKCLR 0x1c /* Interrupt Mask Clear Register */
#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
#define EDGLEVEL 0x24 /* Edge/level Select Register */
#define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
#define OUTDTSEL 0x40 /* Output Data Select Register */
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
#define INOUTSEL 0x04 /* General Input/Output Switching Register */
#define OUTDT 0x08 /* General Output Register */
#define INDT 0x0c /* General Input Register */
#define INTDT 0x10 /* Interrupt Display Register */
#define INTCLR 0x14 /* Interrupt Clear Register */
#define INTMSK 0x18 /* Interrupt Mask Register */
#define MSKCLR 0x1c /* Interrupt Mask Clear Register */
#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
#define EDGLEVEL 0x24 /* Edge/level Select Register */
#define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
#define OUTDTSEL 0x40 /* Output Data Select Register */
#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
#define RCAR_MAX_GPIO_PER_BANK 32
@ -123,7 +127,7 @@ static void gpio_rcar_config_interrupt_input_mode(struct gpio_rcar_priv *p,
gpio_rcar_modify_bit(p, EDGLEVEL, hwirq, !level_trigger);
/* Select one edge or both edges in BOTHEDGE */
if (p->has_both_edge_trigger)
if (p->info.has_both_edge_trigger)
gpio_rcar_modify_bit(p, BOTHEDGE, hwirq, both);
/* Select "Interrupt Input Mode" in IOINTSEL */
@ -162,7 +166,7 @@ static int gpio_rcar_irq_set_type(struct irq_data *d, unsigned int type)
false);
break;
case IRQ_TYPE_EDGE_BOTH:
if (!p->has_both_edge_trigger)
if (!p->info.has_both_edge_trigger)
return -EINVAL;
gpio_rcar_config_interrupt_input_mode(p, hwirq, true, false,
true);
@ -238,7 +242,7 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip,
gpio_rcar_modify_bit(p, INOUTSEL, gpio, output);
/* Select General Output Register to output data in OUTDTSEL */
if (p->has_outdtsel && output)
if (p->info.has_outdtsel && output)
gpio_rcar_modify_bit(p, OUTDTSEL, gpio, false);
spin_unlock_irqrestore(&p->lock, flags);
@ -295,14 +299,44 @@ static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)
static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
{
struct gpio_rcar_priv *p = gpiochip_get_data(chip);
u32 bit = BIT(offset);
/* testing on r8a7790 shows that INDT does not show correct pin state
* when configured as output, so use OUTDT in case of output pins */
if (gpio_rcar_read(gpiochip_get_data(chip), INOUTSEL) & bit)
return !!(gpio_rcar_read(gpiochip_get_data(chip), OUTDT) & bit);
if (gpio_rcar_read(p, INOUTSEL) & bit)
return !!(gpio_rcar_read(p, OUTDT) & bit);
else
return !!(gpio_rcar_read(gpiochip_get_data(chip), INDT) & bit);
return !!(gpio_rcar_read(p, INDT) & bit);
}
static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask,
unsigned long *bits)
{
struct gpio_rcar_priv *p = gpiochip_get_data(chip);
u32 bankmask, outputs, m, val = 0;
unsigned long flags;
bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0);
if (chip->valid_mask)
bankmask &= chip->valid_mask[0];
if (!bankmask)
return 0;
spin_lock_irqsave(&p->lock, flags);
outputs = gpio_rcar_read(p, INOUTSEL);
m = outputs & bankmask;
if (m)
val |= gpio_rcar_read(p, OUTDT) & m;
m = ~outputs & bankmask;
if (m)
val |= gpio_rcar_read(p, INDT) & m;
spin_unlock_irqrestore(&p->lock, flags);
bits[0] = val;
return 0;
}
static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
@ -346,11 +380,6 @@ static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
return 0;
}
struct gpio_rcar_info {
bool has_outdtsel;
bool has_both_edge_trigger;
};
static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
.has_outdtsel = false,
.has_both_edge_trigger = false,
@ -417,8 +446,7 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins)
int ret;
info = of_device_get_match_data(p->dev);
p->has_outdtsel = info->has_outdtsel;
p->has_both_edge_trigger = info->has_both_edge_trigger;
p->info = *info;
ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
*npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
@ -479,6 +507,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
gpio_chip->get_direction = gpio_rcar_get_direction;
gpio_chip->direction_input = gpio_rcar_direction_input;
gpio_chip->get = gpio_rcar_get;
gpio_chip->get_multiple = gpio_rcar_get_multiple;
gpio_chip->direction_output = gpio_rcar_direction_output;
gpio_chip->set = gpio_rcar_set;
gpio_chip->set_multiple = gpio_rcar_set_multiple;
@ -552,7 +581,7 @@ static int gpio_rcar_suspend(struct device *dev)
p->bank_info.intmsk = gpio_rcar_read(p, INTMSK);
p->bank_info.posneg = gpio_rcar_read(p, POSNEG);
p->bank_info.edglevel = gpio_rcar_read(p, EDGLEVEL);
if (p->has_both_edge_trigger)
if (p->info.has_both_edge_trigger)
p->bank_info.bothedge = gpio_rcar_read(p, BOTHEDGE);
if (atomic_read(&p->wakeup_path))

View File

@ -29,7 +29,6 @@
#define SIFIVE_GPIO_OUTPUT_XOR 0x40
#define SIFIVE_GPIO_MAX 32
#define SIFIVE_GPIO_IRQ_OFFSET 7
struct sifive_gpio {
void __iomem *base;
@ -37,7 +36,7 @@ struct sifive_gpio {
struct regmap *regs;
unsigned long irq_state;
unsigned int trigger[SIFIVE_GPIO_MAX];
unsigned int irq_parent[SIFIVE_GPIO_MAX];
unsigned int irq_number[SIFIVE_GPIO_MAX];
};
static void sifive_gpio_set_ie(struct sifive_gpio *chip, unsigned int offset)
@ -155,8 +154,12 @@ static int sifive_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
unsigned int *parent,
unsigned int *parent_type)
{
struct sifive_gpio *chip = gpiochip_get_data(gc);
struct irq_data *d = irq_get_irq_data(chip->irq_number[child]);
*parent_type = IRQ_TYPE_NONE;
*parent = child + SIFIVE_GPIO_IRQ_OFFSET;
*parent = irqd_to_hwirq(d);
return 0;
}
@ -176,7 +179,7 @@ static int sifive_gpio_probe(struct platform_device *pdev)
struct irq_domain *parent;
struct gpio_irq_chip *girq;
struct sifive_gpio *chip;
int ret, ngpio;
int ret, ngpio, i;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@ -211,6 +214,9 @@ static int sifive_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
for (i = 0; i < ngpio; i++)
chip->irq_number[i] = platform_get_irq(pdev, i);
ret = bgpio_init(&chip->gc, dev, 4,
chip->base + SIFIVE_GPIO_INPUT_VAL,
chip->base + SIFIVE_GPIO_OUTPUT_VAL,

View File

@ -61,8 +61,16 @@ struct tegra_gpio_info;
struct tegra_gpio_bank {
unsigned int bank;
unsigned int irq;
spinlock_t lvl_lock[4];
spinlock_t dbc_lock[4]; /* Lock for updating debounce count register */
/*
* IRQ-core code uses raw locking, and thus, nested locking also
* should be raw in order not to trip spinlock debug warnings.
*/
raw_spinlock_t lvl_lock[4];
/* Lock for updating debounce count register */
spinlock_t dbc_lock[4];
#ifdef CONFIG_PM_SLEEP
u32 cnf[4];
u32 out[4];
@ -334,14 +342,14 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
spin_lock_irqsave(&bank->lvl_lock[port], flags);
raw_spin_lock_irqsave(&bank->lvl_lock[port], flags);
val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
val |= lvl_type << GPIO_BIT(gpio);
tegra_gpio_writel(tgi, val, GPIO_INT_LVL(tgi, gpio));
spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
raw_spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0);
tegra_gpio_enable(tgi, gpio);
@ -560,6 +568,9 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
};
static struct lock_class_key gpio_lock_class;
static struct lock_class_key gpio_request_class;
static int tegra_gpio_probe(struct platform_device *pdev)
{
struct tegra_gpio_info *tgi;
@ -661,6 +672,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
bank = &tgi->bank_info[GPIO_BANK(gpio)];
irq_set_chip_data(irq, bank);
irq_set_lockdep_class(irq, &gpio_lock_class, &gpio_request_class);
irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq);
}
@ -671,7 +683,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
tegra_gpio_irq_handler, bank);
for (j = 0; j < 4; j++) {
spin_lock_init(&bank->lvl_lock[j]);
raw_spin_lock_init(&bank->lvl_lock[j]);
spin_lock_init(&bank->dbc_lock[j]);
}
}

View File

@ -186,15 +186,7 @@ static int xra1403_probe(struct spi_device *spi)
return ret;
}
ret = devm_gpiochip_add_data(&spi->dev, &xra->chip, xra);
if (ret < 0) {
dev_err(&spi->dev, "Unable to register gpiochip\n");
return ret;
}
spi_set_drvdata(spi, xra);
return 0;
return devm_gpiochip_add_data(&spi->dev, &xra->chip, xra);
}
static const struct spi_device_id xra1403_ids[] = {

View File

@ -233,6 +233,7 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity)
default:
break;
}
break;
default:
break;
}

View File

@ -428,6 +428,12 @@ struct line {
*/
struct linereq *req;
unsigned int irq;
/*
* eflags is set by edge_detector_setup(), edge_detector_stop() and
* edge_detector_update(), which are themselves mutually exclusive,
* and is accessed by edge_irq_thread() and debounce_work_func(),
* which can both live with a slightly stale value.
*/
u64 eflags;
/*
* timestamp_ns and req_seqno are accessed only by
@ -504,6 +510,8 @@ struct linereq {
(GPIO_V2_LINE_FLAG_EDGE_RISING | \
GPIO_V2_LINE_FLAG_EDGE_FALLING)
#define GPIO_V2_LINE_FLAG_EDGE_BOTH GPIO_V2_LINE_EDGE_FLAGS
#define GPIO_V2_LINE_VALID_FLAGS \
(GPIO_V2_LINE_FLAG_ACTIVE_LOW | \
GPIO_V2_LINE_DIRECTION_FLAGS | \
@ -543,6 +551,7 @@ static irqreturn_t edge_irq_thread(int irq, void *p)
struct line *line = p;
struct linereq *lr = line->req;
struct gpio_v2_line_event le;
u64 eflags;
/* Do not leak kernel stack to userspace */
memset(&le, 0, sizeof(le));
@ -561,8 +570,8 @@ static irqreturn_t edge_irq_thread(int irq, void *p)
}
line->timestamp_ns = 0;
if (line->eflags == (GPIO_V2_LINE_FLAG_EDGE_RISING |
GPIO_V2_LINE_FLAG_EDGE_FALLING)) {
eflags = READ_ONCE(line->eflags);
if (eflags == GPIO_V2_LINE_FLAG_EDGE_BOTH) {
int level = gpiod_get_value_cansleep(line->desc);
if (level)
@ -571,10 +580,10 @@ static irqreturn_t edge_irq_thread(int irq, void *p)
else
/* Emit high-to-low event */
le.id = GPIO_V2_LINE_EVENT_FALLING_EDGE;
} else if (line->eflags == GPIO_V2_LINE_FLAG_EDGE_RISING) {
} else if (eflags == GPIO_V2_LINE_FLAG_EDGE_RISING) {
/* Emit low-to-high event */
le.id = GPIO_V2_LINE_EVENT_RISING_EDGE;
} else if (line->eflags == GPIO_V2_LINE_FLAG_EDGE_FALLING) {
} else if (eflags == GPIO_V2_LINE_FLAG_EDGE_FALLING) {
/* Emit high-to-low event */
le.id = GPIO_V2_LINE_EVENT_FALLING_EDGE;
} else {
@ -643,6 +652,7 @@ static void debounce_work_func(struct work_struct *work)
struct line *line = container_of(work, struct line, work.work);
struct linereq *lr;
int level;
u64 eflags;
level = gpiod_get_raw_value_cansleep(line->desc);
if (level < 0) {
@ -656,7 +666,8 @@ static void debounce_work_func(struct work_struct *work)
WRITE_ONCE(line->level, level);
/* -- edge detection -- */
if (!line->eflags)
eflags = READ_ONCE(line->eflags);
if (!eflags)
return;
/* switch from physical level to logical - if they differ */
@ -664,8 +675,8 @@ static void debounce_work_func(struct work_struct *work)
level = !level;
/* ignore edges that are not being monitored */
if (((line->eflags == GPIO_V2_LINE_FLAG_EDGE_RISING) && !level) ||
((line->eflags == GPIO_V2_LINE_FLAG_EDGE_FALLING) && level))
if (((eflags == GPIO_V2_LINE_FLAG_EDGE_RISING) && !level) ||
((eflags == GPIO_V2_LINE_FLAG_EDGE_FALLING) && level))
return;
/* Do not leak kernel stack to userspace */
@ -764,7 +775,7 @@ static void edge_detector_stop(struct line *line)
cancel_delayed_work_sync(&line->work);
WRITE_ONCE(line->sw_debounced, 0);
line->eflags = 0;
WRITE_ONCE(line->eflags, 0);
/* do not change line->level - see comment in debounced_value() */
}
@ -783,7 +794,7 @@ static int edge_detector_setup(struct line *line,
if (ret)
return ret;
}
line->eflags = eflags;
WRITE_ONCE(line->eflags, eflags);
if (gpio_v2_line_config_debounced(lc, line_idx)) {
debounce_period_us = gpio_v2_line_config_debounce_period(lc, line_idx);
ret = debounce_setup(line, debounce_period_us);
@ -826,13 +837,13 @@ static int edge_detector_update(struct line *line,
unsigned int debounce_period_us =
gpio_v2_line_config_debounce_period(lc, line_idx);
if ((line->eflags == eflags) && !polarity_change &&
if ((READ_ONCE(line->eflags) == eflags) && !polarity_change &&
(READ_ONCE(line->desc->debounce_period_us) == debounce_period_us))
return 0;
/* sw debounced and still will be...*/
if (debounce_period_us && READ_ONCE(line->sw_debounced)) {
line->eflags = eflags;
WRITE_ONCE(line->eflags, eflags);
WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us);
return 0;
}

View File

@ -246,10 +246,8 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
struct gpio_desc *desc;
desc = devm_gpiod_get_index(dev, con_id, index, flags);
if (IS_ERR(desc)) {
if (PTR_ERR(desc) == -ENOENT)
return NULL;
}
if (gpiod_not_found(desc))
return NULL;
return desc;
}
@ -308,7 +306,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
struct gpio_descs *descs;
descs = devm_gpiod_get_array(dev, con_id, flags);
if (PTR_ERR(descs) == -ENOENT)
if (gpiod_not_found(descs))
return NULL;
return descs;
@ -479,9 +477,9 @@ void devm_gpio_free(struct device *dev, unsigned int gpio)
}
EXPORT_SYMBOL_GPL(devm_gpio_free);
static void devm_gpio_chip_release(struct device *dev, void *res)
static void devm_gpio_chip_release(void *data)
{
struct gpio_chip *gc = *(struct gpio_chip **)res;
struct gpio_chip *gc = data;
gpiochip_remove(gc);
}
@ -507,23 +505,12 @@ int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, vo
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
struct gpio_chip **ptr;
int ret;
ptr = devres_alloc(devm_gpio_chip_release, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = gpiochip_add_data_with_key(gc, data, lock_key, request_key);
if (ret < 0) {
devres_free(ptr);
if (ret < 0)
return ret;
}
*ptr = gc;
devres_add(dev, ptr);
return 0;
return devm_add_action_or_reset(dev, devm_gpio_chip_release, gc);
}
EXPORT_SYMBOL_GPL(devm_gpiochip_add_data_with_key);

View File

@ -509,31 +509,31 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
&of_flags);
if (!IS_ERR(desc) || PTR_ERR(desc) != -ENOENT)
if (!gpiod_not_found(desc))
break;
}
if (PTR_ERR(desc) == -ENOENT) {
if (gpiod_not_found(desc)) {
/* Special handling for SPI GPIOs if used */
desc = of_find_spi_gpio(dev, con_id, &of_flags);
}
if (PTR_ERR(desc) == -ENOENT) {
if (gpiod_not_found(desc)) {
/* This quirk looks up flags and all */
desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
if (!IS_ERR(desc))
return desc;
}
if (PTR_ERR(desc) == -ENOENT) {
if (gpiod_not_found(desc)) {
/* Special handling for regulator GPIOs if used */
desc = of_find_regulator_gpio(dev, con_id, &of_flags);
}
if (PTR_ERR(desc) == -ENOENT)
if (gpiod_not_found(desc))
desc = of_find_arizona_gpio(dev, con_id, &of_flags);
if (PTR_ERR(desc) == -ENOENT)
if (gpiod_not_found(desc))
desc = of_find_usb_gpio(dev, con_id, &of_flags);
if (IS_ERR(desc))
@ -593,7 +593,7 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
xlate_flags = 0;
*lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
*dflags = 0;
*dflags = GPIOD_ASIS;
ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp);
if (ret)

View File

@ -476,7 +476,7 @@ static ssize_t export_store(struct class *class,
*/
status = gpiod_request(desc, "sysfs");
if (status < 0) {
if (status) {
if (status == -EPROBE_DEFER)
status = -ENODEV;
goto done;

View File

@ -772,9 +772,11 @@ err_free_ida:
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__,
gdev->base, gdev->base + gdev->ngpio - 1,
gc->label ? : "generic", ret);
if (ret != -EPROBE_DEFER) {
pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
gdev->base, gdev->base + gdev->ngpio - 1,
gc->label ? : "generic", ret);
}
kfree(gdev);
return ret;
}
@ -1828,11 +1830,9 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
desc_set_label(desc, label ? : "?");
ret = 0;
} else {
kfree_const(label);
ret = -EBUSY;
goto done;
goto out_free_unlock;
}
if (gc->request) {
@ -1845,11 +1845,10 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
ret = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
if (ret < 0) {
if (ret) {
desc_set_label(desc, NULL);
kfree_const(label);
clear_bit(FLAG_REQUESTED, &desc->flags);
goto done;
goto out_free_unlock;
}
}
if (gc->get_direction) {
@ -1858,8 +1857,12 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
gpiod_get_direction(desc);
spin_lock_irqsave(&gpio_lock, flags);
}
done:
spin_unlock_irqrestore(&gpio_lock, flags);
return 0;
out_free_unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
kfree_const(label);
return ret;
}
@ -1911,7 +1914,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label)
if (try_module_get(gdev->owner)) {
ret = gpiod_request_commit(desc, label);
if (ret < 0)
if (ret)
module_put(gdev->owner);
else
get_device(&gdev->dev);
@ -3644,7 +3647,7 @@ struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
desc = fwnode_get_named_gpiod(fwnode, prop_name, index, flags,
label);
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
if (!gpiod_not_found(desc))
break;
}
@ -3820,7 +3823,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
* Either we are not using DT or ACPI, or their lookup did not return
* a result. In that case, use platform lookup as a fallback.
*/
if (!desc || desc == ERR_PTR(-ENOENT)) {
if (!desc || gpiod_not_found(desc)) {
dev_dbg(dev, "using lookup tables for GPIO lookup\n");
desc = gpiod_find(dev, con_id, idx, &lookupflags);
}
@ -3835,7 +3838,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
* the device name as label
*/
ret = gpiod_request(desc, con_id ? con_id : devname);
if (ret < 0) {
if (ret) {
if (ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
/*
* This happens when there are several consumers for
@ -3955,10 +3958,8 @@ struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
struct gpio_desc *desc;
desc = gpiod_get_index(dev, con_id, index, flags);
if (IS_ERR(desc)) {
if (PTR_ERR(desc) == -ENOENT)
return NULL;
}
if (gpiod_not_found(desc))
return NULL;
return desc;
}
@ -4160,7 +4161,7 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
struct gpio_descs *descs;
descs = gpiod_get_array(dev, con_id, flags);
if (PTR_ERR(descs) == -ENOENT)
if (gpiod_not_found(descs))
return NULL;
return descs;

View File

@ -131,6 +131,8 @@ struct gpio_desc {
#endif
};
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
int gpiod_request(struct gpio_desc *desc, const char *label);
void gpiod_free(struct gpio_desc *desc);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,