Commit 5fbe5b58 authored by Linus Walleij's avatar Linus Walleij
Browse files

gpio: Initialize the irqchip valid_mask with a callback



After changing the valid_mask for the struct gpio_chip
to detect the need and presence of a valid mask with the
presence of a .init_valid_mask() callback to fill it in,
we augment the gpio_irq_chip to use the same logic.

Switch all driver using the gpio_irq_chio valid_mask
over to this new method.

This makes sure the valid_mask for the gpio_irq_chip gets
filled in when we add the gpio_chip, which makes it a
little easier to switch over drivers using the old
way of setting up gpio_irq_chip over to the new method
of passing the gpio_irq_chip along with the gpio_chip.
(See drivers/gpio/TODO for details.)

Cc: Joel Stanley <joel@jms.id.au>
Cc: Thierry Reding <treding@nvidia.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Tested-by: default avatarHans de Goede <hdegoede@redhat.com>
Reviewed-by: default avatarAndrew Jeffery <andrew@aj.id.au>
Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarPatrice Chotard <patrice.chotard@st.com>
Link: https://lore.kernel.org/r/20190904140104.32426-1-linus.walleij@linaro.org
parent 4f78d91c
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -689,8 +689,11 @@ static struct irq_chip aspeed_gpio_irqchip = {
	.irq_set_type	= aspeed_gpio_set_type,
};

static void set_irq_valid_mask(struct aspeed_gpio *gpio)
static void aspeed_init_irq_valid_mask(struct gpio_chip *gc,
				       unsigned long *valid_mask,
				       unsigned int ngpios)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	const struct aspeed_bank_props *props = gpio->config->props;

	while (!is_bank_props_sentinel(props)) {
@@ -704,7 +707,7 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio)
			if (i >= gpio->config->nr_gpios)
				break;

			clear_bit(i, gpio->chip.irq.valid_mask);
			clear_bit(i, valid_mask);
		}

		props++;
@@ -1203,7 +1206,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
		girq->parents[0] = gpio->irq;
		girq->default_type = IRQ_TYPE_NONE;
		girq->handler = handle_bad_irq;
		girq->need_valid_mask = true;
		girq->init_valid_mask = aspeed_init_irq_valid_mask;
	}

	gpio->offset_timer =
@@ -1215,10 +1218,6 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
	if (rc < 0)
		return rc;

	/* Now the valid mask is allocated */
	if (gpio->irq)
		set_irq_valid_mask(gpio);

	return 0;
}

+26 −10
Original line number Diff line number Diff line
@@ -429,6 +429,23 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
	return IRQ_HANDLED;
}

static void stmpe_init_irq_valid_mask(struct gpio_chip *gc,
				      unsigned long *valid_mask,
				      unsigned int ngpios)
{
	struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
	int i;

	if (!stmpe_gpio->norequest_mask)
		return;

	/* Forbid unused lines to be mapped as IRQs */
	for (i = 0; i < sizeof(u32); i++) {
		if (stmpe_gpio->norequest_mask & BIT(i))
			clear_bit(i, valid_mask);
	}
}

static int stmpe_gpio_probe(struct platform_device *pdev)
{
	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
@@ -454,14 +471,21 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
	stmpe_gpio->chip.parent = &pdev->dev;
	stmpe_gpio->chip.of_node = np;
	stmpe_gpio->chip.base = -1;
	/*
	 * REVISIT: this makes sure the valid mask gets allocated and
	 * filled in when adding the gpio_chip, but the rest of the
	 * gpio_irqchip is still filled in using the old method
	 * in gpiochip_irqchip_add_nested() so clean this up once we
	 * get the gpio_irqchip to initialize while adding the
	 * gpio_chip also for threaded irqchips.
	 */
	stmpe_gpio->chip.irq.init_valid_mask = stmpe_init_irq_valid_mask;

	if (IS_ENABLED(CONFIG_DEBUG_FS))
                stmpe_gpio->chip.dbg_show = stmpe_dbg_show;

	of_property_read_u32(np, "st,norequest-mask",
			&stmpe_gpio->norequest_mask);
	if (stmpe_gpio->norequest_mask)
		stmpe_gpio->chip.irq.need_valid_mask = true;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
@@ -487,14 +511,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
			dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
			goto out_disable;
		}
		if (stmpe_gpio->norequest_mask) {
			int i;

			/* Forbid unused lines to be mapped as IRQs */
			for (i = 0; i < sizeof(u32); i++)
				if (stmpe_gpio->norequest_mask & BIT(i))
					clear_bit(i, stmpe_gpio->chip.irq.valid_mask);
		}
		ret =  gpiochip_irqchip_add_nested(&stmpe_gpio->chip,
						   &stmpe_gpio_irq_chip,
						   0,
+12 −9
Original line number Diff line number Diff line
@@ -214,6 +214,17 @@ static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = {
			   tqmx86_gpio_runtime_resume, NULL)
};

