Loading drivers/gpio/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -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. Loading drivers/gpio/gpio-mcp23s08.c +30 −55 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) Loading Loading @@ -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); } } Loading @@ -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); Loading @@ -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); Loading @@ -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; Loading @@ -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]); Loading @@ -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, Loading @@ -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); } Loading @@ -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 Loading @@ -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); } return 0; 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; } 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; } /*----------------------------------------------------------------------*/ Loading Loading @@ -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; } } Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading
drivers/gpio/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
drivers/gpio/gpio-mcp23s08.c +30 −55 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) Loading Loading @@ -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); } } Loading @@ -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); Loading @@ -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); Loading @@ -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; Loading @@ -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]); Loading @@ -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, Loading @@ -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); } Loading @@ -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 Loading @@ -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); } return 0; 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; } 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; } /*----------------------------------------------------------------------*/ Loading Loading @@ -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; } } Loading Loading @@ -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); Loading Loading @@ -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); } Loading