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>
This commit is contained in:
parent
0e9a5edf5d
commit
a4e635544f
2 changed files with 25 additions and 7 deletions
|
@ -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 {
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue