diff options
author | Phil Reid <preid@electromag.com.au> | 2016-03-18 08:07:06 (GMT) |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-03-30 08:38:50 (GMT) |
commit | dad3d272957b006b9069486597610840f7063350 (patch) | |
tree | acaa2893b8a5c760e10bc59cfb2f90b55b4bff3f | |
parent | d46ab6823963de2165f5a2af7600ce830e990e53 (diff) | |
download | linux-dad3d272957b006b9069486597610840f7063350.tar.xz |
gpio: mcp23s08: switch to use gpiolib irqchip helpers
This switches the mcp23s08 driver to use the gpiolib irqchip
helpers.
Signed-off-by: Phil Reid <preid@electromag.com.au>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/gpio/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-mcp23s08.c | 85 |
2 files changed, 31 insertions, 55 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5f3429f..927be87 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1091,6 +1091,7 @@ menu "SPI or I2C GPIO expanders" config GPIO_MCP23S08 tristate "Microchip MCP23xxx I/O expander" + select GPIOLIB_IRQCHIP help SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 I/O expanders. diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 47e4869..ae61bc2 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -77,7 +77,6 @@ struct mcp23s08 { /* lock protects the cached values */ struct mutex lock; struct mutex irq_lock; - struct irq_domain *irq_domain; struct gpio_chip chip; @@ -96,11 +95,6 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; -/* This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; - /*----------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_I2C) @@ -369,7 +363,7 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) if ((BIT(i) & mcp->cache[MCP_INTF]) && ((BIT(i) & intcap & mcp->irq_rise) || (mcp->irq_fall & ~intcap & BIT(i)))) { - child_irq = irq_find_mapping(mcp->irq_domain, i); + child_irq = irq_find_mapping(mcp->chip.irqdomain, i); handle_nested_irq(child_irq); } } @@ -377,16 +371,10 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) return IRQ_HANDLED; } -static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct mcp23s08 *mcp = gpiochip_get_data(chip); - - return irq_find_mapping(mcp->irq_domain, offset); -} - static void mcp23s08_irq_mask(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; mcp->cache[MCP_GPINTEN] &= ~BIT(pos); @@ -394,7 +382,8 @@ static void mcp23s08_irq_mask(struct irq_data *data) static void mcp23s08_irq_unmask(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; mcp->cache[MCP_GPINTEN] |= BIT(pos); @@ -402,7 +391,8 @@ static void mcp23s08_irq_unmask(struct irq_data *data) static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); unsigned int pos = data->hwirq; int status = 0; @@ -426,14 +416,16 @@ static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) static void mcp23s08_irq_bus_lock(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); mutex_lock(&mcp->irq_lock); } static void mcp23s08_irq_bus_unlock(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); mutex_lock(&mcp->lock); mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); @@ -445,7 +437,8 @@ static void mcp23s08_irq_bus_unlock(struct irq_data *data) static int mcp23s08_irq_reqres(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) { dev_err(mcp->chip.parent, @@ -459,7 +452,8 @@ static int mcp23s08_irq_reqres(struct irq_data *data) static void mcp23s08_irq_relres(struct irq_data *data) { - struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mcp23s08 *mcp = gpiochip_get_data(gc); gpiochip_unlock_as_irq(&mcp->chip, data->hwirq); } @@ -478,17 +472,11 @@ static struct irq_chip mcp23s08_irq_chip = { static int mcp23s08_irq_setup(struct mcp23s08 *mcp) { struct gpio_chip *chip = &mcp->chip; - int err, irq, j; + int err; unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED; mutex_init(&mcp->irq_lock); - mcp->irq_domain = irq_domain_add_linear(chip->parent->of_node, - chip->ngpio, - &irq_domain_simple_ops, mcp); - if (!mcp->irq_domain) - return -ENODEV; - if (mcp->irq_active_high) irqflags |= IRQF_TRIGGER_HIGH; else @@ -503,30 +491,23 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) return err; } - chip->to_irq = mcp23s08_gpio_to_irq; - - for (j = 0; j < mcp->chip.ngpio; j++) { - irq = irq_create_mapping(mcp->irq_domain, j); - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_data(irq, mcp); - irq_set_chip(irq, &mcp23s08_irq_chip); - irq_set_nested_thread(irq, true); - irq_set_noprobe(irq); + err = gpiochip_irqchip_add(chip, + &mcp23s08_irq_chip, + 0, + handle_simple_irq, + IRQ_TYPE_NONE); + if (err) { + dev_err(chip->parent, + "could not connect irqchip to gpiochip: %d\n", err); + return err; } - return 0; -} -static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) -{ - unsigned int irq, i; + gpiochip_set_chained_irqchip(chip, + &mcp23s08_irq_chip, + mcp->irq, + NULL); - for (i = 0; i < mcp->chip.ngpio; i++) { - irq = irq_find_mapping(mcp->irq_domain, i); - if (irq > 0) - irq_dispose_mapping(irq); - } - - irq_domain_remove(mcp->irq_domain); + return 0; } /*----------------------------------------------------------------------*/ @@ -721,7 +702,6 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, if (mcp->irq && mcp->irq_controller) { status = mcp23s08_irq_setup(mcp); if (status) { - mcp23s08_irq_teardown(mcp); goto fail; } } @@ -847,9 +827,6 @@ static int mcp230xx_remove(struct i2c_client *client) { struct mcp23s08 *mcp = i2c_get_clientdata(client); - if (client->irq && mcp->irq_controller) - mcp23s08_irq_teardown(mcp); - gpiochip_remove(&mcp->chip); kfree(mcp); @@ -1017,8 +994,6 @@ static int mcp23s08_remove(struct spi_device *spi) if (!data->mcp[addr]) continue; - if (spi->irq && data->mcp[addr]->irq_controller) - mcp23s08_irq_teardown(data->mcp[addr]); gpiochip_remove(&data->mcp[addr]->chip); } |