diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2016-05-20 20:40:26 +0530 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-06-03 00:41:15 +0100 |
commit | ccc12561926c0bef9a40865db93b926a0927e93f (patch) | |
tree | 2034ef3c4af60b796092465a89cec69ff859f0a2 /drivers/base/regmap | |
parent | 1a695a905c18548062509178b98bc91e67510864 (diff) | |
download | linux-ccc12561926c0bef9a40865db93b926a0927e93f.tar.gz linux-ccc12561926c0bef9a40865db93b926a0927e93f.tar.bz2 linux-ccc12561926c0bef9a40865db93b926a0927e93f.zip |
regmap: irq: Add support to call client specific pre/post interrupt service
Regmap irq implements the generic interrupt service routine which
is common for most of devices. Some devices, like MAX77620, MAX20024
needs the special handling before and after servicing the interrupt
as generic. For the example, MAX77620 programming guidelines for
interrupt servicing says:
1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting
GLBLM.
2. Read IRQTOP and service the interrupt accordingly.
3. Once all interrupts has been checked and serviced, the interrupt
service routine un-masks the hardware interrupt line by clearing
GLBLM.
The step (2) is implemented in regmap irq as generic routine. For
step (1) and (3), add callbacks from regmap irq to client driver
to handle chip specific configurations.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r-- | drivers/base/regmap/regmap-irq.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 26f799e71c82..ec262476d043 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -268,13 +268,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) bool handled = false; u32 reg; + if (chip->handle_pre_irq) + chip->handle_pre_irq(chip->irq_drv_data); + if (chip->runtime_pm) { ret = pm_runtime_get_sync(map->dev); if (ret < 0) { dev_err(map->dev, "IRQ thread failed to resume: %d\n", ret); pm_runtime_put(map->dev); - return IRQ_NONE; + goto exit; } } @@ -296,7 +299,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) if (ret != 0) { dev_err(map->dev, "Failed to read IRQ status: %d\n", ret); - return IRQ_NONE; + goto exit; } for (i = 0; i < data->chip->num_regs; i++) { @@ -312,7 +315,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) break; default: BUG(); - return IRQ_NONE; + goto exit; } } @@ -329,7 +332,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) ret); if (chip->runtime_pm) pm_runtime_put(map->dev); - return IRQ_NONE; + goto exit; } } } @@ -365,6 +368,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) if (chip->runtime_pm) pm_runtime_put(map->dev); +exit: + if (chip->handle_post_irq) + chip->handle_post_irq(chip->irq_drv_data); + if (handled) return IRQ_HANDLED; else |