Commit 41c64bb1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull GPIO fixes from Linus Walleij:
 "Here is a bunch of GPIO fixes that I collected since -rc1, nothing
  controversial, nothing special:

   - fix a memory leak for GPIO hotplug.

   - fix a signedness bug in the ACPI GPIO pin validation.

   - driver fixes: Qualcomm SPMI and OMAP MPUIO IRQ issues"

* tag 'gpio-v4.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: omap: Fix regression for MPUIO interrupts
  gpio: sysfs: fix memory leaks and device hotplug
  pinctrl: qcom-spmi-gpio: Fix input value report
  pinctrl: qcom-spmi-gpio: Fix output type configuration
  gpiolib: change gpio pin from unsigned to signed in acpi callback
parents a8a08113 d2d05c65
Loading
Loading
Loading
Loading
+9 −39
Original line number Diff line number Diff line
@@ -1054,38 +1054,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
		dev_err(bank->dev, "Could not get gpio dbck\n");
}

static void
omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
		    unsigned int num)
{
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;

	gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
				    handle_simple_irq);
	if (!gc) {
		dev_err(bank->dev, "Memory alloc failed for gc\n");
		return;
	}

	ct = gc->chip_types;

	/* NOTE: No ack required, reading IRQ status clears it. */
	ct->chip.irq_mask = irq_gc_mask_set_bit;
	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
	ct->chip.irq_set_type = omap_gpio_irq_type;

	if (bank->regs->wkup_en)
		ct->chip.irq_set_wake = omap_gpio_wake_enable;

	ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
	irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}

static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
{
	int j;
	static int gpio;
	int irq_base = 0;
	int ret;
@@ -1132,6 +1102,15 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
	}
#endif

	/* MPUIO is a bit different, reading IRQ status clears it */
	if (bank->is_mpuio) {
		irqc->irq_ack = dummy_irq_chip.irq_ack;
		irqc->irq_mask = irq_gc_mask_set_bit;
		irqc->irq_unmask = irq_gc_mask_clr_bit;
		if (!bank->regs->wkup_en)
			irqc->irq_set_wake = NULL;
	}

	ret = gpiochip_irqchip_add(&bank->chip, irqc,
				   irq_base, omap_gpio_irq_handler,
				   IRQ_TYPE_NONE);
@@ -1145,15 +1124,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
	gpiochip_set_chained_irqchip(&bank->chip, irqc,
				     bank->irq, omap_gpio_irq_handler);

	for (j = 0; j < bank->width; j++) {
		int irq = irq_find_mapping(bank->chip.irqdomain, j);
		if (bank->is_mpuio) {
			omap_mpuio_alloc_gc(bank, irq, bank->width);
			irq_set_chip_and_handler(irq, NULL, NULL);
			set_irq_flags(irq, 0);
		}
	}

	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -550,7 +550,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,

	length = min(agpio->pin_table_length, (u16)(pin_index + bits));
	for (i = pin_index; i < length; ++i) {
		unsigned pin = agpio->pin_table[i];
		int pin = agpio->pin_table[i];
		struct acpi_gpio_connection *conn;
		struct gpio_desc *desc;
		bool found;
+19 −0
Original line number Diff line number Diff line
@@ -551,6 +551,7 @@ static struct class gpio_class = {
 */
int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
{
	struct gpio_chip	*chip;
	unsigned long		flags;
	int			status;
	const char		*ioname = NULL;
@@ -568,8 +569,16 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
		return -EINVAL;
	}

	chip = desc->chip;

	mutex_lock(&sysfs_lock);

	/* check if chip is being removed */
	if (!chip || !chip->exported) {
		status = -ENODEV;
		goto fail_unlock;
	}

	spin_lock_irqsave(&gpio_lock, flags);
	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
	     test_bit(FLAG_EXPORT, &desc->flags)) {
@@ -783,12 +792,15 @@ void gpiochip_unexport(struct gpio_chip *chip)
{
	int			status;
	struct device		*dev;
	struct gpio_desc *desc;
	unsigned int i;

	mutex_lock(&sysfs_lock);
	dev = class_find_device(&gpio_class, NULL, chip, match_export);
	if (dev) {
		put_device(dev);
		device_unregister(dev);
		/* prevent further gpiod exports */
		chip->exported = false;
		status = 0;
	} else
@@ -797,6 +809,13 @@ void gpiochip_unexport(struct gpio_chip *chip)

	if (status)
		chip_dbg(chip, "%s: status %d\n", __func__, status);

	/* unregister gpiod class devices owned by sysfs */
	for (i = 0; i < chip->ngpio; i++) {
		desc = &chip->desc[i];
		if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
			gpiod_free(desc);
	}
}

static int __init gpiolib_sysfs_init(void)
+7 −6
Original line number Diff line number Diff line
@@ -418,7 +418,7 @@ static int pmic_gpio_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
		return ret;

	val = pad->buffer_type << PMIC_GPIO_REG_OUT_TYPE_SHIFT;
	val = pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
	val |= pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;

	ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL, val);
	if (ret < 0)
@@ -467,13 +467,14 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
		seq_puts(s, " ---");
	} else {

		if (!pad->input_enabled) {
		if (pad->input_enabled) {
			ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
			if (!ret) {
			if (ret < 0)
				return;

			ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
			pad->out_value = ret;
		}
		}

		seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
		seq_printf(s, " %-7s", pmic_gpio_functions[pad->function]);