1
0
Fork 0

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
alistair/sunxi64-5.4-dsi
Linus Walleij 2019-09-04 16:01:04 +02:00
parent 4f78d91c72
commit 5fbe5b5883
8 changed files with 111 additions and 54 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -1543,6 +1543,30 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
{}
};
static void chv_init_irq_valid_mask(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios)
{
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
const struct chv_community *community = pctrl->community;
int i;
/* Do not add GPIOs that can only generate GPEs to the IRQ domain */
for (i = 0; i < community->npins; i++) {
const struct pinctrl_pin_desc *desc;
u32 intsel;
desc = &community->pins[i];
intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0));
intsel &= CHV_PADCTRL0_INTSEL_MASK;
intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
if (intsel >= community->nirqs)
clear_bit(i, valid_mask);
}
}
static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
{
const struct chv_gpio_pinrange *range;
@ -1557,7 +1581,8 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
chip->label = dev_name(pctrl->dev);
chip->parent = pctrl->dev;
chip->base = -1;
chip->irq.need_valid_mask = need_valid_mask;
if (need_valid_mask)
chip->irq.init_valid_mask = chv_init_irq_valid_mask;
ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
if (ret) {
@ -1576,21 +1601,6 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
}
}
/* Do not add GPIOs that can only generate GPEs to the IRQ domain */
for (i = 0; i < community->npins; i++) {
const struct pinctrl_pin_desc *desc;
u32 intsel;
desc = &community->pins[i];
intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0));
intsel &= CHV_PADCTRL0_INTSEL_MASK;
intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
if (need_valid_mask && intsel >= community->nirqs)
clear_bit(i, chip->irq.valid_mask);
}
/*
* The same set of machines in chv_no_valid_mask[] have incorrectly
* configured GPIOs that generate spurious interrupts so we use

View File

@ -152,6 +152,13 @@ static const struct x86_cpu_id int0002_cpu_ids[] = {
{}
};
static void int0002_init_irq_valid_mask(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios)
{
bitmap_clear(valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
}
static int int0002_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -184,7 +191,7 @@ static int int0002_probe(struct platform_device *pdev)
chip->direction_output = int0002_gpio_direction_output;
chip->base = -1;
chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
chip->irq.need_valid_mask = true;
chip->irq.init_valid_mask = int0002_init_irq_valid_mask;
ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
if (ret) {
@ -192,8 +199,6 @@ static int int0002_probe(struct platform_device *pdev)
return ret;
}
bitmap_clear(chip->irq.valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
/*
* We manually request the irq here instead of passing a flow-handler
* to gpiochip_set_chained_irqchip, because the irq is shared.

View File

@ -202,11 +202,17 @@ struct gpio_irq_chip {
bool threaded;
/**
* @need_valid_mask:
*
* If set core allocates @valid_mask with all bits set to one.
* @init_valid_mask: optional routine to initialize @valid_mask, to be
* used if not all GPIO lines are valid interrupts. Sometimes some
* lines just cannot fire interrupts, and this routine, when defined,
* is passed a bitmap in "valid_mask" and it will have ngpios
* bits from 0..(ngpios-1) set to "1" as in valid. The callback can
* then directly set some bits to "0" if they cannot be used for
* interrupts.
*/
bool need_valid_mask;
void (*init_valid_mask)(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios);
/**
* @valid_mask: