Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alexander Stein and committed by
Linus Walleij
a4e63554 0e9a5edf

+25 -7
+2
Documentation/devicetree/bindings/gpio/gpio-mcp23s08.txt
··· 57 57 occurred on. If it is not set, the interrupt are only generated for the 58 58 bank they belong to. 59 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 63 Example I2C (with interrupt): 62 64 gpiom1: gpio@20 {
+23 -7
drivers/gpio/gpio-mcp23s08.c
··· 65 65 66 66 struct mcp23s08 { 67 67 u8 addr; 68 + bool irq_active_high; 68 69 69 70 u16 cache[11]; 70 71 u16 irq_rise; ··· 477 476 { 478 477 struct gpio_chip *chip = &mcp->chip; 479 478 int err, irq, j; 479 + unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED; 480 480 481 481 mutex_init(&mcp->irq_lock); 482 482 ··· 486 484 if (!mcp->irq_domain) 487 485 return -ENODEV; 488 486 487 + if (mcp->irq_active_high) 488 + irqflags |= IRQF_TRIGGER_HIGH; 489 + else 490 + irqflags |= IRQF_TRIGGER_LOW; 491 + 489 492 err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, 490 - IRQF_TRIGGER_LOW | IRQF_ONESHOT | 491 - IRQF_SHARED, 492 - dev_name(chip->dev), mcp); 493 + irqflags, dev_name(chip->dev), mcp); 493 494 if (err != 0) { 494 495 dev_err(chip->dev, "unable to request IRQ#%d: %d\n", 495 496 mcp->irq, err); ··· 594 589 595 590 mcp->data = data; 596 591 mcp->addr = addr; 592 + mcp->irq_active_high = false; 597 593 598 594 mcp->chip.direction_input = mcp23s08_direction_input; 599 595 mcp->chip.get = mcp23s08_get; ··· 654 648 goto fail; 655 649 656 650 mcp->irq_controller = pdata->irq_controller; 657 - if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) 658 - mirror = pdata->mirror; 651 + if (mcp->irq && mcp->irq_controller) { 652 + mcp->irq_active_high = of_property_read_bool(mcp->chip.of_node, 653 + "microchip,irq-active-high"); 659 654 660 - if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { 655 + if (type == MCP_TYPE_017) 656 + mirror = pdata->mirror; 657 + } 658 + 659 + if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror || 660 + mcp->irq_active_high) { 661 661 /* mcp23s17 has IOCON twice, make sure they are in sync */ 662 662 status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); 663 663 status |= IOCON_HAEN | (IOCON_HAEN << 8); 664 - status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); 664 + if (mcp->irq_active_high) 665 + status |= IOCON_INTPOL | (IOCON_INTPOL << 8); 666 + else 667 + status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); 668 + 665 669 if (mirror) 666 670 status |= IOCON_MIRROR | (IOCON_MIRROR << 8); 667 671