Commit 5dea215028686a67e815c32a54dc89fb3467ab05
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge remote-tracking branch 'regmap/topic/irq' into regmap-next
Showing 4 changed files Side-by-side Diff
drivers/base/regmap/regmap-irq.c
... | ... | @@ -34,6 +34,7 @@ |
34 | 34 | int irq; |
35 | 35 | int wake_count; |
36 | 36 | |
37 | + void *status_reg_buf; | |
37 | 38 | unsigned int *status_buf; |
38 | 39 | unsigned int *mask_buf; |
39 | 40 | unsigned int *mask_buf_def; |
... | ... | @@ -87,6 +88,23 @@ |
87 | 88 | if (ret != 0) |
88 | 89 | dev_err(d->map->dev, "Failed to sync masks in %x\n", |
89 | 90 | reg); |
91 | + | |
92 | + reg = d->chip->wake_base + | |
93 | + (i * map->reg_stride * d->irq_reg_stride); | |
94 | + if (d->wake_buf) { | |
95 | + if (d->chip->wake_invert) | |
96 | + ret = regmap_update_bits(d->map, reg, | |
97 | + d->mask_buf_def[i], | |
98 | + ~d->wake_buf[i]); | |
99 | + else | |
100 | + ret = regmap_update_bits(d->map, reg, | |
101 | + d->mask_buf_def[i], | |
102 | + d->wake_buf[i]); | |
103 | + if (ret != 0) | |
104 | + dev_err(d->map->dev, | |
105 | + "Failed to sync wakes in %x: %d\n", | |
106 | + reg, ret); | |
107 | + } | |
90 | 108 | } |
91 | 109 | |
92 | 110 | if (d->chip->runtime_pm) |
93 | 111 | |
94 | 112 | |
... | ... | @@ -129,16 +147,15 @@ |
129 | 147 | struct regmap *map = d->map; |
130 | 148 | const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); |
131 | 149 | |
132 | - if (!d->chip->wake_base) | |
133 | - return -EINVAL; | |
134 | - | |
135 | 150 | if (on) { |
136 | - d->wake_buf[irq_data->reg_offset / map->reg_stride] | |
137 | - &= ~irq_data->mask; | |
151 | + if (d->wake_buf) | |
152 | + d->wake_buf[irq_data->reg_offset / map->reg_stride] | |
153 | + &= ~irq_data->mask; | |
138 | 154 | d->wake_count++; |
139 | 155 | } else { |
140 | - d->wake_buf[irq_data->reg_offset / map->reg_stride] | |
141 | - |= irq_data->mask; | |
156 | + if (d->wake_buf) | |
157 | + d->wake_buf[irq_data->reg_offset / map->reg_stride] | |
158 | + |= irq_data->mask; | |
142 | 159 | d->wake_count--; |
143 | 160 | } |
144 | 161 | |
145 | 162 | |
146 | 163 | |
147 | 164 | |
148 | 165 | |
... | ... | @@ -172,25 +189,69 @@ |
172 | 189 | } |
173 | 190 | |
174 | 191 | /* |
175 | - * Ignore masked IRQs and ack if we need to; we ack early so | |
176 | - * there is no race between handling and acknowleding the | |
177 | - * interrupt. We assume that typically few of the interrupts | |
178 | - * will fire simultaneously so don't worry about overhead from | |
179 | - * doing a write per register. | |
192 | + * Read in the statuses, using a single bulk read if possible | |
193 | + * in order to reduce the I/O overheads. | |
180 | 194 | */ |
181 | - for (i = 0; i < data->chip->num_regs; i++) { | |
182 | - ret = regmap_read(map, chip->status_base + (i * map->reg_stride | |
183 | - * data->irq_reg_stride), | |
184 | - &data->status_buf[i]); | |
195 | + if (!map->use_single_rw && map->reg_stride == 1 && | |
196 | + data->irq_reg_stride == 1) { | |
197 | + u8 *buf8 = data->status_reg_buf; | |
198 | + u16 *buf16 = data->status_reg_buf; | |
199 | + u32 *buf32 = data->status_reg_buf; | |
185 | 200 | |
201 | + BUG_ON(!data->status_reg_buf); | |
202 | + | |
203 | + ret = regmap_bulk_read(map, chip->status_base, | |
204 | + data->status_reg_buf, | |
205 | + chip->num_regs); | |
186 | 206 | if (ret != 0) { |
187 | 207 | dev_err(map->dev, "Failed to read IRQ status: %d\n", |
188 | - ret); | |
189 | - if (chip->runtime_pm) | |
190 | - pm_runtime_put(map->dev); | |
208 | + ret); | |
191 | 209 | return IRQ_NONE; |
192 | 210 | } |
193 | 211 | |
212 | + for (i = 0; i < data->chip->num_regs; i++) { | |
213 | + switch (map->format.val_bytes) { | |
214 | + case 1: | |
215 | + data->status_buf[i] = buf8[i]; | |
216 | + break; | |
217 | + case 2: | |
218 | + data->status_buf[i] = buf16[i]; | |
219 | + break; | |
220 | + case 4: | |
221 | + data->status_buf[i] = buf32[i]; | |
222 | + break; | |
223 | + default: | |
224 | + BUG(); | |
225 | + return IRQ_NONE; | |
226 | + } | |
227 | + } | |
228 | + | |
229 | + } else { | |
230 | + for (i = 0; i < data->chip->num_regs; i++) { | |
231 | + ret = regmap_read(map, chip->status_base + | |
232 | + (i * map->reg_stride | |
233 | + * data->irq_reg_stride), | |
234 | + &data->status_buf[i]); | |
235 | + | |
236 | + if (ret != 0) { | |
237 | + dev_err(map->dev, | |
238 | + "Failed to read IRQ status: %d\n", | |
239 | + ret); | |
240 | + if (chip->runtime_pm) | |
241 | + pm_runtime_put(map->dev); | |
242 | + return IRQ_NONE; | |
243 | + } | |
244 | + } | |
245 | + } | |
246 | + | |
247 | + /* | |
248 | + * Ignore masked IRQs and ack if we need to; we ack early so | |
249 | + * there is no race between handling and acknowleding the | |
250 | + * interrupt. We assume that typically few of the interrupts | |
251 | + * will fire simultaneously so don't worry about overhead from | |
252 | + * doing a write per register. | |
253 | + */ | |
254 | + for (i = 0; i < data->chip->num_regs; i++) { | |
194 | 255 | data->status_buf[i] &= ~data->mask_buf[i]; |
195 | 256 | |
196 | 257 | if (data->status_buf[i] && chip->ack_base) { |
... | ... | @@ -316,11 +377,6 @@ |
316 | 377 | |
317 | 378 | d->irq_chip = regmap_irq_chip; |
318 | 379 | 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 | - } | |
324 | 380 | d->irq = irq; |
325 | 381 | d->map = map; |
326 | 382 | d->chip = chip; |
... | ... | @@ -331,6 +387,14 @@ |
331 | 387 | else |
332 | 388 | d->irq_reg_stride = 1; |
333 | 389 | |
390 | + if (!map->use_single_rw && map->reg_stride == 1 && | |
391 | + d->irq_reg_stride == 1) { | |
392 | + d->status_reg_buf = kmalloc(map->format.val_bytes * | |
393 | + chip->num_regs, GFP_KERNEL); | |
394 | + if (!d->status_reg_buf) | |
395 | + goto err_alloc; | |
396 | + } | |
397 | + | |
334 | 398 | mutex_init(&d->lock); |
335 | 399 | |
336 | 400 | for (i = 0; i < chip->num_irqs; i++) |
... | ... | @@ -361,8 +425,15 @@ |
361 | 425 | d->wake_buf[i] = d->mask_buf_def[i]; |
362 | 426 | reg = chip->wake_base + |
363 | 427 | (i * map->reg_stride * d->irq_reg_stride); |
364 | - ret = regmap_update_bits(map, reg, d->wake_buf[i], | |
365 | - d->wake_buf[i]); | |
428 | + | |
429 | + if (chip->wake_invert) | |
430 | + ret = regmap_update_bits(map, reg, | |
431 | + d->mask_buf_def[i], | |
432 | + 0); | |
433 | + else | |
434 | + ret = regmap_update_bits(map, reg, | |
435 | + d->mask_buf_def[i], | |
436 | + d->wake_buf[i]); | |
366 | 437 | if (ret != 0) { |
367 | 438 | dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", |
368 | 439 | reg, ret); |
... | ... | @@ -401,6 +472,7 @@ |
401 | 472 | kfree(d->mask_buf_def); |
402 | 473 | kfree(d->mask_buf); |
403 | 474 | kfree(d->status_buf); |
475 | + kfree(d->status_reg_buf); | |
404 | 476 | kfree(d); |
405 | 477 | return ret; |
406 | 478 | } |
... | ... | @@ -422,6 +494,7 @@ |
422 | 494 | kfree(d->wake_buf); |
423 | 495 | kfree(d->mask_buf_def); |
424 | 496 | kfree(d->mask_buf); |
497 | + kfree(d->status_reg_buf); | |
425 | 498 | kfree(d->status_buf); |
426 | 499 | kfree(d); |
427 | 500 | } |
drivers/mfd/wm5102-tables.c
drivers/mfd/wm5110-tables.c