gpio fixes for v6.14-rc3 - take 2
- fix interrupt handling issues in gpio-bcm-kona - add an ACPI quirk for Acer Nitro ANV14 fixing an issue with spurious wake up events - add missing return value checks to gpio-stmpe - fix a crash in error path in gpiochip_get_ngpios() -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmewXNIACgkQEacuoBRx 13L3aQ/8C2aQu4lqV2+eu+7PWAyrmwRkZ7qgLe33FFOHShgPLsK3du4iyccVy2Z4 Ett8Yk4hA/KbzlPPSKxK71su4b6dkVpyhZPLB5vwH8yebW+pRCk+FzFdGmcaeymX lg25pSdpIzezQMg/wmYmySu5CoeNbo8AkWQWwU8435URKec+Nmxh13Ssf8aQs5Fa cLTB4dhc7yuYll0F+J2VtJ8+m/Ryb17ic4204EQn0L4t+kgijaeIcUA4d26h3MMz WEHs911zP4tjXJUoaiTrMXp1oB16YzlHumppb7QzozZe1D6fLMjI/MeZbpkrJL5h NvgvsdBQMjLyZtK5EwA/7faExYfts4+g8TyzhF/7TEvz0omU7cLoN3V4/S4sUXa2 lCHufXc5864C1BcJ9tFQAZ1eS+hZiVDZPmCpZ08ACEcrfuzgvSEm5yyIOfALblFO VPsf6ic53XD9MEkAkLK+jMuqZOnifX9sYCvHVM4sgob+A8ra9kTo3XsMy1mHw/Da Z/ospRp/nRfG/hlT0Ko3mxsbmCPhKEEdC07ZVxjyiE0xtuMhMQyQpNtC6NkVLfg+ m21POmBcDZOH64wIOdWj15gTjy4im/p1KhHL5veXOJV36eEu7SiX699LYkNyu7px bVNoZqmMGVH9muD0rIAS1po2TWSDptHGsli2uL2ddQDfvOaelEU= =odVF -----END PGP SIGNATURE----- Merge tag 'gpio-fixes-for-v6.14-rc3-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux Pull gpio fixes from Bartosz Golaszewski: - fix interrupt handling issues in gpio-bcm-kona - add an ACPI quirk for Acer Nitro ANV14 fixing an issue with spurious wake up events - add missing return value checks to gpio-stmpe - fix a crash in error path in gpiochip_get_ngpios() * tag 'gpio-fixes-for-v6.14-rc3-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpiolib: Fix crash on error in gpiochip_get_ngpios() gpio: stmpe: Check return value of stmpe_reg_read in stmpe_gpio_irq_sync_unlock gpiolib: acpi: Add a quirk for Acer Nitro ANV14 gpio: bcm-kona: Add missing newline to dev_err format string gpio: bcm-kona: Make sure GPIO bits are unlocked when requesting IRQ gpio: bcm-kona: Fix GPIO lock/unlock for banks above bank 0
This commit is contained in:
commit
6452feaf29
4 changed files with 87 additions and 19 deletions
|
@ -69,6 +69,22 @@ struct bcm_kona_gpio {
|
|||
struct bcm_kona_gpio_bank {
|
||||
int id;
|
||||
int irq;
|
||||
/*
|
||||
* Used to keep track of lock/unlock operations for each GPIO in the
|
||||
* bank.
|
||||
*
|
||||
* All GPIOs are locked by default (see bcm_kona_gpio_reset), and the
|
||||
* unlock count for all GPIOs is 0 by default. Each unlock increments
|
||||
* the counter, and each lock decrements the counter.
|
||||
*
|
||||
* The lock function only locks the GPIO once its unlock counter is
|
||||
* down to 0. This is necessary because the GPIO is unlocked in two
|
||||
* places in this driver: once for requested GPIOs, and once for
|
||||
* requested IRQs. Since it is possible for a GPIO to be requested
|
||||
* as both a GPIO and an IRQ, we need to ensure that we don't lock it
|
||||
* too early.
|
||||
*/
|
||||
u8 gpio_unlock_count[GPIO_PER_BANK];
|
||||
/* Used in the interrupt handler */
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
};
|
||||
|
@ -86,14 +102,24 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
|
|||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id];
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
if (bank->gpio_unlock_count[bit] == 0) {
|
||||
dev_err(kona_gpio->gpio_chip.parent,
|
||||
"Unbalanced locks for GPIO %u\n", gpio);
|
||||
return;
|
||||
}
|
||||
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val |= BIT(gpio);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
if (--bank->gpio_unlock_count[bit] == 0) {
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val |= BIT(bit);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
|
||||
|
@ -102,14 +128,20 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
|
|||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id];
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
if (bank->gpio_unlock_count[bit] == 0) {
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val &= ~BIT(gpio);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val &= ~BIT(bit);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
++bank->gpio_unlock_count[bit];
|
||||
}
|
||||
|
||||
static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
|
||||
|
@ -360,6 +392,7 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
|
|||
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_MASK(bank_id));
|
||||
|
@ -382,6 +415,7 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
|
|||
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
|
||||
|
@ -477,15 +511,26 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
|
|||
static int bcm_kona_gpio_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
unsigned int gpio = d->hwirq;
|
||||
|
||||
return gpiochip_reqres_irq(&kona_gpio->gpio_chip, d->hwirq);
|
||||
/*
|
||||
* We need to unlock the GPIO before any other operations are performed
|
||||
* on the relevant GPIO configuration registers
|
||||
*/
|
||||
bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
|
||||
|
||||
return gpiochip_reqres_irq(&kona_gpio->gpio_chip, gpio);
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
unsigned int gpio = d->hwirq;
|
||||
|
||||
gpiochip_relres_irq(&kona_gpio->gpio_chip, d->hwirq);
|
||||
/* Once we no longer use it, lock the GPIO again */
|
||||
bcm_kona_gpio_lock_gpio(kona_gpio, gpio);
|
||||
|
||||
gpiochip_relres_irq(&kona_gpio->gpio_chip, gpio);
|
||||
}
|
||||
|
||||
static struct irq_chip bcm_gpio_irq_chip = {
|
||||
|
@ -614,7 +659,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
|
|||
bank->irq = platform_get_irq(pdev, i);
|
||||
bank->kona_gpio = kona_gpio;
|
||||
if (bank->irq < 0) {
|
||||
dev_err(dev, "Couldn't get IRQ for bank %d", i);
|
||||
dev_err(dev, "Couldn't get IRQ for bank %d\n", i);
|
||||
ret = -ENOENT;
|
||||
goto err_irq_domain;
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
|
|||
[REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB,
|
||||
[REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB,
|
||||
};
|
||||
int i, j;
|
||||
int ret, i, j;
|
||||
|
||||
/*
|
||||
* STMPE1600: to be able to get IRQ from pins,
|
||||
|
@ -199,8 +199,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
|
|||
* GPSR or GPCR registers
|
||||
*/
|
||||
if (stmpe->partnum == STMPE1600) {
|
||||
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
|
||||
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
|
||||
ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
|
||||
if (ret < 0) {
|
||||
dev_err(stmpe->dev, "Failed to read GPMR_LSB: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
|
||||
if (ret < 0) {
|
||||
dev_err(stmpe->dev, "Failed to read GPMR_CSB: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < CACHE_NR_REGS; i++) {
|
||||
|
@ -222,6 +230,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
|
|||
}
|
||||
}
|
||||
|
||||
err:
|
||||
mutex_unlock(&stmpe_gpio->irq_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -1689,6 +1689,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
|
|||
.ignore_wake = "PNP0C50:00@8",
|
||||
},
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Spurious wakeups from GPIO 11
|
||||
* Found in BIOS 1.04
|
||||
* https://gitlab.freedesktop.org/drm/amd/-/issues/3954
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 14"),
|
||||
},
|
||||
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
|
||||
.ignore_interrupt = "AMDI0030:00@11",
|
||||
},
|
||||
},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
@ -904,13 +904,13 @@ int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev)
|
|||
}
|
||||
|
||||
if (gc->ngpio == 0) {
|
||||
chip_err(gc, "tried to insert a GPIO chip with zero lines\n");
|
||||
dev_err(dev, "tried to insert a GPIO chip with zero lines\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gc->ngpio > FASTPATH_NGPIO)
|
||||
chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n",
|
||||
gc->ngpio, FASTPATH_NGPIO);
|
||||
dev_warn(dev, "line cnt %u is greater than fast path cnt %u\n",
|
||||
gc->ngpio, FASTPATH_NGPIO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue