diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 11:58:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 11:58:06 -0400 |
commit | b34e5f55a1e6667a800280fc4045632c139b4e4e (patch) | |
tree | c7664dd3fe3a37f89394ae926c83fb859263b765 | |
parent | e151960a23cc99e310f90adad7ee592821a77434 (diff) | |
parent | 613dac31a612f9417bd1b1438acebbc3b8f9073e (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.c | 92 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 13 | ||||
-rw-r--r-- | drivers/mfd/wm8994-irq.c | 1 | ||||
-rw-r--r-- | include/linux/regmap.h | 3 |
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 | ||
23 | struct regmap_irq_chip_data { | 24 | struct 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 | ||
131 | static struct irq_chip regmap_irq_chip = { | 148 | static 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, ®map_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 | */ |
663 | int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | 666 | int 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 | } |
690 | EXPORT_SYMBOL_GPL(regmap_reinit_cache); | 685 | EXPORT_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 | ||
140 | int wm8994_irq_init(struct wm8994 *wm8994) | 141 | int 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 | ||