aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexander Stein <alexander.stein@systec-electronic.com>2014-12-01 02:26:00 -0500
committerLinus Walleij <linus.walleij@linaro.org>2014-12-03 08:34:45 -0500
commita4e635544f65021c346f2097daa0c8dd63dd6221 (patch)
tree0221e40e110afa800db6e4fa210fdcaf4e78f998 /drivers
parent0e9a5edf5d01356fa4a561772a25d97b3fd13de6 (diff)
gpio: mcp23s08: Add option to configure IRQ output polarity as active high
Default is active low, but if property is specified in DT set INTPOL flag. Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpio-mcp23s08.c30
1 files changed, 23 insertions, 7 deletions
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