aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 11:58:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 11:58:06 -0400
commitb34e5f55a1e6667a800280fc4045632c139b4e4e (patch)
treec7664dd3fe3a37f89394ae926c83fb859263b765
parente151960a23cc99e310f90adad7ee592821a77434 (diff)
parent613dac31a612f9417bd1b1438acebbc3b8f9073e (diff)
Merge tag 'regmap-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
Pull regmap updates from Mark Brown: "A quiet release for the regmap core, essentially all the activity is in the shared interrupt controller which is being more and more widely used and has been enhanced to support a wider range of masking types and wake handling methods, plus integration with runtime PM for devices making aggressive use of that." * tag 'regmap-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: regmap: no need primary handler for nested irq regmap: irq: Add mask invert flag for enable register mfd: wm8994: Flag the interrupt block as requiring runtime PM be enabled regmap: irq: Enable devices for runtime PM while handling interrupts regmap: irq: initialize all irqs to wake disabled regmap: set MASK_ON_SUSPEND/SKIP_SET_WAKE if no wake_base regmap: name irq_chip based on regmap_irq_chip's name regmap: store irq_chip inside regmap_irq_chip_data regmap: irq: Only update mask bits when doing initial mask regmap: fix some error messages to take account of irq_reg_stride regmap: Don't lock in regmap_reinit_cache()
-rw-r--r--drivers/base/regmap/regmap-irq.c92
-rw-r--r--drivers/base/regmap/regmap.c13
-rw-r--r--drivers/mfd/wm8994-irq.c1
-rw-r--r--include/linux/regmap.h3
4 files changed, 83 insertions, 26 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index a89734621e51..5b6b1d8e6cc0 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -16,12 +16,14 @@
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"
22 23
23struct regmap_irq_chip_data { 24struct regmap_irq_chip_data {
24 struct mutex lock; 25 struct mutex lock;
26 struct irq_chip irq_chip;
25 27
26 struct regmap *map; 28 struct regmap *map;
27 const struct regmap_irq_chip *chip; 29 const struct regmap_irq_chip *chip;
@@ -59,6 +61,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
59 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); 61 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
60 struct regmap *map = d->map; 62 struct regmap *map = d->map;
61 int i, ret; 63 int i, ret;
64 u32 reg;
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 }
62 72
63 /* 73 /*
64 * 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
@@ -66,15 +76,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
66 * suppress pointless writes. 76 * suppress pointless writes.
67 */ 77 */
68 for (i = 0; i < d->chip->num_regs; i++) { 78 for (i = 0; i < d->chip->num_regs; i++) {
69 ret = regmap_update_bits(d->map, d->chip->mask_base + 79 reg = d->chip->mask_base +
70 (i * map->reg_stride * 80 (i * map->reg_stride * d->irq_reg_stride);
71 d->irq_reg_stride), 81 if (d->chip->mask_invert)
82 ret = regmap_update_bits(d->map, reg,
83 d->mask_buf_def[i], ~d->mask_buf[i]);
84 else
85 ret = regmap_update_bits(d->map, reg,
72 d->mask_buf_def[i], d->mask_buf[i]); 86 d->mask_buf_def[i], d->mask_buf[i]);
73 if (ret != 0) 87 if (ret != 0)
74 dev_err(d->map->dev, "Failed to sync masks in %x\n", 88 dev_err(d->map->dev, "Failed to sync masks in %x\n",
75 d->chip->mask_base + (i * map->reg_stride)); 89 reg);
76 } 90 }
77 91
92 if (d->chip->runtime_pm)
93 pm_runtime_put(map->dev);
94
78 /* If we've changed our wakeup count propagate it to the parent */ 95 /* If we've changed our wakeup count propagate it to the parent */
79 if (d->wake_count < 0) 96 if (d->wake_count < 0)
80 for (i = d->wake_count; i < 0; i++) 97 for (i = d->wake_count; i < 0; i++)
@@ -128,8 +145,7 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
128 return 0; 145 return 0;
129} 146}
130 147
131static struct irq_chip regmap_irq_chip = { 148static const struct irq_chip regmap_irq_chip = {
132 .name = "regmap",
133 .irq_bus_lock = regmap_irq_lock, 149 .irq_bus_lock = regmap_irq_lock,
134 .irq_bus_sync_unlock = regmap_irq_sync_unlock, 150 .irq_bus_sync_unlock = regmap_irq_sync_unlock,
135 .irq_disable = regmap_irq_disable, 151 .irq_disable = regmap_irq_disable,
@@ -144,6 +160,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
144 struct regmap *map = data->map; 160 struct regmap *map = data->map;
145 int ret, i; 161 int ret, i;
146 bool handled = false; 162 bool handled = false;
163 u32 reg;
164
165 if (chip->runtime_pm) {
166 ret = pm_runtime_get_sync(map->dev);
167 if (ret < 0) {
168 dev_err(map->dev, "IRQ thread failed to resume: %d\n",
169 ret);
170 return IRQ_NONE;
171 }
172 }
147 173
148 /* 174 /*
149 * Ignore masked IRQs and ack if we need to; we ack early so 175 * Ignore masked IRQs and ack if we need to; we ack early so
@@ -160,20 +186,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
160 if (ret != 0) { 186 if (ret != 0) {
161 dev_err(map->dev, "Failed to read IRQ status: %d\n", 187 dev_err(map->dev, "Failed to read IRQ status: %d\n",
162 ret); 188 ret);
189 if (chip->runtime_pm)
190 pm_runtime_put(map->dev);
163 return IRQ_NONE; 191 return IRQ_NONE;
164 } 192 }
165 193
166 data->status_buf[i] &= ~data->mask_buf[i]; 194 data->status_buf[i] &= ~data->mask_buf[i];
167 195
168 if (data->status_buf[i] && chip->ack_base) { 196 if (data->status_buf[i] && chip->ack_base) {
169 ret = regmap_write(map, chip->ack_base + 197 reg = chip->ack_base +
170 (i * map->reg_stride * 198 (i * map->reg_stride * data->irq_reg_stride);
171 data->irq_reg_stride), 199 ret = regmap_write(map, reg, data->status_buf[i]);
172 data->status_buf[i]);
173 if (ret != 0) 200 if (ret != 0)
174 dev_err(map->dev, "Failed to ack 0x%x: %d\n", 201 dev_err(map->dev, "Failed to ack 0x%x: %d\n",
175 chip->ack_base + (i * map->reg_stride), 202 reg, ret);
176 ret);
177 } 203 }
178 } 204 }
179 205
@@ -185,6 +211,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
185 } 211 }
186 } 212 }
187 213
214 if (chip->runtime_pm)
215 pm_runtime_put(map->dev);
216
188 if (handled) 217 if (handled)
189 return IRQ_HANDLED; 218 return IRQ_HANDLED;
190 else 219 else
@@ -197,7 +226,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
197 struct regmap_irq_chip_data *data = h->host_data; 226 struct regmap_irq_chip_data *data = h->host_data;
198 227
199 irq_set_chip_data(virq, data); 228 irq_set_chip_data(virq, data);
200 irq_set_chip_and_handler(virq, &regmap_irq_chip, handle_edge_irq); 229 irq_set_chip(virq, &data->irq_chip);
201 irq_set_nested_thread(virq, 1); 230 irq_set_nested_thread(virq, 1);
202 231
203 /* ARM needs us to explicitly flag the IRQ as valid 232 /* ARM needs us to explicitly flag the IRQ as valid
@@ -238,6 +267,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
238 struct regmap_irq_chip_data *d; 267 struct regmap_irq_chip_data *d;
239 int i; 268 int i;
240 int ret = -ENOMEM; 269 int ret = -ENOMEM;
270 u32 reg;
241 271
242 for (i = 0; i < chip->num_irqs; i++) { 272 for (i = 0; i < chip->num_irqs; i++) {
243 if (chip->irqs[i].reg_offset % map->reg_stride) 273 if (chip->irqs[i].reg_offset % map->reg_stride)
@@ -284,6 +314,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
284 goto err_alloc; 314 goto err_alloc;
285 } 315 }
286 316
317 d->irq_chip = regmap_irq_chip;
318 d->irq_chip.name = chip->name;
319 if (!chip->wake_base) {
320 d->irq_chip.irq_set_wake = NULL;
321 d->irq_chip.flags |= IRQCHIP_MASK_ON_SUSPEND |
322 IRQCHIP_SKIP_SET_WAKE;
323 }
287 d->irq = irq; 324 d->irq = irq;
288 d->map = map; 325 d->map = map;
289 d->chip = chip; 326 d->chip = chip;
@@ -303,16 +340,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
303 /* Mask all the interrupts by default */ 340 /* Mask all the interrupts by default */
304 for (i = 0; i < chip->num_regs; i++) { 341 for (i = 0; i < chip->num_regs; i++) {
305 d->mask_buf[i] = d->mask_buf_def[i]; 342 d->mask_buf[i] = d->mask_buf_def[i];
306 ret = regmap_write(map, chip->mask_base + (i * map->reg_stride 343 reg = chip->mask_base +
307 * d->irq_reg_stride), 344 (i * map->reg_stride * d->irq_reg_stride);
308 d->mask_buf[i]); 345 if (chip->mask_invert)
346 ret = regmap_update_bits(map, reg,
347 d->mask_buf[i], ~d->mask_buf[i]);
348 else
349 ret = regmap_update_bits(map, reg,
350 d->mask_buf[i], d->mask_buf[i]);
309 if (ret != 0) { 351 if (ret != 0) {
310 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", 352 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
311 chip->mask_base + (i * map->reg_stride), ret); 353 reg, ret);
312 goto err_alloc; 354 goto err_alloc;
313 } 355 }
314 } 356 }
315 357
358 /* Wake is disabled by default */
359 if (d->wake_buf) {
360 for (i = 0; i < chip->num_regs; i++) {
361 d->wake_buf[i] = d->mask_buf_def[i];
362 reg = chip->wake_base +
363 (i * map->reg_stride * d->irq_reg_stride);
364 ret = regmap_update_bits(map, reg, d->wake_buf[i],
365 d->wake_buf[i]);
366 if (ret != 0) {
367 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
368 reg, ret);
369 goto err_alloc;
370 }
371 }
372 }
373
316 if (irq_base) 374 if (irq_base)
317 d->domain = irq_domain_add_legacy(map->dev->of_node, 375 d->domain = irq_domain_add_legacy(map->dev->of_node,
318 chip->num_irqs, irq_base, 0, 376 chip->num_irqs, irq_base, 0,
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index c241ae2f2f10..52069d29ff12 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -659,13 +659,12 @@ EXPORT_SYMBOL_GPL(devm_regmap_init);
659 * new cache. This can be used to restore the cache to defaults or to 659 * new cache. This can be used to restore the cache to defaults or to
660 * update the cache configuration to reflect runtime discovery of the 660 * update the cache configuration to reflect runtime discovery of the
661 * hardware. 661 * hardware.
662 *
663 * No explicit locking is done here, the user needs to ensure that
664 * this function will not race with other calls to regmap.
662 */ 665 */
663int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) 666int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
664{ 667{
665 int ret;
666
667 map->lock(map);
668
669 regcache_exit(map); 668 regcache_exit(map);
670 regmap_debugfs_exit(map); 669 regmap_debugfs_exit(map);
671 670
@@ -681,11 +680,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
681 map->cache_bypass = false; 680 map->cache_bypass = false;
682 map->cache_only = false; 681 map->cache_only = false;
683 682
684 ret = regcache_init(map, config); 683 return regcache_init(map, config);
685
686 map->unlock(map);
687
688 return ret;
689} 684}
690EXPORT_SYMBOL_GPL(regmap_reinit_cache); 685EXPORT_SYMBOL_GPL(regmap_reinit_cache);
691 686
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
index 0aac4aff17a5..a050e56a9bbd 100644
--- a/drivers/mfd/wm8994-irq.c
+++ b/drivers/mfd/wm8994-irq.c
@@ -135,6 +135,7 @@ static struct regmap_irq_chip wm8994_irq_chip = {
135 .status_base = WM8994_INTERRUPT_STATUS_1, 135 .status_base = WM8994_INTERRUPT_STATUS_1,
136 .mask_base = WM8994_INTERRUPT_STATUS_1_MASK, 136 .mask_base = WM8994_INTERRUPT_STATUS_1_MASK,
137 .ack_base = WM8994_INTERRUPT_STATUS_1, 137 .ack_base = WM8994_INTERRUPT_STATUS_1,
138 .runtime_pm = true,
138}; 139};
139 140
140int wm8994_irq_init(struct wm8994 *wm8994) 141int wm8994_irq_init(struct wm8994 *wm8994)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 7f7e00df3adf..e3bcc3f4dcb8 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -285,6 +285,7 @@ struct regmap_irq {
285 * @ack_base: Base ack address. If zero then the chip is clear on read. 285 * @ack_base: Base ack address. If zero then the chip is clear on read.
286 * @wake_base: Base address for wake enables. If zero unsupported. 286 * @wake_base: Base address for wake enables. If zero unsupported.
287 * @irq_reg_stride: Stride to use for chips where registers are not contiguous. 287 * @irq_reg_stride: Stride to use for chips where registers are not contiguous.
288 * @runtime_pm: Hold a runtime PM lock on the device when accessing it.
288 * 289 *
289 * @num_regs: Number of registers in each control bank. 290 * @num_regs: Number of registers in each control bank.
290 * @irqs: Descriptors for individual IRQs. Interrupt numbers are 291 * @irqs: Descriptors for individual IRQs. Interrupt numbers are
@@ -299,6 +300,8 @@ struct regmap_irq_chip {
299 unsigned int ack_base; 300 unsigned int ack_base;
300 unsigned int wake_base; 301 unsigned int wake_base;
301 unsigned int irq_reg_stride; 302 unsigned int irq_reg_stride;
303 unsigned int mask_invert;
304 bool runtime_pm;
302 305
303 int num_regs; 306 int num_regs;
304 307