aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt2
-rw-r--r--drivers/gpio/gpio-mcp23s08.c30
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
61Example I2C (with interrupt): 63Example I2C (with interrupt):
62gpiom1: gpio@20 { 64gpiom1: 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
66struct mcp23s08 { 66struct 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