Commit 6452feaf authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'gpio-fixes-for-v6.14-rc3-take2' of...

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
parents 7ff71e6d 7b4aebee
Loading
Loading
Loading
Loading
+58 −13
Original line number Diff line number Diff line
@@ -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,15 +102,25 @@ 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];

	if (bank->gpio_unlock_count[bit] == 0) {
		dev_err(kona_gpio->gpio_chip.parent,
			"Unbalanced locks for GPIO %u\n", gpio);
		return;
	}

	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);
		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,
					unsigned gpio)
@@ -102,16 +128,22 @@ 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];

	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);
		val &= ~BIT(bit);
		bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);

		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)
{
	struct bcm_kona_gpio *kona_gpio = gpiochip_get_data(chip);
@@ -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;

	/*
	 * 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, d->hwirq);
	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;

	/* 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, d->hwirq);
	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;
		}
+12 −3
Original line number Diff line number Diff line
@@ -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);
}

+14 −0
Original line number Diff line number Diff line
@@ -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 */
};

+3 −3
Original line number Diff line number Diff line
@@ -904,12 +904,12 @@ 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",
		dev_warn(dev, "line cnt %u is greater than fast path cnt %u\n",
			 gc->ngpio, FASTPATH_NGPIO);

	return 0;