Commit a4e63554 authored by Alexander Stein's avatar Alexander Stein Committed by Linus Walleij

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: default avatarAlexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 0e9a5edf
...@@ -57,6 +57,8 @@ Optional device specific properties: ...@@ -57,6 +57,8 @@ Optional device specific properties:
occurred on. If it is not set, the interrupt are only generated for the occurred on. If it is not set, the interrupt are only generated for the
bank they belong to. bank they belong to.
On devices with only one interrupt output this property is useless. On devices with only one interrupt output this property is useless.
- microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This
configures the IRQ output polarity as active high.
Example I2C (with interrupt): Example I2C (with interrupt):
gpiom1: gpio@20 { gpiom1: gpio@20 {
......
...@@ -65,6 +65,7 @@ struct mcp23s08_ops { ...@@ -65,6 +65,7 @@ struct mcp23s08_ops {
struct mcp23s08 { struct mcp23s08 {
u8 addr; u8 addr;
bool irq_active_high;
u16 cache[11]; u16 cache[11];
u16 irq_rise; u16 irq_rise;
...@@ -476,6 +477,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) ...@@ -476,6 +477,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
{ {
struct gpio_chip *chip = &mcp->chip; struct gpio_chip *chip = &mcp->chip;
int err, irq, j; int err, irq, j;
unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED;
mutex_init(&mcp->irq_lock); mutex_init(&mcp->irq_lock);
...@@ -484,10 +486,13 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) ...@@ -484,10 +486,13 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
if (!mcp->irq_domain) if (!mcp->irq_domain)
return -ENODEV; return -ENODEV;
if (mcp->irq_active_high)
irqflags |= IRQF_TRIGGER_HIGH;
else
irqflags |= IRQF_TRIGGER_LOW;
err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT | irqflags, dev_name(chip->dev), mcp);
IRQF_SHARED,
dev_name(chip->dev), mcp);
if (err != 0) { if (err != 0) {
dev_err(chip->dev, "unable to request IRQ#%d: %d\n", dev_err(chip->dev, "unable to request IRQ#%d: %d\n",
mcp->irq, err); mcp->irq, err);
...@@ -589,6 +594,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, ...@@ -589,6 +594,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
mcp->data = data; mcp->data = data;
mcp->addr = addr; mcp->addr = addr;
mcp->irq_active_high = false;
mcp->chip.direction_input = mcp23s08_direction_input; mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get; mcp->chip.get = mcp23s08_get;
...@@ -648,14 +654,24 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, ...@@ -648,14 +654,24 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
goto fail; goto fail;
mcp->irq_controller = pdata->irq_controller; mcp->irq_controller = pdata->irq_controller;
if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) if (mcp->irq && mcp->irq_controller) {
mirror = pdata->mirror; mcp->irq_active_high = of_property_read_bool(mcp->chip.of_node,
"microchip,irq-active-high");
if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { if (type == MCP_TYPE_017)
mirror = pdata->mirror;
}
if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror ||
mcp->irq_active_high) {
/* mcp23s17 has IOCON twice, make sure they are in sync */ /* mcp23s17 has IOCON twice, make sure they are in sync */
status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
status |= IOCON_HAEN | (IOCON_HAEN << 8); status |= IOCON_HAEN | (IOCON_HAEN << 8);
status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); if (mcp->irq_active_high)
status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
else
status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
if (mirror) if (mirror)
status |= IOCON_MIRROR | (IOCON_MIRROR << 8); status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment