aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-07-24 10:41:19 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-08-07 15:29:45 -0400
commit0c00c50b41a9a6ee83eb16fb5c6c22e5115391b8 (patch)
tree12a30d730032a46fac0793fea2ba30ef900b4d4f /drivers/base/regmap
parent40052ca0c243d101cfadd65936f60ef81df10b02 (diff)
regmap: irq: Enable devices for runtime PM while handling interrupts
Some devices need to have a runtime PM reference while handling interrupts to ensure that the register I/O is available. Support this with a flag in the chip. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/regmap-irq.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 6f8f0c1e550f..bb5e10305197 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -16,6 +16,7 @@
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/irqdomain.h> 18#include <linux/irqdomain.h>
19#include <linux/pm_runtime.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
20 21
21#include "internal.h" 22#include "internal.h"
@@ -62,6 +63,13 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
62 int i, ret; 63 int i, ret;
63 u32 reg; 64 u32 reg;
64 65
66 if (d->chip->runtime_pm) {
67 ret = pm_runtime_get_sync(map->dev);
68 if (ret < 0)
69 dev_err(map->dev, "IRQ sync failed to resume: %d\n",
70 ret);
71 }
72
65 /* 73 /*
66 * If there's been a change in the mask write it back to the 74 * If there's been a change in the mask write it back to the
67 * hardware. We rely on the use of the regmap core cache to 75 * hardware. We rely on the use of the regmap core cache to
@@ -77,6 +85,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
77 reg); 85 reg);
78 } 86 }
79 87
88 if (d->chip->runtime_pm)
89 pm_runtime_put(map->dev);
90
80 /* If we've changed our wakeup count propagate it to the parent */ 91 /* If we've changed our wakeup count propagate it to the parent */
81 if (d->wake_count < 0) 92 if (d->wake_count < 0)
82 for (i = d->wake_count; i < 0; i++) 93 for (i = d->wake_count; i < 0; i++)
@@ -147,6 +158,15 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
147 bool handled = false; 158 bool handled = false;
148 u32 reg; 159 u32 reg;
149 160
161 if (chip->runtime_pm) {
162 ret = pm_runtime_get_sync(map->dev);
163 if (ret < 0) {
164 dev_err(map->dev, "IRQ thread failed to resume: %d\n",
165 ret);
166 return IRQ_NONE;
167 }
168 }
169
150 /* 170 /*
151 * Ignore masked IRQs and ack if we need to; we ack early so 171 * Ignore masked IRQs and ack if we need to; we ack early so
152 * there is no race between handling and acknowleding the 172 * there is no race between handling and acknowleding the
@@ -162,6 +182,8 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
162 if (ret != 0) { 182 if (ret != 0) {
163 dev_err(map->dev, "Failed to read IRQ status: %d\n", 183 dev_err(map->dev, "Failed to read IRQ status: %d\n",
164 ret); 184 ret);
185 if (chip->runtime_pm)
186 pm_runtime_put(map->dev);
165 return IRQ_NONE; 187 return IRQ_NONE;
166 } 188 }
167 189
@@ -185,6 +207,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
185 } 207 }
186 } 208 }
187 209
210 if (chip->runtime_pm)
211 pm_runtime_put(map->dev);
212
188 if (handled) 213 if (handled)
189 return IRQ_HANDLED; 214 return IRQ_HANDLED;
190 else 215 else