diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 14:58:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 14:58:15 -0400 |
commit | ea584595fc85e65796335033dfca25ed655cd0ed (patch) | |
tree | 79d444c507472f6c66d887ad332e7c1784eeb4de /drivers/gpio | |
parent | 782d59c5dfc5ac39ac8cfb4c6dd40597938dde9c (diff) | |
parent | a092e19b688be88f7329bd05f90cb92ebe1a4f5b (diff) |
Merge tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO changes from Linus Walleij:
"This is the bulk of GPIO changes for the v3.18 development cycle:
- Increase the default ARCH_NR_GPIO from 256 to 512. This was done
to avoid having a custom <asm/gpio.h> header for the x86
architecture - GPIO is custom and complicated enough as it is
already! We want to move to a radix to store the descriptors going
forward, and finally get rid of this fixed array size altogether.
- Endgame patching of the gpio_remove() semantics initiated by
Abdoulaye Berthe. It is not accepted by the system that the
removal of a GPIO chip fails during eg reboot or shutdown, and
therefore the return value has now painfully been refactored away.
For special cases like GPIO expanders on a hot-pluggable bus like
USB, we may later add some gpiochip_try_remove() call, but for the
cases we have now, return values are moot.
- Some incremental refactoring of the gpiolib core and ACPI GPIO
library for more descriptor usage.
- Refactor the chained IRQ handler set-up method to handle also
threaded, nested interrupts and set up the parent IRQ correctly.
Switch STMPE and TC3589x drivers to use this registration method.
- Add a .irq_not_threaded flag to the struct gpio_chip, so that also
GPIO expanders that block but are still not using threaded IRQ
handlers.
- New drivers for the ARM64 X-Gene SoC GPIO controller.
- The syscon GPIO driver has been improved to handle the "DSP GPIO"
found on the TI Keystone 2 SoC:s.
- ADNP driver switched to use gpiolib irqchip helpers.
- Refactor the DWAPB driver to support being instantiated from and
MFD cell (platform device).
- Incremental feature improvement in the Zynq, MCP23S08, DWAPB, OMAP,
Xilinx and Crystalcove drivers.
- Various minor fixes"
* tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (52 commits)
gpio: pch: Build context save/restore only for PM
pinctrl: abx500: get rid of unused variable
gpio: ks8695: fix 'else should follow close brace '}''
gpio: stmpe: add verbose debug code
gpio: stmpe: fix up interrupt enable logic
gpio: staticize xway_stp_init()
gpio: handle also nested irqchips in the chained handler set-up
gpio: set parent irq on chained handlers
gpiolib: irqchip: use irq_find_mapping while removing irqchip
gpio: crystalcove: support virtual GPIO
pinctrl: bcm281xx: make Kconfig dependency more strict
gpio: kona: enable only on BCM_MOBILE or for compile testing
gpio, bcm-kona, LLVMLinux: Remove use of __initconst
gpio: Fix ngpio in gpio-xilinx driver
gpio: dwapb: fix pointer to integer cast
gpio: xgene: Remove unneeded #ifdef CONFIG_OF guard
gpio: xgene: Remove unneeded forward declation for struct xgene_gpio
gpio: xgene: Fix missing spin_lock_init()
gpio: ks8695: fix switch case indentation
gpiolib: add irq_not_threaded flag to gpio_chip
...
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 14 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-adnp.c | 155 | ||||
-rw-r--r-- | drivers/gpio/gpio-bcm-kona.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-crystalcove.c | 28 | ||||
-rw-r--r-- | drivers/gpio/gpio-cs5535.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-dwapb.c | 410 | ||||
-rw-r--r-- | drivers/gpio/gpio-ks8695.c | 30 | ||||
-rw-r--r-- | drivers/gpio/gpio-mcp23s08.c | 64 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 33 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 54 | ||||
-rw-r--r-- | drivers/gpio/gpio-pch.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-samsung.c | 50 | ||||
-rw-r--r-- | drivers/gpio/gpio-stmpe.c | 99 | ||||
-rw-r--r-- | drivers/gpio/gpio-stp-xway.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-syscon.c | 94 | ||||
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-xgene.c | 244 | ||||
-rw-r--r-- | drivers/gpio/gpio-xilinx.c | 27 | ||||
-rw-r--r-- | drivers/gpio/gpio-zynq.c | 89 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 30 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 90 |
22 files changed, 1054 insertions, 478 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9de1515e5808..0959ca9b6b27 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -136,7 +136,6 @@ config GPIO_DWAPB | |||
136 | tristate "Synopsys DesignWare APB GPIO driver" | 136 | tristate "Synopsys DesignWare APB GPIO driver" |
137 | select GPIO_GENERIC | 137 | select GPIO_GENERIC |
138 | select GENERIC_IRQ_CHIP | 138 | select GENERIC_IRQ_CHIP |
139 | depends on OF_GPIO | ||
140 | help | 139 | help |
141 | Say Y or M here to build support for the Synopsys DesignWare APB | 140 | Say Y or M here to build support for the Synopsys DesignWare APB |
142 | GPIO block. | 141 | GPIO block. |
@@ -334,6 +333,15 @@ config GPIO_TZ1090_PDC | |||
334 | help | 333 | help |
335 | Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs. | 334 | Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs. |
336 | 335 | ||
336 | config GPIO_XGENE | ||
337 | bool "APM X-Gene GPIO controller support" | ||
338 | depends on ARM64 && OF_GPIO | ||
339 | help | ||
340 | This driver is to support the GPIO block within the APM X-Gene SoC | ||
341 | platform's generic flash controller. The GPIO pins are muxed with | ||
342 | the generic flash controller's address and data pins. Say yes | ||
343 | here to enable the GFC GPIO functionality. | ||
344 | |||
337 | config GPIO_XILINX | 345 | config GPIO_XILINX |
338 | bool "Xilinx GPIO support" | 346 | bool "Xilinx GPIO support" |
339 | depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ | 347 | depends on PPC_OF || MICROBLAZE || ARCH_ZYNQ |
@@ -681,6 +689,7 @@ config GPIO_ADP5588_IRQ | |||
681 | config GPIO_ADNP | 689 | config GPIO_ADNP |
682 | tristate "Avionic Design N-bit GPIO expander" | 690 | tristate "Avionic Design N-bit GPIO expander" |
683 | depends on I2C && OF_GPIO | 691 | depends on I2C && OF_GPIO |
692 | select GPIOLIB_IRQCHIP | ||
684 | help | 693 | help |
685 | This option enables support for N GPIOs found on Avionic Design | 694 | This option enables support for N GPIOs found on Avionic Design |
686 | I2C GPIO expanders. The register space will be extended by powers | 695 | I2C GPIO expanders. The register space will be extended by powers |
@@ -796,7 +805,6 @@ config GPIO_MAX7301 | |||
796 | 805 | ||
797 | config GPIO_MCP23S08 | 806 | config GPIO_MCP23S08 |
798 | tristate "Microchip MCP23xxx I/O expander" | 807 | tristate "Microchip MCP23xxx I/O expander" |
799 | depends on OF_GPIO | ||
800 | depends on (SPI_MASTER && !I2C) || I2C | 808 | depends on (SPI_MASTER && !I2C) || I2C |
801 | help | 809 | help |
802 | SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 | 810 | SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017 |
@@ -880,7 +888,7 @@ config GPIO_MSIC | |||
880 | 888 | ||
881 | config GPIO_BCM_KONA | 889 | config GPIO_BCM_KONA |
882 | bool "Broadcom Kona GPIO" | 890 | bool "Broadcom Kona GPIO" |
883 | depends on OF_GPIO | 891 | depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) |
884 | help | 892 | help |
885 | Turn on GPIO support for Broadcom "Kona" chips. | 893 | Turn on GPIO support for Broadcom "Kona" chips. |
886 | 894 | ||
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 5d024e396622..e5d346cf3b6e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -101,6 +101,7 @@ obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o | |||
101 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o | 101 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o |
102 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o | 102 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o |
103 | obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o | 103 | obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o |
104 | obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o | ||
104 | obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o | 105 | obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o |
105 | obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o | 106 | obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o |
106 | obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o | 107 | obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o |
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index 416b2200d4f1..d3d0a90fe542 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c | |||
@@ -6,10 +6,9 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/gpio.h> | 9 | #include <linux/gpio/driver.h> |
10 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/irqdomain.h> | ||
13 | #include <linux/module.h> | 12 | #include <linux/module.h> |
14 | #include <linux/of_irq.h> | 13 | #include <linux/of_irq.h> |
15 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
@@ -27,8 +26,6 @@ struct adnp { | |||
27 | unsigned int reg_shift; | 26 | unsigned int reg_shift; |
28 | 27 | ||
29 | struct mutex i2c_lock; | 28 | struct mutex i2c_lock; |
30 | |||
31 | struct irq_domain *domain; | ||
32 | struct mutex irq_lock; | 29 | struct mutex irq_lock; |
33 | 30 | ||
34 | u8 *irq_enable; | 31 | u8 *irq_enable; |
@@ -253,6 +250,7 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
253 | static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) | 250 | static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) |
254 | { | 251 | { |
255 | struct gpio_chip *chip = &adnp->gpio; | 252 | struct gpio_chip *chip = &adnp->gpio; |
253 | int err; | ||
256 | 254 | ||
257 | adnp->reg_shift = get_count_order(num_gpios) - 3; | 255 | adnp->reg_shift = get_count_order(num_gpios) - 3; |
258 | 256 | ||
@@ -272,6 +270,10 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios) | |||
272 | chip->of_node = chip->dev->of_node; | 270 | chip->of_node = chip->dev->of_node; |
273 | chip->owner = THIS_MODULE; | 271 | chip->owner = THIS_MODULE; |
274 | 272 | ||
273 | err = gpiochip_add(chip); | ||
274 | if (err) | ||
275 | return err; | ||
276 | |||
275 | return 0; | 277 | return 0; |
276 | } | 278 | } |
277 | 279 | ||
@@ -326,7 +328,8 @@ static irqreturn_t adnp_irq(int irq, void *data) | |||
326 | 328 | ||
327 | for_each_set_bit(bit, &pending, 8) { | 329 | for_each_set_bit(bit, &pending, 8) { |
328 | unsigned int child_irq; | 330 | unsigned int child_irq; |
329 | child_irq = irq_find_mapping(adnp->domain, base + bit); | 331 | child_irq = irq_find_mapping(adnp->gpio.irqdomain, |
332 | base + bit); | ||
330 | handle_nested_irq(child_irq); | 333 | handle_nested_irq(child_irq); |
331 | } | 334 | } |
332 | } | 335 | } |
@@ -334,35 +337,32 @@ static irqreturn_t adnp_irq(int irq, void *data) | |||
334 | return IRQ_HANDLED; | 337 | return IRQ_HANDLED; |
335 | } | 338 | } |
336 | 339 | ||
337 | static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | 340 | static void adnp_irq_mask(struct irq_data *d) |
338 | { | ||
339 | struct adnp *adnp = to_adnp(chip); | ||
340 | return irq_create_mapping(adnp->domain, offset); | ||
341 | } | ||
342 | |||
343 | static void adnp_irq_mask(struct irq_data *data) | ||
344 | { | 341 | { |
345 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | 342 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
346 | unsigned int reg = data->hwirq >> adnp->reg_shift; | 343 | struct adnp *adnp = to_adnp(gc); |
347 | unsigned int pos = data->hwirq & 7; | 344 | unsigned int reg = d->hwirq >> adnp->reg_shift; |
345 | unsigned int pos = d->hwirq & 7; | ||
348 | 346 | ||
349 | adnp->irq_enable[reg] &= ~BIT(pos); | 347 | adnp->irq_enable[reg] &= ~BIT(pos); |
350 | } | 348 | } |
351 | 349 | ||
352 | static void adnp_irq_unmask(struct irq_data *data) | 350 | static void adnp_irq_unmask(struct irq_data *d) |
353 | { | 351 | { |
354 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | 352 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
355 | unsigned int reg = data->hwirq >> adnp->reg_shift; | 353 | struct adnp *adnp = to_adnp(gc); |
356 | unsigned int pos = data->hwirq & 7; | 354 | unsigned int reg = d->hwirq >> adnp->reg_shift; |
355 | unsigned int pos = d->hwirq & 7; | ||
357 | 356 | ||
358 | adnp->irq_enable[reg] |= BIT(pos); | 357 | adnp->irq_enable[reg] |= BIT(pos); |
359 | } | 358 | } |
360 | 359 | ||
361 | static int adnp_irq_set_type(struct irq_data *data, unsigned int type) | 360 | static int adnp_irq_set_type(struct irq_data *d, unsigned int type) |
362 | { | 361 | { |
363 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | 362 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
364 | unsigned int reg = data->hwirq >> adnp->reg_shift; | 363 | struct adnp *adnp = to_adnp(gc); |
365 | unsigned int pos = data->hwirq & 7; | 364 | unsigned int reg = d->hwirq >> adnp->reg_shift; |
365 | unsigned int pos = d->hwirq & 7; | ||
366 | 366 | ||
367 | if (type & IRQ_TYPE_EDGE_RISING) | 367 | if (type & IRQ_TYPE_EDGE_RISING) |
368 | adnp->irq_rise[reg] |= BIT(pos); | 368 | adnp->irq_rise[reg] |= BIT(pos); |
@@ -387,16 +387,18 @@ static int adnp_irq_set_type(struct irq_data *data, unsigned int type) | |||
387 | return 0; | 387 | return 0; |
388 | } | 388 | } |
389 | 389 | ||
390 | static void adnp_irq_bus_lock(struct irq_data *data) | 390 | static void adnp_irq_bus_lock(struct irq_data *d) |
391 | { | 391 | { |
392 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | 392 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
393 | struct adnp *adnp = to_adnp(gc); | ||
393 | 394 | ||
394 | mutex_lock(&adnp->irq_lock); | 395 | mutex_lock(&adnp->irq_lock); |
395 | } | 396 | } |
396 | 397 | ||
397 | static void adnp_irq_bus_unlock(struct irq_data *data) | 398 | static void adnp_irq_bus_unlock(struct irq_data *d) |
398 | { | 399 | { |
399 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | 400 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
401 | struct adnp *adnp = to_adnp(gc); | ||
400 | unsigned int num_regs = 1 << adnp->reg_shift, i; | 402 | unsigned int num_regs = 1 << adnp->reg_shift, i; |
401 | 403 | ||
402 | mutex_lock(&adnp->i2c_lock); | 404 | mutex_lock(&adnp->i2c_lock); |
@@ -408,26 +410,6 @@ static void adnp_irq_bus_unlock(struct irq_data *data) | |||
408 | mutex_unlock(&adnp->irq_lock); | 410 | mutex_unlock(&adnp->irq_lock); |
409 | } | 411 | } |
410 | 412 | ||
411 | static int adnp_irq_reqres(struct irq_data *data) | ||
412 | { | ||
413 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | ||
414 | |||
415 | if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) { | ||
416 | dev_err(adnp->gpio.dev, | ||
417 | "unable to lock HW IRQ %lu for IRQ\n", | ||
418 | data->hwirq); | ||
419 | return -EINVAL; | ||
420 | } | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static void adnp_irq_relres(struct irq_data *data) | ||
425 | { | ||
426 | struct adnp *adnp = irq_data_get_irq_chip_data(data); | ||
427 | |||
428 | gpio_unlock_as_irq(&adnp->gpio, data->hwirq); | ||
429 | } | ||
430 | |||
431 | static struct irq_chip adnp_irq_chip = { | 413 | static struct irq_chip adnp_irq_chip = { |
432 | .name = "gpio-adnp", | 414 | .name = "gpio-adnp", |
433 | .irq_mask = adnp_irq_mask, | 415 | .irq_mask = adnp_irq_mask, |
@@ -435,29 +417,6 @@ static struct irq_chip adnp_irq_chip = { | |||
435 | .irq_set_type = adnp_irq_set_type, | 417 | .irq_set_type = adnp_irq_set_type, |
436 | .irq_bus_lock = adnp_irq_bus_lock, | 418 | .irq_bus_lock = adnp_irq_bus_lock, |
437 | .irq_bus_sync_unlock = adnp_irq_bus_unlock, | 419 | .irq_bus_sync_unlock = adnp_irq_bus_unlock, |
438 | .irq_request_resources = adnp_irq_reqres, | ||
439 | .irq_release_resources = adnp_irq_relres, | ||
440 | }; | ||
441 | |||
442 | static int adnp_irq_map(struct irq_domain *domain, unsigned int irq, | ||
443 | irq_hw_number_t hwirq) | ||
444 | { | ||
445 | irq_set_chip_data(irq, domain->host_data); | ||
446 | irq_set_chip(irq, &adnp_irq_chip); | ||
447 | irq_set_nested_thread(irq, true); | ||
448 | |||
449 | #ifdef CONFIG_ARM | ||
450 | set_irq_flags(irq, IRQF_VALID); | ||
451 | #else | ||
452 | irq_set_noprobe(irq); | ||
453 | #endif | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static const struct irq_domain_ops adnp_irq_domain_ops = { | ||
459 | .map = adnp_irq_map, | ||
460 | .xlate = irq_domain_xlate_twocell, | ||
461 | }; | 420 | }; |
462 | 421 | ||
463 | static int adnp_irq_setup(struct adnp *adnp) | 422 | static int adnp_irq_setup(struct adnp *adnp) |
@@ -503,35 +462,28 @@ static int adnp_irq_setup(struct adnp *adnp) | |||
503 | adnp->irq_enable[i] = 0x00; | 462 | adnp->irq_enable[i] = 0x00; |
504 | } | 463 | } |
505 | 464 | ||
506 | adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio, | 465 | err = devm_request_threaded_irq(chip->dev, adnp->client->irq, |
507 | &adnp_irq_domain_ops, adnp); | 466 | NULL, adnp_irq, |
508 | 467 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
509 | err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq, | 468 | dev_name(chip->dev), adnp); |
510 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
511 | dev_name(chip->dev), adnp); | ||
512 | if (err != 0) { | 469 | if (err != 0) { |
513 | dev_err(chip->dev, "can't request IRQ#%d: %d\n", | 470 | dev_err(chip->dev, "can't request IRQ#%d: %d\n", |
514 | adnp->client->irq, err); | 471 | adnp->client->irq, err); |
515 | return err; | 472 | return err; |
516 | } | 473 | } |
517 | 474 | ||
518 | chip->to_irq = adnp_gpio_to_irq; | 475 | err = gpiochip_irqchip_add(chip, |
519 | return 0; | 476 | &adnp_irq_chip, |
520 | } | 477 | 0, |
521 | 478 | handle_simple_irq, | |
522 | static void adnp_irq_teardown(struct adnp *adnp) | 479 | IRQ_TYPE_NONE); |
523 | { | 480 | if (err) { |
524 | unsigned int irq, i; | 481 | dev_err(chip->dev, |
525 | 482 | "could not connect irqchip to gpiochip\n"); | |
526 | free_irq(adnp->client->irq, adnp); | 483 | return err; |
527 | |||
528 | for (i = 0; i < adnp->gpio.ngpio; i++) { | ||
529 | irq = irq_find_mapping(adnp->domain, i); | ||
530 | if (irq > 0) | ||
531 | irq_dispose_mapping(irq); | ||
532 | } | 484 | } |
533 | 485 | ||
534 | irq_domain_remove(adnp->domain); | 486 | return 0; |
535 | } | 487 | } |
536 | 488 | ||
537 | static int adnp_i2c_probe(struct i2c_client *client, | 489 | static int adnp_i2c_probe(struct i2c_client *client, |
@@ -558,38 +510,25 @@ static int adnp_i2c_probe(struct i2c_client *client, | |||
558 | adnp->client = client; | 510 | adnp->client = client; |
559 | 511 | ||
560 | err = adnp_gpio_setup(adnp, num_gpios); | 512 | err = adnp_gpio_setup(adnp, num_gpios); |
561 | if (err < 0) | 513 | if (err) |
562 | return err; | 514 | return err; |
563 | 515 | ||
564 | if (of_find_property(np, "interrupt-controller", NULL)) { | 516 | if (of_find_property(np, "interrupt-controller", NULL)) { |
565 | err = adnp_irq_setup(adnp); | 517 | err = adnp_irq_setup(adnp); |
566 | if (err < 0) | 518 | if (err) |
567 | goto teardown; | 519 | return err; |
568 | } | 520 | } |
569 | 521 | ||
570 | err = gpiochip_add(&adnp->gpio); | ||
571 | if (err < 0) | ||
572 | goto teardown; | ||
573 | |||
574 | i2c_set_clientdata(client, adnp); | 522 | i2c_set_clientdata(client, adnp); |
575 | return 0; | ||
576 | 523 | ||
577 | teardown: | 524 | return 0; |
578 | if (of_find_property(np, "interrupt-controller", NULL)) | ||
579 | adnp_irq_teardown(adnp); | ||
580 | |||
581 | return err; | ||
582 | } | 525 | } |
583 | 526 | ||
584 | static int adnp_i2c_remove(struct i2c_client *client) | 527 | static int adnp_i2c_remove(struct i2c_client *client) |
585 | { | 528 | { |
586 | struct adnp *adnp = i2c_get_clientdata(client); | 529 | struct adnp *adnp = i2c_get_clientdata(client); |
587 | struct device_node *np = client->dev.of_node; | ||
588 | 530 | ||
589 | gpiochip_remove(&adnp->gpio); | 531 | gpiochip_remove(&adnp->gpio); |
590 | if (of_find_property(np, "interrupt-controller", NULL)) | ||
591 | adnp_irq_teardown(adnp); | ||
592 | |||
593 | return 0; | 532 | return 0; |
594 | } | 533 | } |
595 | 534 | ||
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 3f6b33ce9bd4..de0801e9767a 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c | |||
@@ -496,7 +496,7 @@ static struct irq_chip bcm_gpio_irq_chip = { | |||
496 | .irq_release_resources = bcm_kona_gpio_irq_relres, | 496 | .irq_release_resources = bcm_kona_gpio_irq_relres, |
497 | }; | 497 | }; |
498 | 498 | ||
499 | static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { | 499 | static struct of_device_id const bcm_kona_gpio_of_match[] = { |
500 | { .compatible = "brcm,kona-gpio" }, | 500 | { .compatible = "brcm,kona-gpio" }, |
501 | {} | 501 | {} |
502 | }; | 502 | }; |
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 934462f5bd22..bbfe7f508502 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/mfd/intel_soc_pmic.h> | 24 | #include <linux/mfd/intel_soc_pmic.h> |
25 | 25 | ||
26 | #define CRYSTALCOVE_GPIO_NUM 16 | 26 | #define CRYSTALCOVE_GPIO_NUM 16 |
27 | #define CRYSTALCOVE_VGPIO_NUM 94 | ||
27 | 28 | ||
28 | #define UPDATE_IRQ_TYPE BIT(0) | 29 | #define UPDATE_IRQ_TYPE BIT(0) |
29 | #define UPDATE_IRQ_MASK BIT(1) | 30 | #define UPDATE_IRQ_MASK BIT(1) |
@@ -130,6 +131,9 @@ static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) | |||
130 | { | 131 | { |
131 | struct crystalcove_gpio *cg = to_cg(chip); | 132 | struct crystalcove_gpio *cg = to_cg(chip); |
132 | 133 | ||
134 | if (gpio > CRYSTALCOVE_VGPIO_NUM) | ||
135 | return 0; | ||
136 | |||
133 | return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), | 137 | return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), |
134 | CTLO_INPUT_SET); | 138 | CTLO_INPUT_SET); |
135 | } | 139 | } |
@@ -139,6 +143,9 @@ static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, | |||
139 | { | 143 | { |
140 | struct crystalcove_gpio *cg = to_cg(chip); | 144 | struct crystalcove_gpio *cg = to_cg(chip); |
141 | 145 | ||
146 | if (gpio > CRYSTALCOVE_VGPIO_NUM) | ||
147 | return 0; | ||
148 | |||
142 | return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), | 149 | return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), |
143 | CTLO_OUTPUT_SET | value); | 150 | CTLO_OUTPUT_SET | value); |
144 | } | 151 | } |
@@ -149,6 +156,9 @@ static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) | |||
149 | int ret; | 156 | int ret; |
150 | unsigned int val; | 157 | unsigned int val; |
151 | 158 | ||
159 | if (gpio > CRYSTALCOVE_VGPIO_NUM) | ||
160 | return 0; | ||
161 | |||
152 | ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val); | 162 | ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val); |
153 | if (ret) | 163 | if (ret) |
154 | return ret; | 164 | return ret; |
@@ -161,6 +171,9 @@ static void crystalcove_gpio_set(struct gpio_chip *chip, | |||
161 | { | 171 | { |
162 | struct crystalcove_gpio *cg = to_cg(chip); | 172 | struct crystalcove_gpio *cg = to_cg(chip); |
163 | 173 | ||
174 | if (gpio > CRYSTALCOVE_VGPIO_NUM) | ||
175 | return; | ||
176 | |||
164 | if (value) | 177 | if (value) |
165 | regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1); | 178 | regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1); |
166 | else | 179 | else |
@@ -256,7 +269,7 @@ static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) | |||
256 | 269 | ||
257 | pending = p0 | p1 << 8; | 270 | pending = p0 | p1 << 8; |
258 | 271 | ||
259 | for (gpio = 0; gpio < cg->chip.ngpio; gpio++) { | 272 | for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) { |
260 | if (pending & BIT(gpio)) { | 273 | if (pending & BIT(gpio)) { |
261 | virq = irq_find_mapping(cg->chip.irqdomain, gpio); | 274 | virq = irq_find_mapping(cg->chip.irqdomain, gpio); |
262 | generic_handle_irq(virq); | 275 | generic_handle_irq(virq); |
@@ -273,7 +286,7 @@ static void crystalcove_gpio_dbg_show(struct seq_file *s, | |||
273 | int gpio, offset; | 286 | int gpio, offset; |
274 | unsigned int ctlo, ctli, mirqs0, mirqsx, irq; | 287 | unsigned int ctlo, ctli, mirqs0, mirqsx, irq; |
275 | 288 | ||
276 | for (gpio = 0; gpio < cg->chip.ngpio; gpio++) { | 289 | for (gpio = 0; gpio < CRYSTALCOVE_GPIO_NUM; gpio++) { |
277 | regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo); | 290 | regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo); |
278 | regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli); | 291 | regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli); |
279 | regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0, | 292 | regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0, |
@@ -320,7 +333,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) | |||
320 | cg->chip.get = crystalcove_gpio_get; | 333 | cg->chip.get = crystalcove_gpio_get; |
321 | cg->chip.set = crystalcove_gpio_set; | 334 | cg->chip.set = crystalcove_gpio_set; |
322 | cg->chip.base = -1; | 335 | cg->chip.base = -1; |
323 | cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM; | 336 | cg->chip.ngpio = CRYSTALCOVE_VGPIO_NUM; |
324 | cg->chip.can_sleep = true; | 337 | cg->chip.can_sleep = true; |
325 | cg->chip.dev = dev; | 338 | cg->chip.dev = dev; |
326 | cg->chip.dbg_show = crystalcove_gpio_dbg_show; | 339 | cg->chip.dbg_show = crystalcove_gpio_dbg_show; |
@@ -346,7 +359,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) | |||
346 | return 0; | 359 | return 0; |
347 | 360 | ||
348 | out_remove_gpio: | 361 | out_remove_gpio: |
349 | WARN_ON(gpiochip_remove(&cg->chip)); | 362 | gpiochip_remove(&cg->chip); |
350 | return retval; | 363 | return retval; |
351 | } | 364 | } |
352 | 365 | ||
@@ -354,14 +367,11 @@ static int crystalcove_gpio_remove(struct platform_device *pdev) | |||
354 | { | 367 | { |
355 | struct crystalcove_gpio *cg = platform_get_drvdata(pdev); | 368 | struct crystalcove_gpio *cg = platform_get_drvdata(pdev); |
356 | int irq = platform_get_irq(pdev, 0); | 369 | int irq = platform_get_irq(pdev, 0); |
357 | int err; | ||
358 | |||
359 | err = gpiochip_remove(&cg->chip); | ||
360 | 370 | ||
371 | gpiochip_remove(&cg->chip); | ||
361 | if (irq >= 0) | 372 | if (irq >= 0) |
362 | free_irq(irq, cg); | 373 | free_irq(irq, cg); |
363 | 374 | return 0; | |
364 | return err; | ||
365 | } | 375 | } |
366 | 376 | ||
367 | static struct platform_driver crystalcove_gpio_driver = { | 377 | static struct platform_driver crystalcove_gpio_driver = { |
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c index 92ec58fa9236..668127fe90ef 100644 --- a/drivers/gpio/gpio-cs5535.c +++ b/drivers/gpio/gpio-cs5535.c | |||
@@ -201,7 +201,8 @@ EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event); | |||
201 | 201 | ||
202 | static int chip_gpio_request(struct gpio_chip *c, unsigned offset) | 202 | static int chip_gpio_request(struct gpio_chip *c, unsigned offset) |
203 | { | 203 | { |
204 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | 204 | struct cs5535_gpio_chip *chip = |
205 | container_of(c, struct cs5535_gpio_chip, chip); | ||
205 | unsigned long flags; | 206 | unsigned long flags; |
206 | 207 | ||
207 | spin_lock_irqsave(&chip->lock, flags); | 208 | spin_lock_irqsave(&chip->lock, flags); |
@@ -241,7 +242,8 @@ static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | |||
241 | 242 | ||
242 | static int chip_direction_input(struct gpio_chip *c, unsigned offset) | 243 | static int chip_direction_input(struct gpio_chip *c, unsigned offset) |
243 | { | 244 | { |
244 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | 245 | struct cs5535_gpio_chip *chip = |
246 | container_of(c, struct cs5535_gpio_chip, chip); | ||
245 | unsigned long flags; | 247 | unsigned long flags; |
246 | 248 | ||
247 | spin_lock_irqsave(&chip->lock, flags); | 249 | spin_lock_irqsave(&chip->lock, flags); |
@@ -254,7 +256,8 @@ static int chip_direction_input(struct gpio_chip *c, unsigned offset) | |||
254 | 256 | ||
255 | static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) | 257 | static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) |
256 | { | 258 | { |
257 | struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c; | 259 | struct cs5535_gpio_chip *chip = |
260 | container_of(c, struct cs5535_gpio_chip, chip); | ||
258 | unsigned long flags; | 261 | unsigned long flags; |
259 | 262 | ||
260 | spin_lock_irqsave(&chip->lock, flags); | 263 | spin_lock_irqsave(&chip->lock, flags); |
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index d6618a6e2399..b43cd84b61f1 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/of_irq.h> | 21 | #include <linux/of_irq.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/platform_data/gpio-dwapb.h> | ||
25 | #include <linux/slab.h> | ||
24 | 26 | ||
25 | #define GPIO_SWPORTA_DR 0x00 | 27 | #define GPIO_SWPORTA_DR 0x00 |
26 | #define GPIO_SWPORTA_DDR 0x04 | 28 | #define GPIO_SWPORTA_DDR 0x04 |
@@ -35,6 +37,7 @@ | |||
35 | #define GPIO_INTTYPE_LEVEL 0x38 | 37 | #define GPIO_INTTYPE_LEVEL 0x38 |
36 | #define GPIO_INT_POLARITY 0x3c | 38 | #define GPIO_INT_POLARITY 0x3c |
37 | #define GPIO_INTSTATUS 0x40 | 39 | #define GPIO_INTSTATUS 0x40 |
40 | #define GPIO_PORTA_DEBOUNCE 0x48 | ||
38 | #define GPIO_PORTA_EOI 0x4c | 41 | #define GPIO_PORTA_EOI 0x4c |
39 | #define GPIO_EXT_PORTA 0x50 | 42 | #define GPIO_EXT_PORTA 0x50 |
40 | #define GPIO_EXT_PORTB 0x54 | 43 | #define GPIO_EXT_PORTB 0x54 |
@@ -48,10 +51,28 @@ | |||
48 | 51 | ||
49 | struct dwapb_gpio; | 52 | struct dwapb_gpio; |
50 | 53 | ||
54 | #ifdef CONFIG_PM_SLEEP | ||
55 | /* Store GPIO context across system-wide suspend/resume transitions */ | ||
56 | struct dwapb_context { | ||
57 | u32 data; | ||
58 | u32 dir; | ||
59 | u32 ext; | ||
60 | u32 int_en; | ||
61 | u32 int_mask; | ||
62 | u32 int_type; | ||
63 | u32 int_pol; | ||
64 | u32 int_deb; | ||
65 | }; | ||
66 | #endif | ||
67 | |||
51 | struct dwapb_gpio_port { | 68 | struct dwapb_gpio_port { |
52 | struct bgpio_chip bgc; | 69 | struct bgpio_chip bgc; |
53 | bool is_registered; | 70 | bool is_registered; |
54 | struct dwapb_gpio *gpio; | 71 | struct dwapb_gpio *gpio; |
72 | #ifdef CONFIG_PM_SLEEP | ||
73 | struct dwapb_context *ctx; | ||
74 | #endif | ||
75 | unsigned int idx; | ||
55 | }; | 76 | }; |
56 | 77 | ||
57 | struct dwapb_gpio { | 78 | struct dwapb_gpio { |
@@ -62,11 +83,33 @@ struct dwapb_gpio { | |||
62 | struct irq_domain *domain; | 83 | struct irq_domain *domain; |
63 | }; | 84 | }; |
64 | 85 | ||
86 | static inline struct dwapb_gpio_port * | ||
87 | to_dwapb_gpio_port(struct bgpio_chip *bgc) | ||
88 | { | ||
89 | return container_of(bgc, struct dwapb_gpio_port, bgc); | ||
90 | } | ||
91 | |||
92 | static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset) | ||
93 | { | ||
94 | struct bgpio_chip *bgc = &gpio->ports[0].bgc; | ||
95 | void __iomem *reg_base = gpio->regs; | ||
96 | |||
97 | return bgc->read_reg(reg_base + offset); | ||
98 | } | ||
99 | |||
100 | static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset, | ||
101 | u32 val) | ||
102 | { | ||
103 | struct bgpio_chip *bgc = &gpio->ports[0].bgc; | ||
104 | void __iomem *reg_base = gpio->regs; | ||
105 | |||
106 | bgc->write_reg(reg_base + offset, val); | ||
107 | } | ||
108 | |||
65 | static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | 109 | static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) |
66 | { | 110 | { |
67 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | 111 | struct bgpio_chip *bgc = to_bgpio_chip(gc); |
68 | struct dwapb_gpio_port *port = container_of(bgc, struct | 112 | struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc); |
69 | dwapb_gpio_port, bgc); | ||
70 | struct dwapb_gpio *gpio = port->gpio; | 113 | struct dwapb_gpio *gpio = port->gpio; |
71 | 114 | ||
72 | return irq_find_mapping(gpio->domain, offset); | 115 | return irq_find_mapping(gpio->domain, offset); |
@@ -74,21 +117,20 @@ static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
74 | 117 | ||
75 | static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) | 118 | static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) |
76 | { | 119 | { |
77 | u32 v = readl(gpio->regs + GPIO_INT_POLARITY); | 120 | u32 v = dwapb_read(gpio, GPIO_INT_POLARITY); |
78 | 121 | ||
79 | if (gpio_get_value(gpio->ports[0].bgc.gc.base + offs)) | 122 | if (gpio_get_value(gpio->ports[0].bgc.gc.base + offs)) |
80 | v &= ~BIT(offs); | 123 | v &= ~BIT(offs); |
81 | else | 124 | else |
82 | v |= BIT(offs); | 125 | v |= BIT(offs); |
83 | 126 | ||
84 | writel(v, gpio->regs + GPIO_INT_POLARITY); | 127 | dwapb_write(gpio, GPIO_INT_POLARITY, v); |
85 | } | 128 | } |
86 | 129 | ||
87 | static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) | 130 | static u32 dwapb_do_irq(struct dwapb_gpio *gpio) |
88 | { | 131 | { |
89 | struct dwapb_gpio *gpio = irq_get_handler_data(irq); | ||
90 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
91 | u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS); | 132 | u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS); |
133 | u32 ret = irq_status; | ||
92 | 134 | ||
93 | while (irq_status) { | 135 | while (irq_status) { |
94 | int hwirq = fls(irq_status) - 1; | 136 | int hwirq = fls(irq_status) - 1; |
@@ -102,6 +144,16 @@ static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) | |||
102 | dwapb_toggle_trigger(gpio, hwirq); | 144 | dwapb_toggle_trigger(gpio, hwirq); |
103 | } | 145 | } |
104 | 146 | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) | ||
151 | { | ||
152 | struct dwapb_gpio *gpio = irq_get_handler_data(irq); | ||
153 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
154 | |||
155 | dwapb_do_irq(gpio); | ||
156 | |||
105 | if (chip->irq_eoi) | 157 | if (chip->irq_eoi) |
106 | chip->irq_eoi(irq_desc_get_irq_data(desc)); | 158 | chip->irq_eoi(irq_desc_get_irq_data(desc)); |
107 | } | 159 | } |
@@ -115,9 +167,9 @@ static void dwapb_irq_enable(struct irq_data *d) | |||
115 | u32 val; | 167 | u32 val; |
116 | 168 | ||
117 | spin_lock_irqsave(&bgc->lock, flags); | 169 | spin_lock_irqsave(&bgc->lock, flags); |
118 | val = readl(gpio->regs + GPIO_INTEN); | 170 | val = dwapb_read(gpio, GPIO_INTEN); |
119 | val |= BIT(d->hwirq); | 171 | val |= BIT(d->hwirq); |
120 | writel(val, gpio->regs + GPIO_INTEN); | 172 | dwapb_write(gpio, GPIO_INTEN, val); |
121 | spin_unlock_irqrestore(&bgc->lock, flags); | 173 | spin_unlock_irqrestore(&bgc->lock, flags); |
122 | } | 174 | } |
123 | 175 | ||
@@ -130,9 +182,9 @@ static void dwapb_irq_disable(struct irq_data *d) | |||
130 | u32 val; | 182 | u32 val; |
131 | 183 | ||
132 | spin_lock_irqsave(&bgc->lock, flags); | 184 | spin_lock_irqsave(&bgc->lock, flags); |
133 | val = readl(gpio->regs + GPIO_INTEN); | 185 | val = dwapb_read(gpio, GPIO_INTEN); |
134 | val &= ~BIT(d->hwirq); | 186 | val &= ~BIT(d->hwirq); |
135 | writel(val, gpio->regs + GPIO_INTEN); | 187 | dwapb_write(gpio, GPIO_INTEN, val); |
136 | spin_unlock_irqrestore(&bgc->lock, flags); | 188 | spin_unlock_irqrestore(&bgc->lock, flags); |
137 | } | 189 | } |
138 | 190 | ||
@@ -172,8 +224,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) | |||
172 | return -EINVAL; | 224 | return -EINVAL; |
173 | 225 | ||
174 | spin_lock_irqsave(&bgc->lock, flags); | 226 | spin_lock_irqsave(&bgc->lock, flags); |
175 | level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); | 227 | level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); |
176 | polarity = readl(gpio->regs + GPIO_INT_POLARITY); | 228 | polarity = dwapb_read(gpio, GPIO_INT_POLARITY); |
177 | 229 | ||
178 | switch (type) { | 230 | switch (type) { |
179 | case IRQ_TYPE_EDGE_BOTH: | 231 | case IRQ_TYPE_EDGE_BOTH: |
@@ -200,29 +252,55 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) | |||
200 | 252 | ||
201 | irq_setup_alt_chip(d, type); | 253 | irq_setup_alt_chip(d, type); |
202 | 254 | ||
203 | writel(level, gpio->regs + GPIO_INTTYPE_LEVEL); | 255 | dwapb_write(gpio, GPIO_INTTYPE_LEVEL, level); |
204 | writel(polarity, gpio->regs + GPIO_INT_POLARITY); | 256 | dwapb_write(gpio, GPIO_INT_POLARITY, polarity); |
257 | spin_unlock_irqrestore(&bgc->lock, flags); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int dwapb_gpio_set_debounce(struct gpio_chip *gc, | ||
263 | unsigned offset, unsigned debounce) | ||
264 | { | ||
265 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
266 | struct dwapb_gpio_port *port = to_dwapb_gpio_port(bgc); | ||
267 | struct dwapb_gpio *gpio = port->gpio; | ||
268 | unsigned long flags, val_deb; | ||
269 | unsigned long mask = bgc->pin2mask(bgc, offset); | ||
270 | |||
271 | spin_lock_irqsave(&bgc->lock, flags); | ||
272 | |||
273 | val_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); | ||
274 | if (debounce) | ||
275 | dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb | mask); | ||
276 | else | ||
277 | dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, val_deb & ~mask); | ||
278 | |||
205 | spin_unlock_irqrestore(&bgc->lock, flags); | 279 | spin_unlock_irqrestore(&bgc->lock, flags); |
206 | 280 | ||
207 | return 0; | 281 | return 0; |
208 | } | 282 | } |
209 | 283 | ||
284 | static irqreturn_t dwapb_irq_handler_mfd(int irq, void *dev_id) | ||
285 | { | ||
286 | u32 worked; | ||
287 | struct dwapb_gpio *gpio = dev_id; | ||
288 | |||
289 | worked = dwapb_do_irq(gpio); | ||
290 | |||
291 | return worked ? IRQ_HANDLED : IRQ_NONE; | ||
292 | } | ||
293 | |||
210 | static void dwapb_configure_irqs(struct dwapb_gpio *gpio, | 294 | static void dwapb_configure_irqs(struct dwapb_gpio *gpio, |
211 | struct dwapb_gpio_port *port) | 295 | struct dwapb_gpio_port *port, |
296 | struct dwapb_port_property *pp) | ||
212 | { | 297 | { |
213 | struct gpio_chip *gc = &port->bgc.gc; | 298 | struct gpio_chip *gc = &port->bgc.gc; |
214 | struct device_node *node = gc->of_node; | 299 | struct device_node *node = pp->node; |
215 | struct irq_chip_generic *irq_gc; | 300 | struct irq_chip_generic *irq_gc = NULL; |
216 | unsigned int hwirq, ngpio = gc->ngpio; | 301 | unsigned int hwirq, ngpio = gc->ngpio; |
217 | struct irq_chip_type *ct; | 302 | struct irq_chip_type *ct; |
218 | int err, irq, i; | 303 | int err, i; |
219 | |||
220 | irq = irq_of_parse_and_map(node, 0); | ||
221 | if (!irq) { | ||
222 | dev_warn(gpio->dev, "no irq for bank %s\n", | ||
223 | port->bgc.gc.of_node->full_name); | ||
224 | return; | ||
225 | } | ||
226 | 304 | ||
227 | gpio->domain = irq_domain_add_linear(node, ngpio, | 305 | gpio->domain = irq_domain_add_linear(node, ngpio, |
228 | &irq_generic_chip_ops, gpio); | 306 | &irq_generic_chip_ops, gpio); |
@@ -269,8 +347,24 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, | |||
269 | irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; | 347 | irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; |
270 | irq_gc->chip_types[1].handler = handle_edge_irq; | 348 | irq_gc->chip_types[1].handler = handle_edge_irq; |
271 | 349 | ||
272 | irq_set_chained_handler(irq, dwapb_irq_handler); | 350 | if (!pp->irq_shared) { |
273 | irq_set_handler_data(irq, gpio); | 351 | irq_set_chained_handler(pp->irq, dwapb_irq_handler); |
352 | irq_set_handler_data(pp->irq, gpio); | ||
353 | } else { | ||
354 | /* | ||
355 | * Request a shared IRQ since where MFD would have devices | ||
356 | * using the same irq pin | ||
357 | */ | ||
358 | err = devm_request_irq(gpio->dev, pp->irq, | ||
359 | dwapb_irq_handler_mfd, | ||
360 | IRQF_SHARED, "gpio-dwapb-mfd", gpio); | ||
361 | if (err) { | ||
362 | dev_err(gpio->dev, "error requesting IRQ\n"); | ||
363 | irq_domain_remove(gpio->domain); | ||
364 | gpio->domain = NULL; | ||
365 | return; | ||
366 | } | ||
367 | } | ||
274 | 368 | ||
275 | for (hwirq = 0 ; hwirq < ngpio ; hwirq++) | 369 | for (hwirq = 0 ; hwirq < ngpio ; hwirq++) |
276 | irq_create_mapping(gpio->domain, hwirq); | 370 | irq_create_mapping(gpio->domain, hwirq); |
@@ -296,57 +390,53 @@ static void dwapb_irq_teardown(struct dwapb_gpio *gpio) | |||
296 | } | 390 | } |
297 | 391 | ||
298 | static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, | 392 | static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, |
299 | struct device_node *port_np, | 393 | struct dwapb_port_property *pp, |
300 | unsigned int offs) | 394 | unsigned int offs) |
301 | { | 395 | { |
302 | struct dwapb_gpio_port *port; | 396 | struct dwapb_gpio_port *port; |
303 | u32 port_idx, ngpio; | ||
304 | void __iomem *dat, *set, *dirout; | 397 | void __iomem *dat, *set, *dirout; |
305 | int err; | 398 | int err; |
306 | 399 | ||
307 | if (of_property_read_u32(port_np, "reg", &port_idx) || | ||
308 | port_idx >= DWAPB_MAX_PORTS) { | ||
309 | dev_err(gpio->dev, "missing/invalid port index for %s\n", | ||
310 | port_np->full_name); | ||
311 | return -EINVAL; | ||
312 | } | ||
313 | |||
314 | port = &gpio->ports[offs]; | 400 | port = &gpio->ports[offs]; |
315 | port->gpio = gpio; | 401 | port->gpio = gpio; |
402 | port->idx = pp->idx; | ||
316 | 403 | ||
317 | if (of_property_read_u32(port_np, "snps,nr-gpios", &ngpio)) { | 404 | #ifdef CONFIG_PM_SLEEP |
318 | dev_info(gpio->dev, "failed to get number of gpios for %s\n", | 405 | port->ctx = devm_kzalloc(gpio->dev, sizeof(*port->ctx), GFP_KERNEL); |
319 | port_np->full_name); | 406 | if (!port->ctx) |
320 | ngpio = 32; | 407 | return -ENOMEM; |
321 | } | 408 | #endif |
322 | 409 | ||
323 | dat = gpio->regs + GPIO_EXT_PORTA + (port_idx * GPIO_EXT_PORT_SIZE); | 410 | dat = gpio->regs + GPIO_EXT_PORTA + (pp->idx * GPIO_EXT_PORT_SIZE); |
324 | set = gpio->regs + GPIO_SWPORTA_DR + (port_idx * GPIO_SWPORT_DR_SIZE); | 411 | set = gpio->regs + GPIO_SWPORTA_DR + (pp->idx * GPIO_SWPORT_DR_SIZE); |
325 | dirout = gpio->regs + GPIO_SWPORTA_DDR + | 412 | dirout = gpio->regs + GPIO_SWPORTA_DDR + |
326 | (port_idx * GPIO_SWPORT_DDR_SIZE); | 413 | (pp->idx * GPIO_SWPORT_DDR_SIZE); |
327 | 414 | ||
328 | err = bgpio_init(&port->bgc, gpio->dev, 4, dat, set, NULL, dirout, | 415 | err = bgpio_init(&port->bgc, gpio->dev, 4, dat, set, NULL, dirout, |
329 | NULL, false); | 416 | NULL, false); |
330 | if (err) { | 417 | if (err) { |
331 | dev_err(gpio->dev, "failed to init gpio chip for %s\n", | 418 | dev_err(gpio->dev, "failed to init gpio chip for %s\n", |
332 | port_np->full_name); | 419 | pp->name); |
333 | return err; | 420 | return err; |
334 | } | 421 | } |
335 | 422 | ||
336 | port->bgc.gc.ngpio = ngpio; | 423 | #ifdef CONFIG_OF_GPIO |
337 | port->bgc.gc.of_node = port_np; | 424 | port->bgc.gc.of_node = pp->node; |
425 | #endif | ||
426 | port->bgc.gc.ngpio = pp->ngpio; | ||
427 | port->bgc.gc.base = pp->gpio_base; | ||
338 | 428 | ||
339 | /* | 429 | /* Only port A support debounce */ |
340 | * Only port A can provide interrupts in all configurations of the IP. | 430 | if (pp->idx == 0) |
341 | */ | 431 | port->bgc.gc.set_debounce = dwapb_gpio_set_debounce; |
342 | if (port_idx == 0 && | 432 | |
343 | of_property_read_bool(port_np, "interrupt-controller")) | 433 | if (pp->irq) |
344 | dwapb_configure_irqs(gpio, port); | 434 | dwapb_configure_irqs(gpio, port, pp); |
345 | 435 | ||
346 | err = gpiochip_add(&port->bgc.gc); | 436 | err = gpiochip_add(&port->bgc.gc); |
347 | if (err) | 437 | if (err) |
348 | dev_err(gpio->dev, "failed to register gpiochip for %s\n", | 438 | dev_err(gpio->dev, "failed to register gpiochip for %s\n", |
349 | port_np->full_name); | 439 | pp->name); |
350 | else | 440 | else |
351 | port->is_registered = true; | 441 | port->is_registered = true; |
352 | 442 | ||
@@ -362,25 +452,116 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio) | |||
362 | gpiochip_remove(&gpio->ports[m].bgc.gc); | 452 | gpiochip_remove(&gpio->ports[m].bgc.gc); |
363 | } | 453 | } |
364 | 454 | ||
455 | static struct dwapb_platform_data * | ||
456 | dwapb_gpio_get_pdata_of(struct device *dev) | ||
457 | { | ||
458 | struct device_node *node, *port_np; | ||
459 | struct dwapb_platform_data *pdata; | ||
460 | struct dwapb_port_property *pp; | ||
461 | int nports; | ||
462 | int i; | ||
463 | |||
464 | node = dev->of_node; | ||
465 | if (!IS_ENABLED(CONFIG_OF_GPIO) || !node) | ||
466 | return ERR_PTR(-ENODEV); | ||
467 | |||
468 | nports = of_get_child_count(node); | ||
469 | if (nports == 0) | ||
470 | return ERR_PTR(-ENODEV); | ||
471 | |||
472 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
473 | if (!pdata) | ||
474 | return ERR_PTR(-ENOMEM); | ||
475 | |||
476 | pdata->properties = kcalloc(nports, sizeof(*pp), GFP_KERNEL); | ||
477 | if (!pdata->properties) { | ||
478 | kfree(pdata); | ||
479 | return ERR_PTR(-ENOMEM); | ||
480 | } | ||
481 | |||
482 | pdata->nports = nports; | ||
483 | |||
484 | i = 0; | ||
485 | for_each_child_of_node(node, port_np) { | ||
486 | pp = &pdata->properties[i++]; | ||
487 | pp->node = port_np; | ||
488 | |||
489 | if (of_property_read_u32(port_np, "reg", &pp->idx) || | ||
490 | pp->idx >= DWAPB_MAX_PORTS) { | ||
491 | dev_err(dev, "missing/invalid port index for %s\n", | ||
492 | port_np->full_name); | ||
493 | kfree(pdata->properties); | ||
494 | kfree(pdata); | ||
495 | return ERR_PTR(-EINVAL); | ||
496 | } | ||
497 | |||
498 | if (of_property_read_u32(port_np, "snps,nr-gpios", | ||
499 | &pp->ngpio)) { | ||
500 | dev_info(dev, "failed to get number of gpios for %s\n", | ||
501 | port_np->full_name); | ||
502 | pp->ngpio = 32; | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * Only port A can provide interrupts in all configurations of | ||
507 | * the IP. | ||
508 | */ | ||
509 | if (pp->idx == 0 && | ||
510 | of_property_read_bool(port_np, "interrupt-controller")) { | ||
511 | pp->irq = irq_of_parse_and_map(port_np, 0); | ||
512 | if (!pp->irq) { | ||
513 | dev_warn(dev, "no irq for bank %s\n", | ||
514 | port_np->full_name); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | pp->irq_shared = false; | ||
519 | pp->gpio_base = -1; | ||
520 | pp->name = port_np->full_name; | ||
521 | } | ||
522 | |||
523 | return pdata; | ||
524 | } | ||
525 | |||
526 | static inline void dwapb_free_pdata_of(struct dwapb_platform_data *pdata) | ||
527 | { | ||
528 | if (!IS_ENABLED(CONFIG_OF_GPIO) || !pdata) | ||
529 | return; | ||
530 | |||
531 | kfree(pdata->properties); | ||
532 | kfree(pdata); | ||
533 | } | ||
534 | |||
365 | static int dwapb_gpio_probe(struct platform_device *pdev) | 535 | static int dwapb_gpio_probe(struct platform_device *pdev) |
366 | { | 536 | { |
537 | unsigned int i; | ||
367 | struct resource *res; | 538 | struct resource *res; |
368 | struct dwapb_gpio *gpio; | 539 | struct dwapb_gpio *gpio; |
369 | struct device_node *np; | ||
370 | int err; | 540 | int err; |
371 | unsigned int offs = 0; | 541 | struct device *dev = &pdev->dev; |
542 | struct dwapb_platform_data *pdata = dev_get_platdata(dev); | ||
543 | bool is_pdata_alloc = !pdata; | ||
544 | |||
545 | if (is_pdata_alloc) { | ||
546 | pdata = dwapb_gpio_get_pdata_of(dev); | ||
547 | if (IS_ERR(pdata)) | ||
548 | return PTR_ERR(pdata); | ||
549 | } | ||
372 | 550 | ||
373 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | 551 | if (!pdata->nports) { |
374 | if (!gpio) | 552 | err = -ENODEV; |
375 | return -ENOMEM; | 553 | goto out_err; |
376 | gpio->dev = &pdev->dev; | 554 | } |
377 | 555 | ||
378 | gpio->nr_ports = of_get_child_count(pdev->dev.of_node); | 556 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); |
379 | if (!gpio->nr_ports) { | 557 | if (!gpio) { |
380 | err = -EINVAL; | 558 | err = -ENOMEM; |
381 | goto out_err; | 559 | goto out_err; |
382 | } | 560 | } |
383 | gpio->ports = devm_kzalloc(&pdev->dev, gpio->nr_ports * | 561 | gpio->dev = &pdev->dev; |
562 | gpio->nr_ports = pdata->nports; | ||
563 | |||
564 | gpio->ports = devm_kcalloc(&pdev->dev, gpio->nr_ports, | ||
384 | sizeof(*gpio->ports), GFP_KERNEL); | 565 | sizeof(*gpio->ports), GFP_KERNEL); |
385 | if (!gpio->ports) { | 566 | if (!gpio->ports) { |
386 | err = -ENOMEM; | 567 | err = -ENOMEM; |
@@ -394,20 +575,23 @@ static int dwapb_gpio_probe(struct platform_device *pdev) | |||
394 | goto out_err; | 575 | goto out_err; |
395 | } | 576 | } |
396 | 577 | ||
397 | for_each_child_of_node(pdev->dev.of_node, np) { | 578 | for (i = 0; i < gpio->nr_ports; i++) { |
398 | err = dwapb_gpio_add_port(gpio, np, offs++); | 579 | err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i); |
399 | if (err) | 580 | if (err) |
400 | goto out_unregister; | 581 | goto out_unregister; |
401 | } | 582 | } |
402 | platform_set_drvdata(pdev, gpio); | 583 | platform_set_drvdata(pdev, gpio); |
403 | 584 | ||
404 | return 0; | 585 | goto out_err; |
405 | 586 | ||
406 | out_unregister: | 587 | out_unregister: |
407 | dwapb_gpio_unregister(gpio); | 588 | dwapb_gpio_unregister(gpio); |
408 | dwapb_irq_teardown(gpio); | 589 | dwapb_irq_teardown(gpio); |
409 | 590 | ||
410 | out_err: | 591 | out_err: |
592 | if (is_pdata_alloc) | ||
593 | dwapb_free_pdata_of(pdata); | ||
594 | |||
411 | return err; | 595 | return err; |
412 | } | 596 | } |
413 | 597 | ||
@@ -427,10 +611,100 @@ static const struct of_device_id dwapb_of_match[] = { | |||
427 | }; | 611 | }; |
428 | MODULE_DEVICE_TABLE(of, dwapb_of_match); | 612 | MODULE_DEVICE_TABLE(of, dwapb_of_match); |
429 | 613 | ||
614 | #ifdef CONFIG_PM_SLEEP | ||
615 | static int dwapb_gpio_suspend(struct device *dev) | ||
616 | { | ||
617 | struct platform_device *pdev = to_platform_device(dev); | ||
618 | struct dwapb_gpio *gpio = platform_get_drvdata(pdev); | ||
619 | struct bgpio_chip *bgc = &gpio->ports[0].bgc; | ||
620 | unsigned long flags; | ||
621 | int i; | ||
622 | |||
623 | spin_lock_irqsave(&bgc->lock, flags); | ||
624 | for (i = 0; i < gpio->nr_ports; i++) { | ||
625 | unsigned int offset; | ||
626 | unsigned int idx = gpio->ports[i].idx; | ||
627 | struct dwapb_context *ctx = gpio->ports[i].ctx; | ||
628 | |||
629 | BUG_ON(!ctx); | ||
630 | |||
631 | offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; | ||
632 | ctx->dir = dwapb_read(gpio, offset); | ||
633 | |||
634 | offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; | ||
635 | ctx->data = dwapb_read(gpio, offset); | ||
636 | |||
637 | offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; | ||
638 | ctx->ext = dwapb_read(gpio, offset); | ||
639 | |||
640 | /* Only port A can provide interrupts */ | ||
641 | if (idx == 0) { | ||
642 | ctx->int_mask = dwapb_read(gpio, GPIO_INTMASK); | ||
643 | ctx->int_en = dwapb_read(gpio, GPIO_INTEN); | ||
644 | ctx->int_pol = dwapb_read(gpio, GPIO_INT_POLARITY); | ||
645 | ctx->int_type = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); | ||
646 | ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); | ||
647 | |||
648 | /* Mask out interrupts */ | ||
649 | dwapb_write(gpio, GPIO_INTMASK, 0xffffffff); | ||
650 | } | ||
651 | } | ||
652 | spin_unlock_irqrestore(&bgc->lock, flags); | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | static int dwapb_gpio_resume(struct device *dev) | ||
658 | { | ||
659 | struct platform_device *pdev = to_platform_device(dev); | ||
660 | struct dwapb_gpio *gpio = platform_get_drvdata(pdev); | ||
661 | struct bgpio_chip *bgc = &gpio->ports[0].bgc; | ||
662 | unsigned long flags; | ||
663 | int i; | ||
664 | |||
665 | spin_lock_irqsave(&bgc->lock, flags); | ||
666 | for (i = 0; i < gpio->nr_ports; i++) { | ||
667 | unsigned int offset; | ||
668 | unsigned int idx = gpio->ports[i].idx; | ||
669 | struct dwapb_context *ctx = gpio->ports[i].ctx; | ||
670 | |||
671 | BUG_ON(!ctx); | ||
672 | |||
673 | offset = GPIO_SWPORTA_DR + idx * GPIO_SWPORT_DR_SIZE; | ||
674 | dwapb_write(gpio, offset, ctx->data); | ||
675 | |||
676 | offset = GPIO_SWPORTA_DDR + idx * GPIO_SWPORT_DDR_SIZE; | ||
677 | dwapb_write(gpio, offset, ctx->dir); | ||
678 | |||
679 | offset = GPIO_EXT_PORTA + idx * GPIO_EXT_PORT_SIZE; | ||
680 | dwapb_write(gpio, offset, ctx->ext); | ||
681 | |||
682 | /* Only port A can provide interrupts */ | ||
683 | if (idx == 0) { | ||
684 | dwapb_write(gpio, GPIO_INTTYPE_LEVEL, ctx->int_type); | ||
685 | dwapb_write(gpio, GPIO_INT_POLARITY, ctx->int_pol); | ||
686 | dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, ctx->int_deb); | ||
687 | dwapb_write(gpio, GPIO_INTEN, ctx->int_en); | ||
688 | dwapb_write(gpio, GPIO_INTMASK, ctx->int_mask); | ||
689 | |||
690 | /* Clear out spurious interrupts */ | ||
691 | dwapb_write(gpio, GPIO_PORTA_EOI, 0xffffffff); | ||
692 | } | ||
693 | } | ||
694 | spin_unlock_irqrestore(&bgc->lock, flags); | ||
695 | |||
696 | return 0; | ||
697 | } | ||
698 | #endif | ||
699 | |||
700 | static SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops, dwapb_gpio_suspend, | ||
701 | dwapb_gpio_resume); | ||
702 | |||
430 | static struct platform_driver dwapb_gpio_driver = { | 703 | static struct platform_driver dwapb_gpio_driver = { |
431 | .driver = { | 704 | .driver = { |
432 | .name = "gpio-dwapb", | 705 | .name = "gpio-dwapb", |
433 | .owner = THIS_MODULE, | 706 | .owner = THIS_MODULE, |
707 | .pm = &dwapb_gpio_pm_ops, | ||
434 | .of_match_table = of_match_ptr(dwapb_of_match), | 708 | .of_match_table = of_match_ptr(dwapb_of_match), |
435 | }, | 709 | }, |
436 | .probe = dwapb_gpio_probe, | 710 | .probe = dwapb_gpio_probe, |
diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index 464a83de0d6a..cc09b237e88c 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c | |||
@@ -265,29 +265,27 @@ static int ks8695_gpio_show(struct seq_file *s, void *unused) | |||
265 | seq_printf(s, "EXT%i ", i); | 265 | seq_printf(s, "EXT%i ", i); |
266 | 266 | ||
267 | switch ((ctrl & intmask[i]) >> (4 * i)) { | 267 | switch ((ctrl & intmask[i]) >> (4 * i)) { |
268 | case IOPC_TM_LOW: | 268 | case IOPC_TM_LOW: |
269 | seq_printf(s, "(Low)"); break; | 269 | seq_printf(s, "(Low)"); break; |
270 | case IOPC_TM_HIGH: | 270 | case IOPC_TM_HIGH: |
271 | seq_printf(s, "(High)"); break; | 271 | seq_printf(s, "(High)"); break; |
272 | case IOPC_TM_RISING: | 272 | case IOPC_TM_RISING: |
273 | seq_printf(s, "(Rising)"); break; | 273 | seq_printf(s, "(Rising)"); break; |
274 | case IOPC_TM_FALLING: | 274 | case IOPC_TM_FALLING: |
275 | seq_printf(s, "(Falling)"); break; | 275 | seq_printf(s, "(Falling)"); break; |
276 | case IOPC_TM_EDGE: | 276 | case IOPC_TM_EDGE: |
277 | seq_printf(s, "(Edges)"); break; | 277 | seq_printf(s, "(Edges)"); break; |
278 | } | 278 | } |
279 | } | 279 | } else |
280 | else | ||
281 | seq_printf(s, "GPIO\t"); | 280 | seq_printf(s, "GPIO\t"); |
282 | } | 281 | } else if (i <= KS8695_GPIO_5) { |
283 | else if (i <= KS8695_GPIO_5) { | ||
284 | if (ctrl & enable[i]) | 282 | if (ctrl & enable[i]) |
285 | seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); | 283 | seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); |
286 | else | 284 | else |
287 | seq_printf(s, "GPIO\t"); | 285 | seq_printf(s, "GPIO\t"); |
288 | } | 286 | } else { |
289 | else | ||
290 | seq_printf(s, "GPIO\t"); | 287 | seq_printf(s, "GPIO\t"); |
288 | } | ||
291 | 289 | ||
292 | seq_printf(s, "\t"); | 290 | seq_printf(s, "\t"); |
293 | 291 | ||
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 6f183d9b487e..8488e2fd307c 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c | |||
@@ -479,7 +479,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) | |||
479 | 479 | ||
480 | mutex_init(&mcp->irq_lock); | 480 | mutex_init(&mcp->irq_lock); |
481 | 481 | ||
482 | mcp->irq_domain = irq_domain_add_linear(chip->of_node, chip->ngpio, | 482 | mcp->irq_domain = irq_domain_add_linear(chip->dev->of_node, chip->ngpio, |
483 | &irq_domain_simple_ops, mcp); | 483 | &irq_domain_simple_ops, mcp); |
484 | if (!mcp->irq_domain) | 484 | if (!mcp->irq_domain) |
485 | return -ENODEV; | 485 | return -ENODEV; |
@@ -581,7 +581,7 @@ done: | |||
581 | 581 | ||
582 | static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | 582 | static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, |
583 | void *data, unsigned addr, unsigned type, | 583 | void *data, unsigned addr, unsigned type, |
584 | unsigned base, unsigned pullups) | 584 | struct mcp23s08_platform_data *pdata, int cs) |
585 | { | 585 | { |
586 | int status; | 586 | int status; |
587 | bool mirror = false; | 587 | bool mirror = false; |
@@ -635,7 +635,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
635 | return -EINVAL; | 635 | return -EINVAL; |
636 | } | 636 | } |
637 | 637 | ||
638 | mcp->chip.base = base; | 638 | mcp->chip.base = pdata->base; |
639 | mcp->chip.can_sleep = true; | 639 | mcp->chip.can_sleep = true; |
640 | mcp->chip.dev = dev; | 640 | mcp->chip.dev = dev; |
641 | mcp->chip.owner = THIS_MODULE; | 641 | mcp->chip.owner = THIS_MODULE; |
@@ -648,11 +648,9 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
648 | if (status < 0) | 648 | if (status < 0) |
649 | goto fail; | 649 | goto fail; |
650 | 650 | ||
651 | mcp->irq_controller = of_property_read_bool(mcp->chip.of_node, | 651 | mcp->irq_controller = pdata->irq_controller; |
652 | "interrupt-controller"); | ||
653 | if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) | 652 | if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) |
654 | mirror = of_property_read_bool(mcp->chip.of_node, | 653 | mirror = pdata->mirror; |
655 | "microchip,irq-mirror"); | ||
656 | 654 | ||
657 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { | 655 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { |
658 | /* mcp23s17 has IOCON twice, make sure they are in sync */ | 656 | /* mcp23s17 has IOCON twice, make sure they are in sync */ |
@@ -668,7 +666,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
668 | } | 666 | } |
669 | 667 | ||
670 | /* configure ~100K pullups */ | 668 | /* configure ~100K pullups */ |
671 | status = mcp->ops->write(mcp, MCP_GPPU, pullups); | 669 | status = mcp->ops->write(mcp, MCP_GPPU, pdata->chip[cs].pullups); |
672 | if (status < 0) | 670 | if (status < 0) |
673 | goto fail; | 671 | goto fail; |
674 | 672 | ||
@@ -768,25 +766,29 @@ MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match); | |||
768 | static int mcp230xx_probe(struct i2c_client *client, | 766 | static int mcp230xx_probe(struct i2c_client *client, |
769 | const struct i2c_device_id *id) | 767 | const struct i2c_device_id *id) |
770 | { | 768 | { |
771 | struct mcp23s08_platform_data *pdata; | 769 | struct mcp23s08_platform_data *pdata, local_pdata; |
772 | struct mcp23s08 *mcp; | 770 | struct mcp23s08 *mcp; |
773 | int status, base, pullups; | 771 | int status; |
774 | const struct of_device_id *match; | 772 | const struct of_device_id *match; |
775 | 773 | ||
776 | match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match), | 774 | match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match), |
777 | &client->dev); | 775 | &client->dev); |
778 | pdata = dev_get_platdata(&client->dev); | 776 | if (match) { |
779 | if (match || !pdata) { | 777 | pdata = &local_pdata; |
780 | base = -1; | 778 | pdata->base = -1; |
781 | pullups = 0; | 779 | pdata->chip[0].pullups = 0; |
780 | pdata->irq_controller = of_property_read_bool( | ||
781 | client->dev.of_node, | ||
782 | "interrupt-controller"); | ||
783 | pdata->mirror = of_property_read_bool(client->dev.of_node, | ||
784 | "microchip,irq-mirror"); | ||
782 | client->irq = irq_of_parse_and_map(client->dev.of_node, 0); | 785 | client->irq = irq_of_parse_and_map(client->dev.of_node, 0); |
783 | } else { | 786 | } else { |
784 | if (!gpio_is_valid(pdata->base)) { | 787 | pdata = dev_get_platdata(&client->dev); |
788 | if (!pdata || !gpio_is_valid(pdata->base)) { | ||
785 | dev_dbg(&client->dev, "invalid platform data\n"); | 789 | dev_dbg(&client->dev, "invalid platform data\n"); |
786 | return -EINVAL; | 790 | return -EINVAL; |
787 | } | 791 | } |
788 | base = pdata->base; | ||
789 | pullups = pdata->chip[0].pullups; | ||
790 | } | 792 | } |
791 | 793 | ||
792 | mcp = kzalloc(sizeof(*mcp), GFP_KERNEL); | 794 | mcp = kzalloc(sizeof(*mcp), GFP_KERNEL); |
@@ -795,7 +797,7 @@ static int mcp230xx_probe(struct i2c_client *client, | |||
795 | 797 | ||
796 | mcp->irq = client->irq; | 798 | mcp->irq = client->irq; |
797 | status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, | 799 | status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr, |
798 | id->driver_data, base, pullups); | 800 | id->driver_data, pdata, 0); |
799 | if (status) | 801 | if (status) |
800 | goto fail; | 802 | goto fail; |
801 | 803 | ||
@@ -863,14 +865,12 @@ static void mcp23s08_i2c_exit(void) { } | |||
863 | 865 | ||
864 | static int mcp23s08_probe(struct spi_device *spi) | 866 | static int mcp23s08_probe(struct spi_device *spi) |
865 | { | 867 | { |
866 | struct mcp23s08_platform_data *pdata; | 868 | struct mcp23s08_platform_data *pdata, local_pdata; |
867 | unsigned addr; | 869 | unsigned addr; |
868 | int chips = 0; | 870 | int chips = 0; |
869 | struct mcp23s08_driver_data *data; | 871 | struct mcp23s08_driver_data *data; |
870 | int status, type; | 872 | int status, type; |
871 | unsigned base = -1, | 873 | unsigned ngpio = 0; |
872 | ngpio = 0, | ||
873 | pullups[ARRAY_SIZE(pdata->chip)]; | ||
874 | const struct of_device_id *match; | 874 | const struct of_device_id *match; |
875 | u32 spi_present_mask = 0; | 875 | u32 spi_present_mask = 0; |
876 | 876 | ||
@@ -893,11 +893,18 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
893 | return -ENODEV; | 893 | return -ENODEV; |
894 | } | 894 | } |
895 | 895 | ||
896 | pdata = &local_pdata; | ||
897 | pdata->base = -1; | ||
896 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { | 898 | for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) { |
897 | pullups[addr] = 0; | 899 | pdata->chip[addr].pullups = 0; |
898 | if (spi_present_mask & (1 << addr)) | 900 | if (spi_present_mask & (1 << addr)) |
899 | chips++; | 901 | chips++; |
900 | } | 902 | } |
903 | pdata->irq_controller = of_property_read_bool( | ||
904 | spi->dev.of_node, | ||
905 | "interrupt-controller"); | ||
906 | pdata->mirror = of_property_read_bool(spi->dev.of_node, | ||
907 | "microchip,irq-mirror"); | ||
901 | } else { | 908 | } else { |
902 | type = spi_get_device_id(spi)->driver_data; | 909 | type = spi_get_device_id(spi)->driver_data; |
903 | pdata = dev_get_platdata(&spi->dev); | 910 | pdata = dev_get_platdata(&spi->dev); |
@@ -917,10 +924,7 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
917 | return -EINVAL; | 924 | return -EINVAL; |
918 | } | 925 | } |
919 | spi_present_mask |= 1 << addr; | 926 | spi_present_mask |= 1 << addr; |
920 | pullups[addr] = pdata->chip[addr].pullups; | ||
921 | } | 927 | } |
922 | |||
923 | base = pdata->base; | ||
924 | } | 928 | } |
925 | 929 | ||
926 | if (!chips) | 930 | if (!chips) |
@@ -938,13 +942,13 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
938 | chips--; | 942 | chips--; |
939 | data->mcp[addr] = &data->chip[chips]; | 943 | data->mcp[addr] = &data->chip[chips]; |
940 | status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, | 944 | status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, |
941 | 0x40 | (addr << 1), type, base, | 945 | 0x40 | (addr << 1), type, pdata, |
942 | pullups[addr]); | 946 | addr); |
943 | if (status < 0) | 947 | if (status < 0) |
944 | goto fail; | 948 | goto fail; |
945 | 949 | ||
946 | if (base != -1) | 950 | if (pdata->base != -1) |
947 | base += (type == MCP_TYPE_S17) ? 16 : 8; | 951 | pdata->base += (type == MCP_TYPE_S17) ? 16 : 8; |
948 | ngpio += (type == MCP_TYPE_S17) ? 16 : 8; | 952 | ngpio += (type == MCP_TYPE_S17) ? 16 : 8; |
949 | } | 953 | } |
950 | data->ngpio = ngpio; | 954 | data->ngpio = ngpio; |
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 174932165fcb..415682f69214 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -857,16 +857,6 @@ static void omap_gpio_unmask_irq(struct irq_data *d) | |||
857 | spin_unlock_irqrestore(&bank->lock, flags); | 857 | spin_unlock_irqrestore(&bank->lock, flags); |
858 | } | 858 | } |
859 | 859 | ||
860 | static struct irq_chip gpio_irq_chip = { | ||
861 | .name = "GPIO", | ||
862 | .irq_shutdown = omap_gpio_irq_shutdown, | ||
863 | .irq_ack = omap_gpio_ack_irq, | ||
864 | .irq_mask = omap_gpio_mask_irq, | ||
865 | .irq_unmask = omap_gpio_unmask_irq, | ||
866 | .irq_set_type = omap_gpio_irq_type, | ||
867 | .irq_set_wake = omap_gpio_wake_enable, | ||
868 | }; | ||
869 | |||
870 | /*---------------------------------------------------------------------*/ | 860 | /*---------------------------------------------------------------------*/ |
871 | 861 | ||
872 | static int omap_mpuio_suspend_noirq(struct device *dev) | 862 | static int omap_mpuio_suspend_noirq(struct device *dev) |
@@ -1088,7 +1078,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start, | |||
1088 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | 1078 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); |
1089 | } | 1079 | } |
1090 | 1080 | ||
1091 | static int omap_gpio_chip_init(struct gpio_bank *bank) | 1081 | static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) |
1092 | { | 1082 | { |
1093 | int j; | 1083 | int j; |
1094 | static int gpio; | 1084 | static int gpio; |
@@ -1137,17 +1127,17 @@ static int omap_gpio_chip_init(struct gpio_bank *bank) | |||
1137 | } | 1127 | } |
1138 | #endif | 1128 | #endif |
1139 | 1129 | ||
1140 | ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip, | 1130 | ret = gpiochip_irqchip_add(&bank->chip, irqc, |
1141 | irq_base, omap_gpio_irq_handler, | 1131 | irq_base, omap_gpio_irq_handler, |
1142 | IRQ_TYPE_NONE); | 1132 | IRQ_TYPE_NONE); |
1143 | 1133 | ||
1144 | if (ret) { | 1134 | if (ret) { |
1145 | dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret); | 1135 | dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret); |
1146 | ret = gpiochip_remove(&bank->chip); | 1136 | gpiochip_remove(&bank->chip); |
1147 | return -ENODEV; | 1137 | return -ENODEV; |
1148 | } | 1138 | } |
1149 | 1139 | ||
1150 | gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip, | 1140 | gpiochip_set_chained_irqchip(&bank->chip, irqc, |
1151 | bank->irq, omap_gpio_irq_handler); | 1141 | bank->irq, omap_gpio_irq_handler); |
1152 | 1142 | ||
1153 | for (j = 0; j < bank->width; j++) { | 1143 | for (j = 0; j < bank->width; j++) { |
@@ -1172,6 +1162,7 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
1172 | const struct omap_gpio_platform_data *pdata; | 1162 | const struct omap_gpio_platform_data *pdata; |
1173 | struct resource *res; | 1163 | struct resource *res; |
1174 | struct gpio_bank *bank; | 1164 | struct gpio_bank *bank; |
1165 | struct irq_chip *irqc; | ||
1175 | int ret; | 1166 | int ret; |
1176 | 1167 | ||
1177 | match = of_match_device(of_match_ptr(omap_gpio_match), dev); | 1168 | match = of_match_device(of_match_ptr(omap_gpio_match), dev); |
@@ -1186,6 +1177,18 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
1186 | return -ENOMEM; | 1177 | return -ENOMEM; |
1187 | } | 1178 | } |
1188 | 1179 | ||
1180 | irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); | ||
1181 | if (!irqc) | ||
1182 | return -ENOMEM; | ||
1183 | |||
1184 | irqc->irq_shutdown = omap_gpio_irq_shutdown, | ||
1185 | irqc->irq_ack = omap_gpio_ack_irq, | ||
1186 | irqc->irq_mask = omap_gpio_mask_irq, | ||
1187 | irqc->irq_unmask = omap_gpio_unmask_irq, | ||
1188 | irqc->irq_set_type = omap_gpio_irq_type, | ||
1189 | irqc->irq_set_wake = omap_gpio_wake_enable, | ||
1190 | irqc->name = dev_name(&pdev->dev); | ||
1191 | |||
1189 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 1192 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
1190 | if (unlikely(!res)) { | 1193 | if (unlikely(!res)) { |
1191 | dev_err(dev, "Invalid IRQ resource\n"); | 1194 | dev_err(dev, "Invalid IRQ resource\n"); |
@@ -1241,7 +1244,7 @@ static int omap_gpio_probe(struct platform_device *pdev) | |||
1241 | 1244 | ||
1242 | omap_gpio_mod_init(bank); | 1245 | omap_gpio_mod_init(bank); |
1243 | 1246 | ||
1244 | ret = omap_gpio_chip_init(bank); | 1247 | ret = omap_gpio_chip_init(bank, irqc); |
1245 | if (ret) | 1248 | if (ret) |
1246 | return ret; | 1249 | return ret; |
1247 | 1250 | ||
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index f9961eea2120..e2da64abbccd 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
@@ -520,7 +520,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
520 | struct i2c_client *client = chip->client; | 520 | struct i2c_client *client = chip->client; |
521 | int ret, i, offset = 0; | 521 | int ret, i, offset = 0; |
522 | 522 | ||
523 | if (irq_base != -1 | 523 | if (client->irq && irq_base != -1 |
524 | && (id->driver_data & PCA_INT)) { | 524 | && (id->driver_data & PCA_INT)) { |
525 | 525 | ||
526 | switch (chip->chip_type) { | 526 | switch (chip->chip_type) { |
@@ -586,50 +586,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
586 | } | 586 | } |
587 | #endif | 587 | #endif |
588 | 588 | ||
589 | /* | ||
590 | * Handlers for alternative sources of platform_data | ||
591 | */ | ||
592 | #ifdef CONFIG_OF_GPIO | ||
593 | /* | ||
594 | * Translate OpenFirmware node properties into platform_data | ||
595 | * WARNING: This is DEPRECATED and will be removed eventually! | ||
596 | */ | ||
597 | static void | ||
598 | pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) | ||
599 | { | ||
600 | struct device_node *node; | ||
601 | const __be32 *val; | ||
602 | int size; | ||
603 | |||
604 | *gpio_base = -1; | ||
605 | |||
606 | node = client->dev.of_node; | ||
607 | if (node == NULL) | ||
608 | return; | ||
609 | |||
610 | val = of_get_property(node, "linux,gpio-base", &size); | ||
611 | WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__); | ||
612 | if (val) { | ||
613 | if (size != sizeof(*val)) | ||
614 | dev_warn(&client->dev, "%s: wrong linux,gpio-base\n", | ||
615 | node->full_name); | ||
616 | else | ||
617 | *gpio_base = be32_to_cpup(val); | ||
618 | } | ||
619 | |||
620 | val = of_get_property(node, "polarity", NULL); | ||
621 | WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__); | ||
622 | if (val) | ||
623 | *invert = *val; | ||
624 | } | ||
625 | #else | ||
626 | static void | ||
627 | pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert) | ||
628 | { | ||
629 | *gpio_base = -1; | ||
630 | } | ||
631 | #endif | ||
632 | |||
633 | static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) | 589 | static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) |
634 | { | 590 | { |
635 | int ret; | 591 | int ret; |
@@ -704,12 +660,8 @@ static int pca953x_probe(struct i2c_client *client, | |||
704 | invert = pdata->invert; | 660 | invert = pdata->invert; |
705 | chip->names = pdata->names; | 661 | chip->names = pdata->names; |
706 | } else { | 662 | } else { |
707 | pca953x_get_alt_pdata(client, &chip->gpio_start, &invert); | 663 | chip->gpio_start = -1; |
708 | #ifdef CONFIG_OF_GPIO | 664 | irq_base = 0; |
709 | /* If I2C node has no interrupts property, disable GPIO interrupts */ | ||
710 | if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL) | ||
711 | irq_base = -1; | ||
712 | #endif | ||
713 | } | 665 | } |
714 | 666 | ||
715 | chip->client = client; | 667 | chip->client = client; |
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index e0ac549dccb5..2d9a950ca2d4 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c | |||
@@ -171,6 +171,7 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | #ifdef CONFIG_PM | ||
174 | /* | 175 | /* |
175 | * Save register configuration and disable interrupts. | 176 | * Save register configuration and disable interrupts. |
176 | */ | 177 | */ |
@@ -206,6 +207,7 @@ static void pch_gpio_restore_reg_conf(struct pch_gpio *chip) | |||
206 | iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, | 207 | iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, |
207 | &chip->reg->gpio_use_sel); | 208 | &chip->reg->gpio_use_sel); |
208 | } | 209 | } |
210 | #endif | ||
209 | 211 | ||
210 | static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) | 212 | static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) |
211 | { | 213 | { |
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 3810da47043f..7c288ba4dc87 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
@@ -1309,56 +1309,6 @@ samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin) | |||
1309 | } | 1309 | } |
1310 | EXPORT_SYMBOL(s3c_gpio_getpull); | 1310 | EXPORT_SYMBOL(s3c_gpio_getpull); |
1311 | 1311 | ||
1312 | #ifdef CONFIG_S5P_GPIO_DRVSTR | ||
1313 | s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) | ||
1314 | { | ||
1315 | struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); | ||
1316 | unsigned int off; | ||
1317 | void __iomem *reg; | ||
1318 | int shift; | ||
1319 | u32 drvstr; | ||
1320 | |||
1321 | if (!chip) | ||
1322 | return -EINVAL; | ||
1323 | |||
1324 | off = pin - chip->chip.base; | ||
1325 | shift = off * 2; | ||
1326 | reg = chip->base + 0x0C; | ||
1327 | |||
1328 | drvstr = __raw_readl(reg); | ||
1329 | drvstr = drvstr >> shift; | ||
1330 | drvstr &= 0x3; | ||
1331 | |||
1332 | return (__force s5p_gpio_drvstr_t)drvstr; | ||
1333 | } | ||
1334 | EXPORT_SYMBOL(s5p_gpio_get_drvstr); | ||
1335 | |||
1336 | int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) | ||
1337 | { | ||
1338 | struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin); | ||
1339 | unsigned int off; | ||
1340 | void __iomem *reg; | ||
1341 | int shift; | ||
1342 | u32 tmp; | ||
1343 | |||
1344 | if (!chip) | ||
1345 | return -EINVAL; | ||
1346 | |||
1347 | off = pin - chip->chip.base; | ||
1348 | shift = off * 2; | ||
1349 | reg = chip->base + 0x0C; | ||
1350 | |||
1351 | tmp = __raw_readl(reg); | ||
1352 | tmp &= ~(0x3 << shift); | ||
1353 | tmp |= drvstr << shift; | ||
1354 | |||
1355 | __raw_writel(tmp, reg); | ||
1356 | |||
1357 | return 0; | ||
1358 | } | ||
1359 | EXPORT_SYMBOL(s5p_gpio_set_drvstr); | ||
1360 | #endif /* CONFIG_S5P_GPIO_DRVSTR */ | ||
1361 | |||
1362 | #ifdef CONFIG_PLAT_S3C24XX | 1312 | #ifdef CONFIG_PLAT_S3C24XX |
1363 | unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) | 1313 | unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) |
1364 | { | 1314 | { |
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 845025a57240..85c5b1974294 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/mfd/stmpe.h> | 15 | #include <linux/mfd/stmpe.h> |
16 | #include <linux/seq_file.h> | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * These registers are modified under the irq bus lock and cached to avoid | 19 | * These registers are modified under the irq bus lock and cached to avoid |
@@ -127,19 +128,19 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
127 | int regoffset = offset / 8; | 128 | int regoffset = offset / 8; |
128 | int mask = 1 << (offset % 8); | 129 | int mask = 1 << (offset % 8); |
129 | 130 | ||
130 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | 131 | if (type & IRQ_TYPE_LEVEL_LOW || type & IRQ_TYPE_LEVEL_HIGH) |
131 | return -EINVAL; | 132 | return -EINVAL; |
132 | 133 | ||
133 | /* STMPE801 doesn't have RE and FE registers */ | 134 | /* STMPE801 doesn't have RE and FE registers */ |
134 | if (stmpe_gpio->stmpe->partnum == STMPE801) | 135 | if (stmpe_gpio->stmpe->partnum == STMPE801) |
135 | return 0; | 136 | return 0; |
136 | 137 | ||
137 | if (type == IRQ_TYPE_EDGE_RISING) | 138 | if (type & IRQ_TYPE_EDGE_RISING) |
138 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; | 139 | stmpe_gpio->regs[REG_RE][regoffset] |= mask; |
139 | else | 140 | else |
140 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; | 141 | stmpe_gpio->regs[REG_RE][regoffset] &= ~mask; |
141 | 142 | ||
142 | if (type == IRQ_TYPE_EDGE_FALLING) | 143 | if (type & IRQ_TYPE_EDGE_FALLING) |
143 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; | 144 | stmpe_gpio->regs[REG_FE][regoffset] |= mask; |
144 | else | 145 | else |
145 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; | 146 | stmpe_gpio->regs[REG_FE][regoffset] &= ~mask; |
@@ -211,6 +212,77 @@ static void stmpe_gpio_irq_unmask(struct irq_data *d) | |||
211 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; | 212 | stmpe_gpio->regs[REG_IE][regoffset] |= mask; |
212 | } | 213 | } |
213 | 214 | ||
215 | static void stmpe_dbg_show_one(struct seq_file *s, | ||
216 | struct gpio_chip *gc, | ||
217 | unsigned offset, unsigned gpio) | ||
218 | { | ||
219 | struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc); | ||
220 | struct stmpe *stmpe = stmpe_gpio->stmpe; | ||
221 | const char *label = gpiochip_is_requested(gc, offset); | ||
222 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | ||
223 | bool val = !!stmpe_gpio_get(gc, offset); | ||
224 | u8 dir_reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8); | ||
225 | u8 mask = 1 << (offset % 8); | ||
226 | int ret; | ||
227 | u8 dir; | ||
228 | |||
229 | ret = stmpe_reg_read(stmpe, dir_reg); | ||
230 | if (ret < 0) | ||
231 | return; | ||
232 | dir = !!(ret & mask); | ||
233 | |||
234 | if (dir) { | ||
235 | seq_printf(s, " gpio-%-3d (%-20.20s) out %s", | ||
236 | gpio, label ?: "(none)", | ||
237 | val ? "hi" : "lo"); | ||
238 | } else { | ||
239 | u8 edge_det_reg = stmpe->regs[STMPE_IDX_GPEDR_MSB] + num_banks - 1 - (offset / 8); | ||
240 | u8 rise_reg = stmpe->regs[STMPE_IDX_GPRER_LSB] - (offset / 8); | ||
241 | u8 fall_reg = stmpe->regs[STMPE_IDX_GPFER_LSB] - (offset / 8); | ||
242 | u8 irqen_reg = stmpe->regs[STMPE_IDX_IEGPIOR_LSB] - (offset / 8); | ||
243 | bool edge_det; | ||
244 | bool rise; | ||
245 | bool fall; | ||
246 | bool irqen; | ||
247 | |||
248 | ret = stmpe_reg_read(stmpe, edge_det_reg); | ||
249 | if (ret < 0) | ||
250 | return; | ||
251 | edge_det = !!(ret & mask); | ||
252 | ret = stmpe_reg_read(stmpe, rise_reg); | ||
253 | if (ret < 0) | ||
254 | return; | ||
255 | rise = !!(ret & mask); | ||
256 | ret = stmpe_reg_read(stmpe, fall_reg); | ||
257 | if (ret < 0) | ||
258 | return; | ||
259 | fall = !!(ret & mask); | ||
260 | ret = stmpe_reg_read(stmpe, irqen_reg); | ||
261 | if (ret < 0) | ||
262 | return; | ||
263 | irqen = !!(ret & mask); | ||
264 | |||
265 | seq_printf(s, " gpio-%-3d (%-20.20s) in %s %s %s%s%s", | ||
266 | gpio, label ?: "(none)", | ||
267 | val ? "hi" : "lo", | ||
268 | edge_det ? "edge-asserted" : "edge-inactive", | ||
269 | irqen ? "IRQ-enabled" : "", | ||
270 | rise ? " rising-edge-detection" : "", | ||
271 | fall ? " falling-edge-detection" : ""); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | static void stmpe_dbg_show(struct seq_file *s, struct gpio_chip *gc) | ||
276 | { | ||
277 | unsigned i; | ||
278 | unsigned gpio = gc->base; | ||
279 | |||
280 | for (i = 0; i < gc->ngpio; i++, gpio++) { | ||
281 | stmpe_dbg_show_one(s, gc, i, gpio); | ||
282 | seq_printf(s, "\n"); | ||
283 | } | ||
284 | } | ||
285 | |||
214 | static struct irq_chip stmpe_gpio_irq_chip = { | 286 | static struct irq_chip stmpe_gpio_irq_chip = { |
215 | .name = "stmpe-gpio", | 287 | .name = "stmpe-gpio", |
216 | .irq_bus_lock = stmpe_gpio_irq_lock, | 288 | .irq_bus_lock = stmpe_gpio_irq_lock, |
@@ -293,6 +365,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||
293 | #endif | 365 | #endif |
294 | stmpe_gpio->chip.base = -1; | 366 | stmpe_gpio->chip.base = -1; |
295 | 367 | ||
368 | if (IS_ENABLED(CONFIG_DEBUG_FS)) | ||
369 | stmpe_gpio->chip.dbg_show = stmpe_dbg_show; | ||
370 | |||
296 | if (pdata) | 371 | if (pdata) |
297 | stmpe_gpio->norequest_mask = pdata->norequest_mask; | 372 | stmpe_gpio->norequest_mask = pdata->norequest_mask; |
298 | else if (np) | 373 | else if (np) |
@@ -308,6 +383,12 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||
308 | if (ret) | 383 | if (ret) |
309 | goto out_free; | 384 | goto out_free; |
310 | 385 | ||
386 | ret = gpiochip_add(&stmpe_gpio->chip); | ||
387 | if (ret) { | ||
388 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
389 | goto out_disable; | ||
390 | } | ||
391 | |||
311 | if (irq > 0) { | 392 | if (irq > 0) { |
312 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 393 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
313 | stmpe_gpio_irq, IRQF_ONESHOT, | 394 | stmpe_gpio_irq, IRQF_ONESHOT, |
@@ -324,14 +405,13 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||
324 | if (ret) { | 405 | if (ret) { |
325 | dev_err(&pdev->dev, | 406 | dev_err(&pdev->dev, |
326 | "could not connect irqchip to gpiochip\n"); | 407 | "could not connect irqchip to gpiochip\n"); |
327 | return ret; | 408 | goto out_disable; |
328 | } | 409 | } |
329 | } | ||
330 | 410 | ||
331 | ret = gpiochip_add(&stmpe_gpio->chip); | 411 | gpiochip_set_chained_irqchip(&stmpe_gpio->chip, |
332 | if (ret) { | 412 | &stmpe_gpio_irq_chip, |
333 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | 413 | irq, |
334 | goto out_disable; | 414 | NULL); |
335 | } | 415 | } |
336 | 416 | ||
337 | if (pdata && pdata->setup) | 417 | if (pdata && pdata->setup) |
@@ -343,6 +423,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) | |||
343 | 423 | ||
344 | out_disable: | 424 | out_disable: |
345 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); | 425 | stmpe_disable(stmpe, STMPE_BLOCK_GPIO); |
426 | gpiochip_remove(&stmpe_gpio->chip); | ||
346 | out_free: | 427 | out_free: |
347 | kfree(stmpe_gpio); | 428 | kfree(stmpe_gpio); |
348 | return ret; | 429 | return ret; |
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 04882a911b65..7e359b7cce1b 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c | |||
@@ -292,7 +292,7 @@ static struct platform_driver xway_stp_driver = { | |||
292 | }, | 292 | }, |
293 | }; | 293 | }; |
294 | 294 | ||
295 | int __init xway_stp_init(void) | 295 | static int __init xway_stp_init(void) |
296 | { | 296 | { |
297 | return platform_driver_register(&xway_stp_driver); | 297 | return platform_driver_register(&xway_stp_driver); |
298 | } | 298 | } |
diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 30884fbc750d..e82fde4b6898 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c | |||
@@ -37,6 +37,8 @@ | |||
37 | * dat_bit_offset: Offset (in bits) to the first GPIO bit. | 37 | * dat_bit_offset: Offset (in bits) to the first GPIO bit. |
38 | * dir_bit_offset: Optional offset (in bits) to the first bit to switch | 38 | * dir_bit_offset: Optional offset (in bits) to the first bit to switch |
39 | * GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag). | 39 | * GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag). |
40 | * set: HW specific callback to assigns output value | ||
41 | * for signal "offset" | ||
40 | */ | 42 | */ |
41 | 43 | ||
42 | struct syscon_gpio_data { | 44 | struct syscon_gpio_data { |
@@ -45,12 +47,16 @@ struct syscon_gpio_data { | |||
45 | unsigned int bit_count; | 47 | unsigned int bit_count; |
46 | unsigned int dat_bit_offset; | 48 | unsigned int dat_bit_offset; |
47 | unsigned int dir_bit_offset; | 49 | unsigned int dir_bit_offset; |
50 | void (*set)(struct gpio_chip *chip, | ||
51 | unsigned offset, int value); | ||
48 | }; | 52 | }; |
49 | 53 | ||
50 | struct syscon_gpio_priv { | 54 | struct syscon_gpio_priv { |
51 | struct gpio_chip chip; | 55 | struct gpio_chip chip; |
52 | struct regmap *syscon; | 56 | struct regmap *syscon; |
53 | const struct syscon_gpio_data *data; | 57 | const struct syscon_gpio_data *data; |
58 | u32 dreg_offset; | ||
59 | u32 dir_reg_offset; | ||
54 | }; | 60 | }; |
55 | 61 | ||
56 | static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) | 62 | static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) |
@@ -61,9 +67,11 @@ static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) | |||
61 | static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) | 67 | static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) |
62 | { | 68 | { |
63 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); | 69 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
64 | unsigned int val, offs = priv->data->dat_bit_offset + offset; | 70 | unsigned int val, offs; |
65 | int ret; | 71 | int ret; |
66 | 72 | ||
73 | offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; | ||
74 | |||
67 | ret = regmap_read(priv->syscon, | 75 | ret = regmap_read(priv->syscon, |
68 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, &val); | 76 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, &val); |
69 | if (ret) | 77 | if (ret) |
@@ -75,7 +83,9 @@ static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) | |||
75 | static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | 83 | static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val) |
76 | { | 84 | { |
77 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); | 85 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
78 | unsigned int offs = priv->data->dat_bit_offset + offset; | 86 | unsigned int offs; |
87 | |||
88 | offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; | ||
79 | 89 | ||
80 | regmap_update_bits(priv->syscon, | 90 | regmap_update_bits(priv->syscon, |
81 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, | 91 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, |
@@ -88,7 +98,10 @@ static int syscon_gpio_dir_in(struct gpio_chip *chip, unsigned offset) | |||
88 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); | 98 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
89 | 99 | ||
90 | if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { | 100 | if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { |
91 | unsigned int offs = priv->data->dir_bit_offset + offset; | 101 | unsigned int offs; |
102 | |||
103 | offs = priv->dir_reg_offset + | ||
104 | priv->data->dir_bit_offset + offset; | ||
92 | 105 | ||
93 | regmap_update_bits(priv->syscon, | 106 | regmap_update_bits(priv->syscon, |
94 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, | 107 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, |
@@ -103,7 +116,10 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) | |||
103 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); | 116 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); |
104 | 117 | ||
105 | if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { | 118 | if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { |
106 | unsigned int offs = priv->data->dir_bit_offset + offset; | 119 | unsigned int offs; |
120 | |||
121 | offs = priv->dir_reg_offset + | ||
122 | priv->data->dir_bit_offset + offset; | ||
107 | 123 | ||
108 | regmap_update_bits(priv->syscon, | 124 | regmap_update_bits(priv->syscon, |
109 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, | 125 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, |
@@ -111,7 +127,7 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) | |||
111 | BIT(offs % SYSCON_REG_BITS)); | 127 | BIT(offs % SYSCON_REG_BITS)); |
112 | } | 128 | } |
113 | 129 | ||
114 | syscon_gpio_set(chip, offset, val); | 130 | priv->data->set(chip, offset, val); |
115 | 131 | ||
116 | return 0; | 132 | return 0; |
117 | } | 133 | } |
@@ -124,11 +140,46 @@ static const struct syscon_gpio_data clps711x_mctrl_gpio = { | |||
124 | .dat_bit_offset = 0x40 * 8 + 8, | 140 | .dat_bit_offset = 0x40 * 8 + 8, |
125 | }; | 141 | }; |
126 | 142 | ||
143 | #define KEYSTONE_LOCK_BIT BIT(0) | ||
144 | |||
145 | static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
146 | { | ||
147 | struct syscon_gpio_priv *priv = to_syscon_gpio(chip); | ||
148 | unsigned int offs; | ||
149 | int ret; | ||
150 | |||
151 | offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; | ||
152 | |||
153 | if (!val) | ||
154 | return; | ||
155 | |||
156 | ret = regmap_update_bits( | ||
157 | priv->syscon, | ||
158 | (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, | ||
159 | BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT, | ||
160 | BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT); | ||
161 | if (ret < 0) | ||
162 | dev_err(chip->dev, "gpio write failed ret(%d)\n", ret); | ||
163 | } | ||
164 | |||
165 | static const struct syscon_gpio_data keystone_dsp_gpio = { | ||
166 | /* ARM Keystone 2 */ | ||
167 | .compatible = NULL, | ||
168 | .flags = GPIO_SYSCON_FEAT_OUT, | ||
169 | .bit_count = 28, | ||
170 | .dat_bit_offset = 4, | ||
171 | .set = keystone_gpio_set, | ||
172 | }; | ||
173 | |||
127 | static const struct of_device_id syscon_gpio_ids[] = { | 174 | static const struct of_device_id syscon_gpio_ids[] = { |
128 | { | 175 | { |
129 | .compatible = "cirrus,clps711x-mctrl-gpio", | 176 | .compatible = "cirrus,clps711x-mctrl-gpio", |
130 | .data = &clps711x_mctrl_gpio, | 177 | .data = &clps711x_mctrl_gpio, |
131 | }, | 178 | }, |
179 | { | ||
180 | .compatible = "ti,keystone-dsp-gpio", | ||
181 | .data = &keystone_dsp_gpio, | ||
182 | }, | ||
132 | { } | 183 | { } |
133 | }; | 184 | }; |
134 | MODULE_DEVICE_TABLE(of, syscon_gpio_ids); | 185 | MODULE_DEVICE_TABLE(of, syscon_gpio_ids); |
@@ -138,6 +189,8 @@ static int syscon_gpio_probe(struct platform_device *pdev) | |||
138 | struct device *dev = &pdev->dev; | 189 | struct device *dev = &pdev->dev; |
139 | const struct of_device_id *of_id = of_match_device(syscon_gpio_ids, dev); | 190 | const struct of_device_id *of_id = of_match_device(syscon_gpio_ids, dev); |
140 | struct syscon_gpio_priv *priv; | 191 | struct syscon_gpio_priv *priv; |
192 | struct device_node *np = dev->of_node; | ||
193 | int ret; | ||
141 | 194 | ||
142 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | 195 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
143 | if (!priv) | 196 | if (!priv) |
@@ -145,10 +198,31 @@ static int syscon_gpio_probe(struct platform_device *pdev) | |||
145 | 198 | ||
146 | priv->data = of_id->data; | 199 | priv->data = of_id->data; |
147 | 200 | ||
148 | priv->syscon = | 201 | if (priv->data->compatible) { |
149 | syscon_regmap_lookup_by_compatible(priv->data->compatible); | 202 | priv->syscon = syscon_regmap_lookup_by_compatible( |
150 | if (IS_ERR(priv->syscon)) | 203 | priv->data->compatible); |
151 | return PTR_ERR(priv->syscon); | 204 | if (IS_ERR(priv->syscon)) |
205 | return PTR_ERR(priv->syscon); | ||
206 | } else { | ||
207 | priv->syscon = | ||
208 | syscon_regmap_lookup_by_phandle(np, "gpio,syscon-dev"); | ||
209 | if (IS_ERR(priv->syscon)) | ||
210 | return PTR_ERR(priv->syscon); | ||
211 | |||
212 | ret = of_property_read_u32_index(np, "gpio,syscon-dev", 1, | ||
213 | &priv->dreg_offset); | ||
214 | if (ret) | ||
215 | dev_err(dev, "can't read the data register offset!\n"); | ||
216 | |||
217 | priv->dreg_offset <<= 3; | ||
218 | |||
219 | ret = of_property_read_u32_index(np, "gpio,syscon-dev", 2, | ||
220 | &priv->dir_reg_offset); | ||
221 | if (ret) | ||
222 | dev_err(dev, "can't read the dir register offset!\n"); | ||
223 | |||
224 | priv->dir_reg_offset <<= 3; | ||
225 | } | ||
152 | 226 | ||
153 | priv->chip.dev = dev; | 227 | priv->chip.dev = dev; |
154 | priv->chip.owner = THIS_MODULE; | 228 | priv->chip.owner = THIS_MODULE; |
@@ -159,7 +233,7 @@ static int syscon_gpio_probe(struct platform_device *pdev) | |||
159 | if (priv->data->flags & GPIO_SYSCON_FEAT_IN) | 233 | if (priv->data->flags & GPIO_SYSCON_FEAT_IN) |
160 | priv->chip.direction_input = syscon_gpio_dir_in; | 234 | priv->chip.direction_input = syscon_gpio_dir_in; |
161 | if (priv->data->flags & GPIO_SYSCON_FEAT_OUT) { | 235 | if (priv->data->flags & GPIO_SYSCON_FEAT_OUT) { |
162 | priv->chip.set = syscon_gpio_set; | 236 | priv->chip.set = priv->data->set ? : syscon_gpio_set; |
163 | priv->chip.direction_output = syscon_gpio_dir_out; | 237 | priv->chip.direction_output = syscon_gpio_dir_out; |
164 | } | 238 | } |
165 | 239 | ||
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 7324869c38e0..ae0f6466eb09 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c | |||
@@ -300,6 +300,11 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) | |||
300 | return ret; | 300 | return ret; |
301 | } | 301 | } |
302 | 302 | ||
303 | gpiochip_set_chained_irqchip(&tc3589x_gpio->chip, | ||
304 | &tc3589x_gpio_irq_chip, | ||
305 | irq, | ||
306 | NULL); | ||
307 | |||
303 | if (pdata && pdata->setup) | 308 | if (pdata && pdata->setup) |
304 | pdata->setup(tc3589x, tc3589x_gpio->chip.base); | 309 | pdata->setup(tc3589x, tc3589x_gpio->chip.base); |
305 | 310 | ||
diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c new file mode 100644 index 000000000000..7d489221dc1f --- /dev/null +++ b/drivers/gpio/gpio-xgene.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * AppliedMicro X-Gene SoC GPIO Driver | ||
3 | * | ||
4 | * Copyright (c) 2014, Applied Micro Circuits Corporation | ||
5 | * Author: Feng Kan <fkan@apm.com>. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/gpio/driver.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/bitops.h> | ||
29 | |||
30 | #define GPIO_SET_DR_OFFSET 0x0C | ||
31 | #define GPIO_DATA_OFFSET 0x14 | ||
32 | #define GPIO_BANK_STRIDE 0x0C | ||
33 | |||
34 | #define XGENE_GPIOS_PER_BANK 16 | ||
35 | #define XGENE_MAX_GPIO_BANKS 3 | ||
36 | #define XGENE_MAX_GPIOS (XGENE_GPIOS_PER_BANK * XGENE_MAX_GPIO_BANKS) | ||
37 | |||
38 | #define GPIO_BIT_OFFSET(x) (x % XGENE_GPIOS_PER_BANK) | ||
39 | #define GPIO_BANK_OFFSET(x) ((x / XGENE_GPIOS_PER_BANK) * GPIO_BANK_STRIDE) | ||
40 | |||
41 | struct xgene_gpio { | ||
42 | struct gpio_chip chip; | ||
43 | void __iomem *base; | ||
44 | spinlock_t lock; | ||
45 | #ifdef CONFIG_PM | ||
46 | u32 set_dr_val[XGENE_MAX_GPIO_BANKS]; | ||
47 | #endif | ||
48 | }; | ||
49 | |||
50 | static inline struct xgene_gpio *to_xgene_gpio(struct gpio_chip *chip) | ||
51 | { | ||
52 | return container_of(chip, struct xgene_gpio, chip); | ||
53 | } | ||
54 | |||
55 | static int xgene_gpio_get(struct gpio_chip *gc, unsigned int offset) | ||
56 | { | ||
57 | struct xgene_gpio *chip = to_xgene_gpio(gc); | ||
58 | unsigned long bank_offset; | ||
59 | u32 bit_offset; | ||
60 | |||
61 | bank_offset = GPIO_DATA_OFFSET + GPIO_BANK_OFFSET(offset); | ||
62 | bit_offset = GPIO_BIT_OFFSET(offset); | ||
63 | return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset)); | ||
64 | } | ||
65 | |||
66 | static void __xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) | ||
67 | { | ||
68 | struct xgene_gpio *chip = to_xgene_gpio(gc); | ||
69 | unsigned long bank_offset; | ||
70 | u32 setval, bit_offset; | ||
71 | |||
72 | bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); | ||
73 | bit_offset = GPIO_BIT_OFFSET(offset) + XGENE_GPIOS_PER_BANK; | ||
74 | |||
75 | setval = ioread32(chip->base + bank_offset); | ||
76 | if (val) | ||
77 | setval |= BIT(bit_offset); | ||
78 | else | ||
79 | setval &= ~BIT(bit_offset); | ||
80 | iowrite32(setval, chip->base + bank_offset); | ||
81 | } | ||
82 | |||
83 | static void xgene_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) | ||
84 | { | ||
85 | struct xgene_gpio *chip = to_xgene_gpio(gc); | ||
86 | unsigned long flags; | ||
87 | |||
88 | spin_lock_irqsave(&chip->lock, flags); | ||
89 | __xgene_gpio_set(gc, offset, val); | ||
90 | spin_unlock_irqrestore(&chip->lock, flags); | ||
91 | } | ||
92 | |||
93 | static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) | ||
94 | { | ||
95 | struct xgene_gpio *chip = to_xgene_gpio(gc); | ||
96 | unsigned long flags, bank_offset; | ||
97 | u32 dirval, bit_offset; | ||
98 | |||
99 | bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); | ||
100 | bit_offset = GPIO_BIT_OFFSET(offset); | ||
101 | |||
102 | spin_lock_irqsave(&chip->lock, flags); | ||
103 | |||
104 | dirval = ioread32(chip->base + bank_offset); | ||
105 | dirval |= BIT(bit_offset); | ||
106 | iowrite32(dirval, chip->base + bank_offset); | ||
107 | |||
108 | spin_unlock_irqrestore(&chip->lock, flags); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int xgene_gpio_dir_out(struct gpio_chip *gc, | ||
114 | unsigned int offset, int val) | ||
115 | { | ||
116 | struct xgene_gpio *chip = to_xgene_gpio(gc); | ||
117 | unsigned long flags, bank_offset; | ||
118 | u32 dirval, bit_offset; | ||
119 | |||
120 | bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset); | ||
121 | bit_offset = GPIO_BIT_OFFSET(offset); | ||
122 | |||
123 | spin_lock_irqsave(&chip->lock, flags); | ||
124 | |||
125 | dirval = ioread32(chip->base + bank_offset); | ||
126 | dirval &= ~BIT(bit_offset); | ||
127 | iowrite32(dirval, chip->base + bank_offset); | ||
128 | __xgene_gpio_set(gc, offset, val); | ||
129 | |||
130 | spin_unlock_irqrestore(&chip->lock, flags); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | #ifdef CONFIG_PM | ||
136 | static int xgene_gpio_suspend(struct device *dev) | ||
137 | { | ||
138 | struct xgene_gpio *gpio = dev_get_drvdata(dev); | ||
139 | unsigned long bank_offset; | ||
140 | unsigned int bank; | ||
141 | |||
142 | for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) { | ||
143 | bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE; | ||
144 | gpio->set_dr_val[bank] = ioread32(gpio->base + bank_offset); | ||
145 | } | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int xgene_gpio_resume(struct device *dev) | ||
150 | { | ||
151 | struct xgene_gpio *gpio = dev_get_drvdata(dev); | ||
152 | unsigned long bank_offset; | ||
153 | unsigned int bank; | ||
154 | |||
155 | for (bank = 0; bank < XGENE_MAX_GPIO_BANKS; bank++) { | ||
156 | bank_offset = GPIO_SET_DR_OFFSET + bank * GPIO_BANK_STRIDE; | ||
157 | iowrite32(gpio->set_dr_val[bank], gpio->base + bank_offset); | ||
158 | } | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); | ||
163 | #define XGENE_GPIO_PM_OPS (&xgene_gpio_pm) | ||
164 | #else | ||
165 | #define XGENE_GPIO_PM_OPS NULL | ||
166 | #endif | ||
167 | |||
168 | static int xgene_gpio_probe(struct platform_device *pdev) | ||
169 | { | ||
170 | struct resource *res; | ||
171 | struct xgene_gpio *gpio; | ||
172 | int err = 0; | ||
173 | |||
174 | gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); | ||
175 | if (!gpio) { | ||
176 | err = -ENOMEM; | ||
177 | goto err; | ||
178 | } | ||
179 | |||
180 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
181 | gpio->base = devm_ioremap_nocache(&pdev->dev, res->start, | ||
182 | resource_size(res)); | ||
183 | if (!gpio->base) { | ||
184 | err = -ENOMEM; | ||
185 | goto err; | ||
186 | } | ||
187 | |||
188 | gpio->chip.ngpio = XGENE_MAX_GPIOS; | ||
189 | |||
190 | spin_lock_init(&gpio->lock); | ||
191 | gpio->chip.dev = &pdev->dev; | ||
192 | gpio->chip.direction_input = xgene_gpio_dir_in; | ||
193 | gpio->chip.direction_output = xgene_gpio_dir_out; | ||
194 | gpio->chip.get = xgene_gpio_get; | ||
195 | gpio->chip.set = xgene_gpio_set; | ||
196 | gpio->chip.label = dev_name(&pdev->dev); | ||
197 | gpio->chip.base = -1; | ||
198 | |||
199 | platform_set_drvdata(pdev, gpio); | ||
200 | |||
201 | err = gpiochip_add(&gpio->chip); | ||
202 | if (err) { | ||
203 | dev_err(&pdev->dev, | ||
204 | "failed to register gpiochip.\n"); | ||
205 | goto err; | ||
206 | } | ||
207 | |||
208 | dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); | ||
209 | return 0; | ||
210 | err: | ||
211 | dev_err(&pdev->dev, "X-Gene GPIO driver registration failed.\n"); | ||
212 | return err; | ||
213 | } | ||
214 | |||
215 | static int xgene_gpio_remove(struct platform_device *pdev) | ||
216 | { | ||
217 | struct xgene_gpio *gpio = platform_get_drvdata(pdev); | ||
218 | |||
219 | gpiochip_remove(&gpio->chip); | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static const struct of_device_id xgene_gpio_of_match[] = { | ||
224 | { .compatible = "apm,xgene-gpio", }, | ||
225 | {}, | ||
226 | }; | ||
227 | MODULE_DEVICE_TABLE(of, xgene_gpio_of_match); | ||
228 | |||
229 | static struct platform_driver xgene_gpio_driver = { | ||
230 | .driver = { | ||
231 | .name = "xgene-gpio", | ||
232 | .owner = THIS_MODULE, | ||
233 | .of_match_table = xgene_gpio_of_match, | ||
234 | .pm = XGENE_GPIO_PM_OPS, | ||
235 | }, | ||
236 | .probe = xgene_gpio_probe, | ||
237 | .remove = xgene_gpio_remove, | ||
238 | }; | ||
239 | |||
240 | module_platform_driver(xgene_gpio_driver); | ||
241 | |||
242 | MODULE_AUTHOR("Feng Kan <fkan@apm.com>"); | ||
243 | MODULE_DESCRIPTION("APM X-Gene GPIO driver"); | ||
244 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 12481867daf1..ba18b06c9a21 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c | |||
@@ -197,6 +197,7 @@ static int xgpio_of_probe(struct device_node *np) | |||
197 | struct xgpio_instance *chip; | 197 | struct xgpio_instance *chip; |
198 | int status = 0; | 198 | int status = 0; |
199 | const u32 *tree_info; | 199 | const u32 *tree_info; |
200 | u32 ngpio; | ||
200 | 201 | ||
201 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 202 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
202 | if (!chip) | 203 | if (!chip) |
@@ -211,12 +212,13 @@ static int xgpio_of_probe(struct device_node *np) | |||
211 | /* Update GPIO direction shadow register with default value */ | 212 | /* Update GPIO direction shadow register with default value */ |
212 | of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); | 213 | of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); |
213 | 214 | ||
214 | /* By default assume full GPIO controller */ | 215 | /* |
215 | chip->mmchip.gc.ngpio = 32; | 216 | * Check device node and parent device node for device width |
216 | 217 | * and assume default width of 32 | |
217 | /* Check device node and parent device node for device width */ | 218 | */ |
218 | of_property_read_u32(np, "xlnx,gpio-width", | 219 | if (of_property_read_u32(np, "xlnx,gpio-width", &ngpio)) |
219 | (u32 *)&chip->mmchip.gc.ngpio); | 220 | ngpio = 32; |
221 | chip->mmchip.gc.ngpio = (u16)ngpio; | ||
220 | 222 | ||
221 | spin_lock_init(&chip->gpio_lock); | 223 | spin_lock_init(&chip->gpio_lock); |
222 | 224 | ||
@@ -258,12 +260,13 @@ static int xgpio_of_probe(struct device_node *np) | |||
258 | /* Update GPIO direction shadow register with default value */ | 260 | /* Update GPIO direction shadow register with default value */ |
259 | of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir); | 261 | of_property_read_u32(np, "xlnx,tri-default-2", &chip->gpio_dir); |
260 | 262 | ||
261 | /* By default assume full GPIO controller */ | 263 | /* |
262 | chip->mmchip.gc.ngpio = 32; | 264 | * Check device node and parent device node for device width |
263 | 265 | * and assume default width of 32 | |
264 | /* Check device node and parent device node for device width */ | 266 | */ |
265 | of_property_read_u32(np, "xlnx,gpio2-width", | 267 | if (of_property_read_u32(np, "xlnx,gpio2-width", &ngpio)) |
266 | (u32 *)&chip->mmchip.gc.ngpio); | 268 | ngpio = 32; |
269 | chip->mmchip.gc.ngpio = (u16)ngpio; | ||
267 | 270 | ||
268 | spin_lock_init(&chip->gpio_lock); | 271 | spin_lock_init(&chip->gpio_lock); |
269 | 272 | ||
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 31ad5df5dbc9..74cd480bf8de 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c | |||
@@ -88,16 +88,17 @@ | |||
88 | * @chip: instance of the gpio_chip | 88 | * @chip: instance of the gpio_chip |
89 | * @base_addr: base address of the GPIO device | 89 | * @base_addr: base address of the GPIO device |
90 | * @clk: clock resource for this controller | 90 | * @clk: clock resource for this controller |
91 | * @irq: interrupt for the GPIO device | ||
91 | */ | 92 | */ |
92 | struct zynq_gpio { | 93 | struct zynq_gpio { |
93 | struct gpio_chip chip; | 94 | struct gpio_chip chip; |
94 | void __iomem *base_addr; | 95 | void __iomem *base_addr; |
95 | struct clk *clk; | 96 | struct clk *clk; |
97 | int irq; | ||
96 | }; | 98 | }; |
97 | 99 | ||
98 | static struct irq_chip zynq_gpio_level_irqchip; | 100 | static struct irq_chip zynq_gpio_level_irqchip; |
99 | static struct irq_chip zynq_gpio_edge_irqchip; | 101 | static struct irq_chip zynq_gpio_edge_irqchip; |
100 | |||
101 | /** | 102 | /** |
102 | * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank | 103 | * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank |
103 | * for a given pin in the GPIO device | 104 | * for a given pin in the GPIO device |
@@ -138,6 +139,13 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, | |||
138 | } | 139 | } |
139 | } | 140 | } |
140 | 141 | ||
142 | static const unsigned int zynq_gpio_bank_offset[] = { | ||
143 | ZYNQ_GPIO_BANK0_PIN_MIN, | ||
144 | ZYNQ_GPIO_BANK1_PIN_MIN, | ||
145 | ZYNQ_GPIO_BANK2_PIN_MIN, | ||
146 | ZYNQ_GPIO_BANK3_PIN_MIN, | ||
147 | }; | ||
148 | |||
141 | /** | 149 | /** |
142 | * zynq_gpio_get_value - Get the state of the specified pin of GPIO device | 150 | * zynq_gpio_get_value - Get the state of the specified pin of GPIO device |
143 | * @chip: gpio_chip instance to be worked on | 151 | * @chip: gpio_chip instance to be worked on |
@@ -427,10 +435,9 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) | |||
427 | 435 | ||
428 | static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) | 436 | static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on) |
429 | { | 437 | { |
430 | if (on) | 438 | struct zynq_gpio *gpio = irq_data_get_irq_chip_data(data); |
431 | zynq_gpio_irq_unmask(data); | 439 | |
432 | else | 440 | irq_set_irq_wake(gpio->irq, on); |
433 | zynq_gpio_irq_mask(data); | ||
434 | 441 | ||
435 | return 0; | 442 | return 0; |
436 | } | 443 | } |
@@ -444,7 +451,8 @@ static struct irq_chip zynq_gpio_level_irqchip = { | |||
444 | .irq_unmask = zynq_gpio_irq_unmask, | 451 | .irq_unmask = zynq_gpio_irq_unmask, |
445 | .irq_set_type = zynq_gpio_set_irq_type, | 452 | .irq_set_type = zynq_gpio_set_irq_type, |
446 | .irq_set_wake = zynq_gpio_set_wake, | 453 | .irq_set_wake = zynq_gpio_set_wake, |
447 | .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, | 454 | .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | |
455 | IRQCHIP_MASK_ON_SUSPEND, | ||
448 | }; | 456 | }; |
449 | 457 | ||
450 | static struct irq_chip zynq_gpio_edge_irqchip = { | 458 | static struct irq_chip zynq_gpio_edge_irqchip = { |
@@ -455,8 +463,28 @@ static struct irq_chip zynq_gpio_edge_irqchip = { | |||
455 | .irq_unmask = zynq_gpio_irq_unmask, | 463 | .irq_unmask = zynq_gpio_irq_unmask, |
456 | .irq_set_type = zynq_gpio_set_irq_type, | 464 | .irq_set_type = zynq_gpio_set_irq_type, |
457 | .irq_set_wake = zynq_gpio_set_wake, | 465 | .irq_set_wake = zynq_gpio_set_wake, |
466 | .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
458 | }; | 467 | }; |
459 | 468 | ||
469 | static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio, | ||
470 | unsigned int bank_num, | ||
471 | unsigned long pending) | ||
472 | { | ||
473 | unsigned int bank_offset = zynq_gpio_bank_offset[bank_num]; | ||
474 | struct irq_domain *irqdomain = gpio->chip.irqdomain; | ||
475 | int offset; | ||
476 | |||
477 | if (!pending) | ||
478 | return; | ||
479 | |||
480 | for_each_set_bit(offset, &pending, 32) { | ||
481 | unsigned int gpio_irq; | ||
482 | |||
483 | gpio_irq = irq_find_mapping(irqdomain, offset + bank_offset); | ||
484 | generic_handle_irq(gpio_irq); | ||
485 | } | ||
486 | } | ||
487 | |||
460 | /** | 488 | /** |
461 | * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device | 489 | * zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device |
462 | * @irq: irq number of the gpio bank where interrupt has occurred | 490 | * @irq: irq number of the gpio bank where interrupt has occurred |
@@ -482,18 +510,7 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc) | |||
482 | ZYNQ_GPIO_INTSTS_OFFSET(bank_num)); | 510 | ZYNQ_GPIO_INTSTS_OFFSET(bank_num)); |
483 | int_enb = readl_relaxed(gpio->base_addr + | 511 | int_enb = readl_relaxed(gpio->base_addr + |
484 | ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); | 512 | ZYNQ_GPIO_INTMASK_OFFSET(bank_num)); |
485 | int_sts &= ~int_enb; | 513 | zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb); |
486 | if (int_sts) { | ||
487 | int offset; | ||
488 | unsigned long pending = int_sts; | ||
489 | |||
490 | for_each_set_bit(offset, &pending, 32) { | ||
491 | unsigned int gpio_irq = | ||
492 | irq_find_mapping(gpio->chip.irqdomain, | ||
493 | offset); | ||
494 | generic_handle_irq(gpio_irq); | ||
495 | } | ||
496 | } | ||
497 | } | 514 | } |
498 | 515 | ||
499 | chained_irq_exit(irqchip, desc); | 516 | chained_irq_exit(irqchip, desc); |
@@ -501,7 +518,11 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc) | |||
501 | 518 | ||
502 | static int __maybe_unused zynq_gpio_suspend(struct device *dev) | 519 | static int __maybe_unused zynq_gpio_suspend(struct device *dev) |
503 | { | 520 | { |
504 | if (!device_may_wakeup(dev)) | 521 | struct platform_device *pdev = to_platform_device(dev); |
522 | int irq = platform_get_irq(pdev, 0); | ||
523 | struct irq_data *data = irq_get_irq_data(irq); | ||
524 | |||
525 | if (!irqd_is_wakeup_set(data)) | ||
505 | return pm_runtime_force_suspend(dev); | 526 | return pm_runtime_force_suspend(dev); |
506 | 527 | ||
507 | return 0; | 528 | return 0; |
@@ -509,7 +530,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) | |||
509 | 530 | ||
510 | static int __maybe_unused zynq_gpio_resume(struct device *dev) | 531 | static int __maybe_unused zynq_gpio_resume(struct device *dev) |
511 | { | 532 | { |
512 | if (!device_may_wakeup(dev)) | 533 | struct platform_device *pdev = to_platform_device(dev); |
534 | int irq = platform_get_irq(pdev, 0); | ||
535 | struct irq_data *data = irq_get_irq_data(irq); | ||
536 | |||
537 | if (!irqd_is_wakeup_set(data)) | ||
513 | return pm_runtime_force_resume(dev); | 538 | return pm_runtime_force_resume(dev); |
514 | 539 | ||
515 | return 0; | 540 | return 0; |
@@ -570,7 +595,7 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { | |||
570 | */ | 595 | */ |
571 | static int zynq_gpio_probe(struct platform_device *pdev) | 596 | static int zynq_gpio_probe(struct platform_device *pdev) |
572 | { | 597 | { |
573 | int ret, bank_num, irq; | 598 | int ret, bank_num; |
574 | struct zynq_gpio *gpio; | 599 | struct zynq_gpio *gpio; |
575 | struct gpio_chip *chip; | 600 | struct gpio_chip *chip; |
576 | struct resource *res; | 601 | struct resource *res; |
@@ -586,10 +611,10 @@ static int zynq_gpio_probe(struct platform_device *pdev) | |||
586 | if (IS_ERR(gpio->base_addr)) | 611 | if (IS_ERR(gpio->base_addr)) |
587 | return PTR_ERR(gpio->base_addr); | 612 | return PTR_ERR(gpio->base_addr); |
588 | 613 | ||
589 | irq = platform_get_irq(pdev, 0); | 614 | gpio->irq = platform_get_irq(pdev, 0); |
590 | if (irq < 0) { | 615 | if (gpio->irq < 0) { |
591 | dev_err(&pdev->dev, "invalid IRQ\n"); | 616 | dev_err(&pdev->dev, "invalid IRQ\n"); |
592 | return irq; | 617 | return gpio->irq; |
593 | } | 618 | } |
594 | 619 | ||
595 | /* configure the gpio chip */ | 620 | /* configure the gpio chip */ |
@@ -637,19 +662,16 @@ static int zynq_gpio_probe(struct platform_device *pdev) | |||
637 | goto err_rm_gpiochip; | 662 | goto err_rm_gpiochip; |
638 | } | 663 | } |
639 | 664 | ||
640 | gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, irq, | 665 | gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq, |
641 | zynq_gpio_irqhandler); | 666 | zynq_gpio_irqhandler); |
642 | 667 | ||
643 | pm_runtime_set_active(&pdev->dev); | 668 | pm_runtime_set_active(&pdev->dev); |
644 | pm_runtime_enable(&pdev->dev); | 669 | pm_runtime_enable(&pdev->dev); |
645 | 670 | ||
646 | device_set_wakeup_capable(&pdev->dev, 1); | ||
647 | |||
648 | return 0; | 671 | return 0; |
649 | 672 | ||
650 | err_rm_gpiochip: | 673 | err_rm_gpiochip: |
651 | if (gpiochip_remove(chip)) | 674 | gpiochip_remove(chip); |
652 | dev_err(&pdev->dev, "Failed to remove gpio chip\n"); | ||
653 | err_disable_clk: | 675 | err_disable_clk: |
654 | clk_disable_unprepare(gpio->clk); | 676 | clk_disable_unprepare(gpio->clk); |
655 | 677 | ||
@@ -664,16 +686,10 @@ err_disable_clk: | |||
664 | */ | 686 | */ |
665 | static int zynq_gpio_remove(struct platform_device *pdev) | 687 | static int zynq_gpio_remove(struct platform_device *pdev) |
666 | { | 688 | { |
667 | int ret; | ||
668 | struct zynq_gpio *gpio = platform_get_drvdata(pdev); | 689 | struct zynq_gpio *gpio = platform_get_drvdata(pdev); |
669 | 690 | ||
670 | pm_runtime_get_sync(&pdev->dev); | 691 | pm_runtime_get_sync(&pdev->dev); |
671 | 692 | gpiochip_remove(&gpio->chip); | |
672 | ret = gpiochip_remove(&gpio->chip); | ||
673 | if (ret) { | ||
674 | dev_err(&pdev->dev, "Failed to remove gpio chip\n"); | ||
675 | return ret; | ||
676 | } | ||
677 | clk_disable_unprepare(gpio->clk); | 693 | clk_disable_unprepare(gpio->clk); |
678 | device_set_wakeup_capable(&pdev->dev, 0); | 694 | device_set_wakeup_capable(&pdev->dev, 0); |
679 | return 0; | 695 | return 0; |
@@ -688,7 +704,6 @@ MODULE_DEVICE_TABLE(of, zynq_gpio_of_match); | |||
688 | static struct platform_driver zynq_gpio_driver = { | 704 | static struct platform_driver zynq_gpio_driver = { |
689 | .driver = { | 705 | .driver = { |
690 | .name = DRIVER_NAME, | 706 | .name = DRIVER_NAME, |
691 | .owner = THIS_MODULE, | ||
692 | .pm = &zynq_gpio_dev_pm_ops, | 707 | .pm = &zynq_gpio_dev_pm_ops, |
693 | .of_match_table = zynq_gpio_of_match, | 708 | .of_match_table = zynq_gpio_of_match, |
694 | }, | 709 | }, |
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 687476fb39e3..05c6275da224 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -25,10 +25,12 @@ struct acpi_gpio_event { | |||
25 | acpi_handle handle; | 25 | acpi_handle handle; |
26 | unsigned int pin; | 26 | unsigned int pin; |
27 | unsigned int irq; | 27 | unsigned int irq; |
28 | struct gpio_desc *desc; | ||
28 | }; | 29 | }; |
29 | 30 | ||
30 | struct acpi_gpio_connection { | 31 | struct acpi_gpio_connection { |
31 | struct list_head node; | 32 | struct list_head node; |
33 | unsigned int pin; | ||
32 | struct gpio_desc *desc; | 34 | struct gpio_desc *desc; |
33 | }; | 35 | }; |
34 | 36 | ||
@@ -143,14 +145,8 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, | |||
143 | if (!handler) | 145 | if (!handler) |
144 | return AE_BAD_PARAMETER; | 146 | return AE_BAD_PARAMETER; |
145 | 147 | ||
146 | desc = gpiochip_get_desc(chip, pin); | 148 | desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event"); |
147 | if (IS_ERR(desc)) { | 149 | if (IS_ERR(desc)) { |
148 | dev_err(chip->dev, "Failed to get GPIO descriptor\n"); | ||
149 | return AE_ERROR; | ||
150 | } | ||
151 | |||
152 | ret = gpiochip_request_own_desc(desc, "ACPI:Event"); | ||
153 | if (ret) { | ||
154 | dev_err(chip->dev, "Failed to request GPIO\n"); | 150 | dev_err(chip->dev, "Failed to request GPIO\n"); |
155 | return AE_ERROR; | 151 | return AE_ERROR; |
156 | } | 152 | } |
@@ -197,6 +193,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, | |||
197 | event->handle = evt_handle; | 193 | event->handle = evt_handle; |
198 | event->irq = irq; | 194 | event->irq = irq; |
199 | event->pin = pin; | 195 | event->pin = pin; |
196 | event->desc = desc; | ||
200 | 197 | ||
201 | ret = request_threaded_irq(event->irq, NULL, handler, irqflags, | 198 | ret = request_threaded_irq(event->irq, NULL, handler, irqflags, |
202 | "ACPI:Event", event); | 199 | "ACPI:Event", event); |
@@ -280,7 +277,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) | |||
280 | struct gpio_desc *desc; | 277 | struct gpio_desc *desc; |
281 | 278 | ||
282 | free_irq(event->irq, event); | 279 | free_irq(event->irq, event); |
283 | desc = gpiochip_get_desc(chip, event->pin); | 280 | desc = event->desc; |
284 | if (WARN_ON(IS_ERR(desc))) | 281 | if (WARN_ON(IS_ERR(desc))) |
285 | continue; | 282 | continue; |
286 | gpio_unlock_as_irq(chip, event->pin); | 283 | gpio_unlock_as_irq(chip, event->pin); |
@@ -409,26 +406,20 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, | |||
409 | struct gpio_desc *desc; | 406 | struct gpio_desc *desc; |
410 | bool found; | 407 | bool found; |
411 | 408 | ||
412 | desc = gpiochip_get_desc(chip, pin); | ||
413 | if (IS_ERR(desc)) { | ||
414 | status = AE_ERROR; | ||
415 | goto out; | ||
416 | } | ||
417 | |||
418 | mutex_lock(&achip->conn_lock); | 409 | mutex_lock(&achip->conn_lock); |
419 | 410 | ||
420 | found = false; | 411 | found = false; |
421 | list_for_each_entry(conn, &achip->conns, node) { | 412 | list_for_each_entry(conn, &achip->conns, node) { |
422 | if (conn->desc == desc) { | 413 | if (conn->pin == pin) { |
423 | found = true; | 414 | found = true; |
415 | desc = conn->desc; | ||
424 | break; | 416 | break; |
425 | } | 417 | } |
426 | } | 418 | } |
427 | if (!found) { | 419 | if (!found) { |
428 | int ret; | 420 | desc = gpiochip_request_own_desc(chip, pin, |
429 | 421 | "ACPI:OpRegion"); | |
430 | ret = gpiochip_request_own_desc(desc, "ACPI:OpRegion"); | 422 | if (IS_ERR(desc)) { |
431 | if (ret) { | ||
432 | status = AE_ERROR; | 423 | status = AE_ERROR; |
433 | mutex_unlock(&achip->conn_lock); | 424 | mutex_unlock(&achip->conn_lock); |
434 | goto out; | 425 | goto out; |
@@ -465,6 +456,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, | |||
465 | goto out; | 456 | goto out; |
466 | } | 457 | } |
467 | 458 | ||
459 | conn->pin = pin; | ||
468 | conn->desc = desc; | 460 | conn->desc = desc; |
469 | list_add_tail(&conn->node, &achip->conns); | 461 | list_add_tail(&conn->node, &achip->conns); |
470 | } | 462 | } |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c68d037de656..e8e98ca25ec7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -308,10 +308,9 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); | |||
308 | * | 308 | * |
309 | * A gpio_chip with any GPIOs still requested may not be removed. | 309 | * A gpio_chip with any GPIOs still requested may not be removed. |
310 | */ | 310 | */ |
311 | int gpiochip_remove(struct gpio_chip *chip) | 311 | void gpiochip_remove(struct gpio_chip *chip) |
312 | { | 312 | { |
313 | unsigned long flags; | 313 | unsigned long flags; |
314 | int status = 0; | ||
315 | unsigned id; | 314 | unsigned id; |
316 | 315 | ||
317 | acpi_gpiochip_remove(chip); | 316 | acpi_gpiochip_remove(chip); |
@@ -323,24 +322,15 @@ int gpiochip_remove(struct gpio_chip *chip) | |||
323 | of_gpiochip_remove(chip); | 322 | of_gpiochip_remove(chip); |
324 | 323 | ||
325 | for (id = 0; id < chip->ngpio; id++) { | 324 | for (id = 0; id < chip->ngpio; id++) { |
326 | if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { | 325 | if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) |
327 | status = -EBUSY; | 326 | dev_crit(chip->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); |
328 | break; | ||
329 | } | ||
330 | } | ||
331 | if (status == 0) { | ||
332 | for (id = 0; id < chip->ngpio; id++) | ||
333 | chip->desc[id].chip = NULL; | ||
334 | |||
335 | list_del(&chip->list); | ||
336 | } | 327 | } |
328 | for (id = 0; id < chip->ngpio; id++) | ||
329 | chip->desc[id].chip = NULL; | ||
337 | 330 | ||
331 | list_del(&chip->list); | ||
338 | spin_unlock_irqrestore(&gpio_lock, flags); | 332 | spin_unlock_irqrestore(&gpio_lock, flags); |
339 | 333 | gpiochip_unexport(chip); | |
340 | if (status == 0) | ||
341 | gpiochip_unexport(chip); | ||
342 | |||
343 | return status; | ||
344 | } | 334 | } |
345 | EXPORT_SYMBOL_GPL(gpiochip_remove); | 335 | EXPORT_SYMBOL_GPL(gpiochip_remove); |
346 | 336 | ||
@@ -395,30 +385,47 @@ static struct gpio_chip *find_chip_by_name(const char *name) | |||
395 | */ | 385 | */ |
396 | 386 | ||
397 | /** | 387 | /** |
398 | * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip | 388 | * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip |
399 | * @gpiochip: the gpiochip to add the irqchip to | 389 | * @gpiochip: the gpiochip to set the irqchip chain to |
400 | * @irqchip: the irqchip to add to the gpiochip | 390 | * @irqchip: the irqchip to chain to the gpiochip |
401 | * @parent_irq: the irq number corresponding to the parent IRQ for this | 391 | * @parent_irq: the irq number corresponding to the parent IRQ for this |
402 | * chained irqchip | 392 | * chained irqchip |
403 | * @parent_handler: the parent interrupt handler for the accumulated IRQ | 393 | * @parent_handler: the parent interrupt handler for the accumulated IRQ |
404 | * coming out of the gpiochip | 394 | * coming out of the gpiochip. If the interrupt is nested rather than |
395 | * cascaded, pass NULL in this handler argument | ||
405 | */ | 396 | */ |
406 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, | 397 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, |
407 | struct irq_chip *irqchip, | 398 | struct irq_chip *irqchip, |
408 | int parent_irq, | 399 | int parent_irq, |
409 | irq_flow_handler_t parent_handler) | 400 | irq_flow_handler_t parent_handler) |
410 | { | 401 | { |
411 | if (gpiochip->can_sleep) { | 402 | unsigned int offset; |
412 | chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n"); | 403 | |
404 | if (!gpiochip->irqdomain) { | ||
405 | chip_err(gpiochip, "called %s before setting up irqchip\n", | ||
406 | __func__); | ||
413 | return; | 407 | return; |
414 | } | 408 | } |
415 | 409 | ||
416 | /* | 410 | if (parent_handler) { |
417 | * The parent irqchip is already using the chip_data for this | 411 | if (gpiochip->can_sleep) { |
418 | * irqchip, so our callbacks simply use the handler_data. | 412 | chip_err(gpiochip, |
419 | */ | 413 | "you cannot have chained interrupts on a " |
420 | irq_set_handler_data(parent_irq, gpiochip); | 414 | "chip that may sleep\n"); |
421 | irq_set_chained_handler(parent_irq, parent_handler); | 415 | return; |
416 | } | ||
417 | /* | ||
418 | * The parent irqchip is already using the chip_data for this | ||
419 | * irqchip, so our callbacks simply use the handler_data. | ||
420 | */ | ||
421 | irq_set_handler_data(parent_irq, gpiochip); | ||
422 | irq_set_chained_handler(parent_irq, parent_handler); | ||
423 | } | ||
424 | |||
425 | /* Set the parent IRQ for all affected IRQs */ | ||
426 | for (offset = 0; offset < gpiochip->ngpio; offset++) | ||
427 | irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset), | ||
428 | parent_irq); | ||
422 | } | 429 | } |
423 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); | 430 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); |
424 | 431 | ||
@@ -447,7 +454,7 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, | |||
447 | irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); | 454 | irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); |
448 | irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); | 455 | irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); |
449 | /* Chips that can sleep need nested thread handlers */ | 456 | /* Chips that can sleep need nested thread handlers */ |
450 | if (chip->can_sleep) | 457 | if (chip->can_sleep && !chip->irq_not_threaded) |
451 | irq_set_nested_thread(irq, 1); | 458 | irq_set_nested_thread(irq, 1); |
452 | #ifdef CONFIG_ARM | 459 | #ifdef CONFIG_ARM |
453 | set_irq_flags(irq, IRQF_VALID); | 460 | set_irq_flags(irq, IRQF_VALID); |
@@ -524,7 +531,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) | |||
524 | /* Remove all IRQ mappings and delete the domain */ | 531 | /* Remove all IRQ mappings and delete the domain */ |
525 | if (gpiochip->irqdomain) { | 532 | if (gpiochip->irqdomain) { |
526 | for (offset = 0; offset < gpiochip->ngpio; offset++) | 533 | for (offset = 0; offset < gpiochip->ngpio; offset++) |
527 | irq_dispose_mapping(gpiochip->irq_base + offset); | 534 | irq_dispose_mapping( |
535 | irq_find_mapping(gpiochip->irqdomain, offset)); | ||
528 | irq_domain_remove(gpiochip->irqdomain); | 536 | irq_domain_remove(gpiochip->irqdomain); |
529 | } | 537 | } |
530 | 538 | ||
@@ -895,12 +903,22 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); | |||
895 | * allows the GPIO chip module to be unloaded as needed (we assume that the | 903 | * allows the GPIO chip module to be unloaded as needed (we assume that the |
896 | * GPIO chip driver handles freeing the GPIOs it has requested). | 904 | * GPIO chip driver handles freeing the GPIOs it has requested). |
897 | */ | 905 | */ |
898 | int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) | 906 | struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, |
907 | const char *label) | ||
899 | { | 908 | { |
900 | if (!desc || !desc->chip) | 909 | struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); |
901 | return -EINVAL; | 910 | int err; |
902 | 911 | ||
903 | return __gpiod_request(desc, label); | 912 | if (IS_ERR(desc)) { |
913 | chip_err(chip, "failed to get GPIO descriptor\n"); | ||
914 | return desc; | ||
915 | } | ||
916 | |||
917 | err = __gpiod_request(desc, label); | ||
918 | if (err < 0) | ||
919 | return ERR_PTR(err); | ||
920 | |||
921 | return desc; | ||
904 | } | 922 | } |
905 | EXPORT_SYMBOL_GPL(gpiochip_request_own_desc); | 923 | EXPORT_SYMBOL_GPL(gpiochip_request_own_desc); |
906 | 924 | ||
@@ -1652,7 +1670,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, | |||
1652 | * a result. In that case, use platform lookup as a fallback. | 1670 | * a result. In that case, use platform lookup as a fallback. |
1653 | */ | 1671 | */ |
1654 | if (!desc || desc == ERR_PTR(-ENOENT)) { | 1672 | if (!desc || desc == ERR_PTR(-ENOENT)) { |
1655 | dev_dbg(dev, "using lookup tables for GPIO lookup"); | 1673 | dev_dbg(dev, "using lookup tables for GPIO lookup\n"); |
1656 | desc = gpiod_find(dev, con_id, idx, &lookupflags); | 1674 | desc = gpiod_find(dev, con_id, idx, &lookupflags); |
1657 | } | 1675 | } |
1658 | 1676 | ||