static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip,
				       unsigned long *valid_mask,
				       unsigned int ngpios)
{
	/* Only GPIOs 4-7 are valid for interrupts. Clear the others */
	clear_bit(0, valid_mask);
	clear_bit(1, valid_mask);
	clear_bit(2, valid_mask);
	clear_bit(3, valid_mask);
}

static int tqmx86_gpio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
@@ -260,7 +271,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
	chip->get = tqmx86_gpio_get;
	chip->set = tqmx86_gpio_set;
	chip->ngpio = TQMX86_NGPIO;
	chip->irq.need_valid_mask = true;
	chip->parent = pdev->dev.parent;

	pm_runtime_enable(&pdev->dev);
@@ -296,6 +306,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
		girq->parents[0] = irq;
		girq->default_type = IRQ_TYPE_NONE;
		girq->handler = handle_simple_irq;
		girq->init_valid_mask = tqmx86_init_irq_valid_mask;
	}

	ret = devm_gpiochip_add_data(dev, chip, gpio);
@@ -304,14 +315,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
		goto out_pm_dis;
	}

	/* Only GPIOs 4-7 are valid for interrupts. Clear the others */
	if (irq) {
		clear_bit(0, girq->valid_mask);
		clear_bit(1, girq->valid_mask);
		clear_bit(2, girq->valid_mask);
		clear_bit(3, girq->valid_mask);
	}

	dev_info(dev, "GPIO functionality initialized with %d pins\n",
		 chip->ngpio);

+8 −4
Original line number Diff line number Diff line
@@ -1615,15 +1615,19 @@ static struct gpio_chip *find_chip_by_name(const char *name)
 * The following is irqchip helper code for gpiochips.
 */

static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc)
{
	if (!gpiochip->irq.need_valid_mask)
	struct gpio_irq_chip *girq = &gc->irq;

	if (!girq->init_valid_mask)
		return 0;

	gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip);
	if (!gpiochip->irq.valid_mask)
	girq->valid_mask = gpiochip_allocate_mask(gc);
	if (!girq->valid_mask)
		return -ENOMEM;

	girq->init_valid_mask(gc, girq->valid_mask, gc->ngpio);

	return 0;
}

+15 −1
Original line number Diff line number Diff line
@@ -1455,6 +1455,20 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
	chip->irq_eoi(data);
}

static void byt_init_irq_valid_mask(struct gpio_chip *chip,
				    unsigned long *valid_mask,
				    unsigned int ngpios)
{
	/*
	 * FIXME: currently the valid_mask is filled in as part of
	 * initializing the irq_chip below in byt_gpio_irq_init_hw().
	 * when converting this driver to the new way of passing the
	 * gpio_irq_chip along when adding the gpio_chip, move the
	 * mask initialization into this callback instead. Right now
	 * this callback is here to make sure the mask gets allocated.
	 */
}

static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
{
	struct gpio_chip *gc = &vg->chip;
@@ -1525,7 +1539,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
	gc->can_sleep	= false;
	gc->parent	= &vg->pdev->dev;
	gc->ngpio	= vg->soc_data->npins;
	gc->irq.need_valid_mask	= true;
	gc->irq.init_valid_mask	= byt_init_irq_valid_mask;

#ifdef CONFIG_PM_SLEEP
	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
Loading