diff options
| author | Samuel Ortiz <sameo@linux.intel.com> | 2013-08-19 21:07:25 -0400 |
|---|---|---|
| committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-08-19 21:07:25 -0400 |
| commit | a849212f6e04dff5f977439d91c4642f2cdda775 (patch) | |
| tree | 028a67efe151bc604f981149e490fd56c1f5bbbf | |
| parent | 38c4faaea4ca71c69584ef71cca8d0735d5361c1 (diff) | |
| parent | 68622bdfefb969fd7cf710545d7e758a732ab01d (diff) | |
Merge tag 'regmap-irq-ack-mask' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
regmap: Support for acknowledging masked IRQs
Some devices need interrupts to be clear when they are masked otherwise
the interrupt is not deasserted by the mask being set - add support for
this to regmap-irq from Philipp Zabel.
| -rw-r--r-- | drivers/base/regmap/regmap-irq.c | 25 | ||||
| -rw-r--r-- | include/linux/regmap.h | 10 |
2 files changed, 32 insertions, 3 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 1643e889bafc..d10456ffd811 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c | |||
| @@ -418,6 +418,31 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, | |||
| 418 | reg, ret); | 418 | reg, ret); |
| 419 | goto err_alloc; | 419 | goto err_alloc; |
| 420 | } | 420 | } |
| 421 | |||
| 422 | if (!chip->init_ack_masked) | ||
| 423 | continue; | ||
| 424 | |||
| 425 | /* Ack masked but set interrupts */ | ||
| 426 | reg = chip->status_base + | ||
| 427 | (i * map->reg_stride * d->irq_reg_stride); | ||
| 428 | ret = regmap_read(map, reg, &d->status_buf[i]); | ||
| 429 | if (ret != 0) { | ||
| 430 | dev_err(map->dev, "Failed to read IRQ status: %d\n", | ||
| 431 | ret); | ||
| 432 | goto err_alloc; | ||
| 433 | } | ||
| 434 | |||
| 435 | if (d->status_buf[i] && chip->ack_base) { | ||
| 436 | reg = chip->ack_base + | ||
| 437 | (i * map->reg_stride * d->irq_reg_stride); | ||
| 438 | ret = regmap_write(map, reg, | ||
| 439 | d->status_buf[i] & d->mask_buf[i]); | ||
| 440 | if (ret != 0) { | ||
| 441 | dev_err(map->dev, "Failed to ack 0x%x: %d\n", | ||
| 442 | reg, ret); | ||
| 443 | goto err_alloc; | ||
| 444 | } | ||
| 445 | } | ||
| 421 | } | 446 | } |
| 422 | 447 | ||
| 423 | /* Wake is disabled by default */ | 448 | /* Wake is disabled by default */ |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 75981d0b57dc..a3c68aad2381 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -470,6 +470,9 @@ struct regmap_irq { | |||
| 470 | * @ack_base: Base ack address. If zero then the chip is clear on read. | 470 | * @ack_base: Base ack address. If zero then the chip is clear on read. |
| 471 | * @wake_base: Base address for wake enables. If zero unsupported. | 471 | * @wake_base: Base address for wake enables. If zero unsupported. |
| 472 | * @irq_reg_stride: Stride to use for chips where registers are not contiguous. | 472 | * @irq_reg_stride: Stride to use for chips where registers are not contiguous. |
| 473 | * @init_ack_masked: Ack all masked interrupts once during initalization. | ||
| 474 | * @mask_invert: Inverted mask register: cleared bits are masked out. | ||
| 475 | * @wake_invert: Inverted wake register: cleared bits are wake enabled. | ||
| 473 | * @runtime_pm: Hold a runtime PM lock on the device when accessing it. | 476 | * @runtime_pm: Hold a runtime PM lock on the device when accessing it. |
| 474 | * | 477 | * |
| 475 | * @num_regs: Number of registers in each control bank. | 478 | * @num_regs: Number of registers in each control bank. |
| @@ -485,9 +488,10 @@ struct regmap_irq_chip { | |||
| 485 | unsigned int ack_base; | 488 | unsigned int ack_base; |
| 486 | unsigned int wake_base; | 489 | unsigned int wake_base; |
| 487 | unsigned int irq_reg_stride; | 490 | unsigned int irq_reg_stride; |
| 488 | unsigned int mask_invert; | 491 | bool init_ack_masked:1; |
| 489 | unsigned int wake_invert; | 492 | bool mask_invert:1; |
| 490 | bool runtime_pm; | 493 | bool wake_invert:1; |
| 494 | bool runtime_pm:1; | ||
| 491 | 495 | ||
| 492 | int num_regs; | 496 | int num_regs; |
| 493 | 497 | ||
