diff options
-rw-r--r-- | Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mcp23s08.c | 30 |
2 files changed, 25 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt b/Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt index c306a2d0f2b1..f3332b9a8ed4 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt | |||
@@ -57,6 +57,8 @@ Optional device specific properties: | |||
57 | occurred on. If it is not set, the interrupt are only generated for the | 57 | occurred on. If it is not set, the interrupt are only generated for the |
58 | bank they belong to. | 58 | bank they belong to. |
59 | On devices with only one interrupt output this property is useless. | 59 | On devices with only one interrupt output this property is useless. |
60 | - microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This | ||
61 | configures the IRQ output polarity as active high. | ||
60 | 62 | ||
61 | Example I2C (with interrupt): | 63 | Example I2C (with interrupt): |
62 | gpiom1: gpio@20 { | 64 | gpiom1: gpio@20 { |
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 0d58440eb8da..93ee7da2d8b0 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c | |||
@@ -65,6 +65,7 @@ struct mcp23s08_ops { | |||
65 | 65 | ||
66 | struct mcp23s08 { | 66 | struct mcp23s08 { |
67 | u8 addr; | 67 | u8 addr; |
68 | bool irq_active_high; | ||
68 | 69 | ||
69 | u16 cache[11]; | 70 | u16 cache[11]; |
70 | u16 irq_rise; | 71 | u16 irq_rise; |
@@ -476,6 +477,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) | |||
476 | { | 477 | { |
477 | struct gpio_chip *chip = &mcp->chip; | 478 | struct gpio_chip *chip = &mcp->chip; |
478 | int err, irq, j; | 479 | int err, irq, j; |
480 | unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED; | ||
479 | 481 | ||
480 | mutex_init(&mcp->irq_lock); | 482 | mutex_init(&mcp->irq_lock); |
481 | 483 | ||
@@ -484,10 +486,13 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) | |||
484 | if (!mcp->irq_domain) | 486 | if (!mcp->irq_domain) |
485 | return -ENODEV; | 487 | return -ENODEV; |
486 | 488 | ||
489 | if (mcp->irq_active_high) | ||
490 | irqflags |= IRQF_TRIGGER_HIGH; | ||
491 | else | ||
492 | irqflags |= IRQF_TRIGGER_LOW; | ||
493 | |||
487 | err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, | 494 | err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, |
488 | IRQF_TRIGGER_LOW | IRQF_ONESHOT | | 495 | irqflags, dev_name(chip->dev), mcp); |
489 | IRQF_SHARED, | ||
490 | dev_name(chip->dev), mcp); | ||
491 | if (err != 0) { | 496 | if (err != 0) { |
492 | dev_err(chip->dev, "unable to request IRQ#%d: %d\n", | 497 | dev_err(chip->dev, "unable to request IRQ#%d: %d\n", |
493 | mcp->irq, err); | 498 | mcp->irq, err); |
@@ -589,6 +594,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
589 | 594 | ||
590 | mcp->data = data; | 595 | mcp->data = data; |
591 | mcp->addr = addr; | 596 | mcp->addr = addr; |
597 | mcp->irq_active_high = false; | ||
592 | 598 | ||
593 | mcp->chip.direction_input = mcp23s08_direction_input; | 599 | mcp->chip.direction_input = mcp23s08_direction_input; |
594 | mcp->chip.get = mcp23s08_get; | 600 | mcp->chip.get = mcp23s08_get; |
@@ -648,14 +654,24 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, | |||
648 | goto fail; | 654 | goto fail; |
649 | 655 | ||
650 | mcp->irq_controller = pdata->irq_controller; | 656 | mcp->irq_controller = pdata->irq_controller; |
651 | if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) | 657 | if (mcp->irq && mcp->irq_controller) { |
652 | mirror = pdata->mirror; | 658 | mcp->irq_active_high = of_property_read_bool(mcp->chip.of_node, |
659 | "microchip,irq-active-high"); | ||
653 | 660 | ||
654 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { | 661 | if (type == MCP_TYPE_017) |
662 | mirror = pdata->mirror; | ||
663 | } | ||
664 | |||
665 | if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror || | ||
666 | mcp->irq_active_high) { | ||
655 | /* mcp23s17 has IOCON twice, make sure they are in sync */ | 667 | /* mcp23s17 has IOCON twice, make sure they are in sync */ |
656 | status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); | 668 | status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); |
657 | status |= IOCON_HAEN | (IOCON_HAEN << 8); | 669 | status |= IOCON_HAEN | (IOCON_HAEN << 8); |
658 | status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); | 670 | if (mcp->irq_active_high) |
671 | status |= IOCON_INTPOL | (IOCON_INTPOL << 8); | ||
672 | else | ||
673 | status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); | ||
674 | |||
659 | if (mirror) | 675 | if (mirror) |
660 | status |= IOCON_MIRROR | (IOCON_MIRROR << 8); | 676 | status |= IOCON_MIRROR | (IOCON_MIRROR << 8); |
661 | 677 | ||