diff options
Diffstat (limited to 'drivers/gpio')
48 files changed, 1949 insertions, 1579 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c6b5c65c8405..8030fd91a3cc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -410,7 +410,7 @@ config GPIO_MXS config GPIO_OCTEON tristate "Cavium OCTEON GPIO" - depends on GPIOLIB && CAVIUM_OCTEON_SOC + depends on CAVIUM_OCTEON_SOC default y help Say yes here to support the on-chip GPIO lines on the OCTEON @@ -962,6 +962,14 @@ config GPIO_PCA953X_IRQ Say yes here to enable the pca953x to be used as an interrupt controller. It requires the driver to be built in the kernel. +config GPIO_PCA9570 + tristate "PCA9570 4-Bit I2C GPO expander" + help + Say yes here to enable the GPO driver for the NXP PCA9570 chip. + + To compile this driver as a module, choose M here: the module will + be called gpio-pca9570. + config GPIO_PCF857X tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" select GPIOLIB_IRQCHIP @@ -1117,7 +1125,7 @@ config GPIO_DLN2 config HTC_EGPIO bool "HTC EGPIO support" - depends on GPIOLIB && ARM + depends on ARM help This driver supports the CPLD egpio chip present on several HTC phones. It provides basic support for input diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1e4894e0bf0f..4f9abff4f2dc 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIOLIB) += gpiolib-devres.o obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o +obj-$(CONFIG_GPIOLIB) += gpiolib-cdev.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o @@ -110,6 +111,7 @@ obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o +obj-$(CONFIG_GPIO_PCA9570) += gpio-pca9570.o obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o obj-$(CONFIG_GPIO_PCH) += gpio-pch.o obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO index b989c9352da2..e560e45e84f8 100644 --- a/drivers/gpio/TODO +++ b/drivers/gpio/TODO @@ -5,7 +5,7 @@ subsystem. GPIO descriptors Starting with commit 79a9becda894 the GPIO subsystem embarked on a journey -to move away from the global GPIO numberspace and toward a decriptor-based +to move away from the global GPIO numberspace and toward a descriptor-based approach. This means that GPIO consumers, drivers and machine descriptions ideally have no use or idea of the global GPIO numberspace that has/was used in the inception of the GPIO subsystem. diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 1f7d9bbec0fc..7a9021c4fa48 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -368,10 +368,21 @@ static const char *dio48e_names[DIO48E_NGPIO] = { "PPI Group 1 Port C 5", "PPI Group 1 Port C 6", "PPI Group 1 Port C 7" }; +static int dio48e_irq_init_hw(struct gpio_chip *gc) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(gc); + + /* Disable IRQ by default */ + inb(dio48egpio->base + 0xB); + + return 0; +} + static int dio48e_probe(struct device *dev, unsigned int id) { struct dio48e_gpio *dio48egpio; const char *const name = dev_name(dev); + struct gpio_irq_chip *girq; int err; dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); @@ -399,13 +410,17 @@ static int dio48e_probe(struct device *dev, unsigned int id) dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple; dio48egpio->base = base[id]; - raw_spin_lock_init(&dio48egpio->lock); + girq = &dio48egpio->chip.irq; + girq->chip = &dio48e_irqchip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_edge_irq; + girq->init_hw = dio48e_irq_init_hw; - err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } + raw_spin_lock_init(&dio48egpio->lock); /* initialize all GPIO as output */ outb(0x80, base[id] + 3); @@ -419,13 +434,9 @@ static int dio48e_probe(struct device *dev, unsigned int id) outb(0x00, base[id] + 6); outb(0x00, base[id] + 7); - /* disable IRQ by default */ - inb(base[id] + 0xB); - - err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0, - handle_edge_irq, IRQ_TYPE_NONE); + err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio); if (err) { - dev_err(dev, "Could not add irqchip (%d)\n", err); + dev_err(dev, "GPIO registering failed (%d)\n", err); return err; } diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index d350ac0de06b..94c3a9bc4e75 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -247,10 +247,22 @@ static const char *idi48_names[IDI48_NGPIO] = { "Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B" }; +static int idi_48_irq_init_hw(struct gpio_chip *gc) +{ + struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc); + + /* Disable IRQ by default */ + outb(0, idi48gpio->base + 7); + inb(idi48gpio->base + 7); + + return 0; +} + static int idi_48_probe(struct device *dev, unsigned int id) { struct idi_48_gpio *idi48gpio; const char *const name = dev_name(dev); + struct gpio_irq_chip *girq; int err; idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL); @@ -275,6 +287,16 @@ static int idi_48_probe(struct device *dev, unsigned int id) idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple; idi48gpio->base = base[id]; + girq = &idi48gpio->chip.irq; + girq->chip = &idi_48_irqchip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_edge_irq; + girq->init_hw = idi_48_irq_init_hw; + raw_spin_lock_init(&idi48gpio->lock); spin_lock_init(&idi48gpio->ack_lock); @@ -284,17 +306,6 @@ static int idi_48_probe(struct device *dev, unsigned int id) return err; } - /* Disable IRQ by default */ - outb(0, base[id] + 7); - inb(base[id] + 7); - - err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0, - handle_edge_irq, IRQ_TYPE_NONE); - if (err) { - dev_err(dev, "Could not add irqchip (%d)\n", err); - return err; - } - err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED, name, idi48gpio); if (err) { diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 5752d9dab148..50ad0280fd78 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -224,10 +224,22 @@ static const char *idio_16_names[IDIO_16_NGPIO] = { "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" }; +static int idio_16_irq_init_hw(struct gpio_chip *gc) +{ + struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc); + + /* Disable IRQ by default */ + outb(0, idio16gpio->base + 2); + outb(0, idio16gpio->base + 1); + + return 0; +} + static int idio_16_probe(struct device *dev, unsigned int id) { struct idio_16_gpio *idio16gpio; const char *const name = dev_name(dev); + struct gpio_irq_chip *girq; int err; idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); @@ -256,6 +268,16 @@ static int idio_16_probe(struct device *dev, unsigned int id) idio16gpio->base = base[id]; idio16gpio->out_state = 0xFFFF; + girq = &idio16gpio->chip.irq; + girq->chip = &idio_16_irqchip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_edge_irq; + girq->init_hw = idio_16_irq_init_hw; + raw_spin_lock_init(&idio16gpio->lock); err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); @@ -264,17 +286,6 @@ static int idio_16_probe(struct device *dev, unsigned int id) return err; } - /* Disable IRQ by default */ - outb(0, base[id] + 2); - outb(0, base[id] + 1); - - err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, - handle_edge_irq, IRQ_TYPE_NONE); - if (err) { - dev_err(dev, "Could not add irqchip (%d)\n", err); - return err; - } - err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name, idio16gpio); if (err) { diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index b9fcaab2a931..8eedfc6451df 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -238,36 +238,6 @@ unlock: mutex_unlock(&adnp->i2c_lock); } -static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) -{ - struct gpio_chip *chip = &adnp->gpio; - int err; - - adnp->reg_shift = get_count_order(num_gpios) - 3; - - chip->direction_input = adnp_gpio_direction_input; - chip->direction_output = adnp_gpio_direction_output; - chip->get = adnp_gpio_get; - chip->set = adnp_gpio_set; - chip->can_sleep = true; - - if (IS_ENABLED(CONFIG_DEBUG_FS)) - chip->dbg_show = adnp_gpio_dbg_show; - - chip->base = -1; - chip->ngpio = num_gpios; - chip->label = adnp->client->name; - chip->parent = &adnp->client->dev; - chip->of_node = chip->parent->of_node; - chip->owner = THIS_MODULE; - - err = devm_gpiochip_add_data(&adnp->client->dev, chip, adnp); - if (err) - return err; - - return 0; -} - static irqreturn_t adnp_irq(int irq, void *data) { struct adnp *adnp = data; @@ -464,18 +434,54 @@ static int adnp_irq_setup(struct adnp *adnp) return err; } - err = gpiochip_irqchip_add_nested(chip, - &adnp_irq_chip, - 0, - handle_simple_irq, - IRQ_TYPE_NONE); - if (err) { - dev_err(chip->parent, - "could not connect irqchip to gpiochip\n"); - return err; + return 0; +} + +static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios, + bool is_irq_controller) +{ + struct gpio_chip *chip = &adnp->gpio; + int err; + + adnp->reg_shift = get_count_order(num_gpios) - 3; + + chip->direction_input = adnp_gpio_direction_input; + chip->direction_output = adnp_gpio_direction_output; + chip->get = adnp_gpio_get; + chip->set = adnp_gpio_set; + chip->can_sleep = true; + + if (IS_ENABLED(CONFIG_DEBUG_FS)) + chip->dbg_show = adnp_gpio_dbg_show; + + chip->base = -1; + chip->ngpio = num_gpios; + chip->label = adnp->client->name; + chip->parent = &adnp->client->dev; + chip->of_node = chip->parent->of_node; + chip->owner = THIS_MODULE; + + if (is_irq_controller) { + struct gpio_irq_chip *girq; + + err = adnp_irq_setup(adnp); + if (err) + return err; + + girq = &chip->irq; + girq->chip = &adnp_irq_chip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + girq->threaded = true; } - gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq); + err = devm_gpiochip_add_data(&adnp->client->dev, chip, adnp); + if (err) + return err; return 0; } @@ -503,16 +509,11 @@ static int adnp_i2c_probe(struct i2c_client *client, mutex_init(&adnp->i2c_lock); adnp->client = client; - err = adnp_gpio_setup(adnp, num_gpios); + err = adnp_gpio_setup(adnp, num_gpios, + of_property_read_bool(np, "interrupt-controller")); if (err) return err; - if (of_find_property(np, "interrupt-controller", NULL)) { - err = adnp_irq_setup(adnp); - if (err) - return err; - } - i2c_set_clientdata(client, adnp); return 0; diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 49f423d7beba..f1e4ac90e7d3 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -272,13 +272,24 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid) return IRQ_HANDLED; } + +static int adp5588_irq_init_hw(struct gpio_chip *gc) +{ + struct adp5588_gpio *dev = gpiochip_get_data(gc); + /* Enable IRQs after registering chip */ + adp5588_gpio_write(dev->client, CFG, + ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN); + + return 0; +} + static int adp5588_irq_setup(struct adp5588_gpio *dev) { struct i2c_client *client = dev->client; int ret; struct adp5588_gpio_platform_data *pdata = dev_get_platdata(&client->dev); - int irq_base = pdata ? pdata->irq_base : 0; + struct gpio_irq_chip *girq; adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC); adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */ @@ -294,21 +305,19 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev) client->irq); return ret; } - ret = gpiochip_irqchip_add_nested(&dev->gpio_chip, - &adp5588_irq_chip, irq_base, - handle_simple_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(&client->dev, - "could not connect irqchip to gpiochip\n"); - return ret; - } - gpiochip_set_nested_irqchip(&dev->gpio_chip, - &adp5588_irq_chip, - client->irq); - adp5588_gpio_write(client, CFG, - ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN); + /* This will be registered in the call to devm_gpiochip_add_data() */ + girq = &dev->gpio_chip.irq; + girq->chip = &adp5588_irq_chip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->first = pdata ? pdata->irq_base : 0; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + girq->init_hw = adp5588_irq_init_hw; + girq->threaded = true; return 0; } diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 9b0adbdddbfc..424a3d25350b 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -10,6 +10,7 @@ #include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/ctype.h> +#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> #include <linux/gpio/machine.h> @@ -38,9 +39,9 @@ static DEFINE_IDR(gpio_aggregator_idr); static char *get_arg(char **args) { - char *start = *args, *end; + char *start, *end; - start = skip_spaces(start); + start = skip_spaces(*args); if (!*start) return NULL; @@ -111,55 +112,45 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key, static int aggr_parse(struct gpio_aggregator *aggr) { - unsigned int first_index, last_index, i, n = 0; - char *name, *offsets, *first, *last, *next; char *args = aggr->args; - int error; + unsigned long *bitmap; + unsigned int i, n = 0; + char *name, *offsets; + int error = 0; + + bitmap = bitmap_alloc(ARCH_NR_GPIOS, GFP_KERNEL); + if (!bitmap) + return -ENOMEM; for (name = get_arg(&args), offsets = get_arg(&args); name; offsets = get_arg(&args)) { if (IS_ERR(name)) { pr_err("Cannot get GPIO specifier: %pe\n", name); - return PTR_ERR(name); + error = PTR_ERR(name); + goto free_bitmap; } if (!isrange(offsets)) { /* Named GPIO line */ error = aggr_add_gpio(aggr, name, U16_MAX, &n); if (error) - return error; + goto free_bitmap; name = offsets; continue; } /* GPIO chip + offset(s) */ - for (first = offsets; *first; first = next) { - next = strchrnul(first, ','); - if (*next) - *next++ = '\0'; - - last = strchr(first, '-'); - if (last) - *last++ = '\0'; - - if (kstrtouint(first, 10, &first_index)) { - pr_err("Cannot parse GPIO index %s\n", first); - return -EINVAL; - } - - if (!last) { - last_index = first_index; - } else if (kstrtouint(last, 10, &last_index)) { - pr_err("Cannot parse GPIO index %s\n", last); - return -EINVAL; - } - - for (i = first_index; i <= last_index; i++) { - error = aggr_add_gpio(aggr, name, i, &n); - if (error) - return error; - } + error = bitmap_parselist(offsets, bitmap, ARCH_NR_GPIOS); + if (error) { + pr_err("Cannot parse %s: %d\n", offsets, error); + goto free_bitmap; + } + + for_each_set_bit(i, bitmap, ARCH_NR_GPIOS) { + error = aggr_add_gpio(aggr, name, i, &n); + if (error) + goto free_bitmap; } name = get_arg(&args); @@ -167,10 +158,12 @@ static int aggr_parse(struct gpio_aggregator *aggr) if (!n) { pr_err("No GPIOs specified\n"); - return -EINVAL; + error = -EINVAL; } - return 0; +free_bitmap: + bitmap_free(bitmap); + return error; } static ssize_t new_device_store(struct device_driver *driver, const char *buf, diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index cc4ba71e4fe3..b7932ecc3b61 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -24,6 +24,7 @@ * @interrupt_trigger : specifies the hardware configured IRQ trigger type * (rising, falling, both, high) * @mapped_irq : kernel mapped irq number. +* @irq_chip : IRQ chip configuration */ struct altera_gpio_chip { struct of_mm_gpio_chip mmchip; @@ -69,7 +70,7 @@ static void altera_gpio_irq_mask(struct irq_data *d) raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); } -/** +/* * This controller's IRQ type is synthesized in hardware, so this function * just checks if the requested set_type matches the synthesized IRQ type */ diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 14d1f4c933b6..2ba225720086 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -129,7 +129,7 @@ static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio) regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value); } -static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) +static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned int gpio) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); int reg = to_reg(gpio, CTRL_OUT); @@ -140,7 +140,7 @@ static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) return regmap_write(cg->regmap, reg, CTLO_INPUT_SET); } -static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, +static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); @@ -152,7 +152,7 @@ static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value); } -static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) +static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned int gpio) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); unsigned int val; @@ -169,7 +169,7 @@ static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) } static void crystalcove_gpio_set(struct gpio_chip *chip, - unsigned gpio, int value) + unsigned int gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); int reg = to_reg(gpio, CTRL_OUT); @@ -183,7 +183,7 @@ static void crystalcove_gpio_set(struct gpio_chip *chip, regmap_update_bits(cg->regmap, reg, 1, 0); } -static int crystalcove_irq_type(struct irq_data *data, unsigned type) +static int crystalcove_irq_type(struct irq_data *data, unsigned int type) { struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); @@ -330,6 +330,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) int retval; struct device *dev = pdev->dev.parent; struct intel_soc_pmic *pmic = dev_get_drvdata(dev); + struct gpio_irq_chip *girq; if (irq < 0) return irq; @@ -353,46 +354,39 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) cg->chip.dbg_show = crystalcove_gpio_dbg_show; cg->regmap = pmic->regmap; - retval = devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg); + girq = &cg->chip.irq; + girq->chip = &crystalcove_irqchip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + girq->threaded = true; + + retval = devm_request_threaded_irq(&pdev->dev, irq, NULL, + crystalcove_gpio_irq_handler, + IRQF_ONESHOT, KBUILD_MODNAME, cg); if (retval) { - dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval); + dev_warn(&pdev->dev, "request irq failed: %d\n", retval); return retval; } - gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); - - retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler, - IRQF_ONESHOT, KBUILD_MODNAME, cg); - + retval = devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg); if (retval) { - dev_warn(&pdev->dev, "request irq failed: %d\n", retval); + dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval); return retval; } - gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq); - - return 0; -} - -static int crystalcove_gpio_remove(struct platform_device *pdev) -{ - struct crystalcove_gpio *cg = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - if (irq >= 0) - free_irq(irq, cg); return 0; } static struct platform_driver crystalcove_gpio_driver = { .probe = crystalcove_gpio_probe, - .remove = crystalcove_gpio_remove, .driver = { .name = "crystal_cove_gpio", }, }; - module_platform_driver(crystalcove_gpio_driver); MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>"); diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c index 26b40c8b8a12..4c5f6d0c8d74 100644 --- a/drivers/gpio/gpio-dln2.c +++ b/drivers/gpio/gpio-dln2.c @@ -440,6 +440,7 @@ static int dln2_gpio_probe(struct platform_device *pdev) { struct dln2_gpio *dln2; struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; int pins; int ret; @@ -476,6 +477,15 @@ static int dln2_gpio_probe(struct platform_device *pdev) dln2->gpio.direction_output = dln2_gpio_direction_output; dln2->gpio.set_config = dln2_gpio_set_config; + girq = &dln2->gpio.irq; + girq->chip = &dln2_gpio_irqchip; + /* The event comes from the outside so no parent handler */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + platform_set_drvdata(pdev, dln2); r |