diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2019-09-04 16:01:04 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2019-09-11 01:09:37 +0100 |
commit | 5fbe5b5883f847363ff1b7280e8b1d2980526b8e (patch) | |
tree | 806efff2538fb4d6860cae617f4990f47481db7c /drivers/gpio | |
parent | 4f78d91c722345de94a3c72da49b9d0d49cb76b8 (diff) | |
download | linux-5fbe5b5883f847363ff1b7280e8b1d2980526b8e.tar.bz2 |
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: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Link: https://lore.kernel.org/r/20190904140104.32426-1-linus.walleij@linaro.org
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-aspeed.c | 13 | ||||
-rw-r--r-- | drivers/gpio/gpio-stmpe.c | 36 | ||||
-rw-r--r-- | drivers/gpio/gpio-tqmx86.c | 21 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 12 |
4 files changed, 52 insertions, 30 deletions
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 9defe25d4721..7bcd83dbc3e3 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -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; } diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index dbf9cbe36b2b..994d542daf53 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -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, diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index 07050cdbadb9..a3109bcaa0ac 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -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); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 56d0898d94aa..f5b2649e2893 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -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; } |