aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regmap-irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/regmap/regmap-irq.c')
-rw-r--r--drivers/base/regmap/regmap-irq.c126
1 files changed, 100 insertions, 26 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 5972ad958544..020ea2b9fd2f 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -34,6 +34,7 @@ struct regmap_irq_chip_data {
34 int irq; 34 int irq;
35 int wake_count; 35 int wake_count;
36 36
37 void *status_reg_buf;
37 unsigned int *status_buf; 38 unsigned int *status_buf;
38 unsigned int *mask_buf; 39 unsigned int *mask_buf;
39 unsigned int *mask_buf_def; 40 unsigned int *mask_buf_def;
@@ -87,6 +88,23 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
87 if (ret != 0) 88 if (ret != 0)
88 dev_err(d->map->dev, "Failed to sync masks in %x\n", 89 dev_err(d->map->dev, "Failed to sync masks in %x\n",
89 reg); 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 if (d->chip->runtime_pm) 110 if (d->chip->runtime_pm)
@@ -129,16 +147,15 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
129 struct regmap *map = d->map; 147 struct regmap *map = d->map;
130 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); 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 if (on) { 150 if (on) {
136 d->wake_buf[irq_data->reg_offset / map->reg_stride] 151 if (d->wake_buf)
137 &= ~irq_data->mask; 152 d->wake_buf[irq_data->reg_offset / map->reg_stride]
153 &= ~irq_data->mask;
138 d->wake_count++; 154 d->wake_count++;
139 } else { 155 } else {
140 d->wake_buf[irq_data->reg_offset / map->reg_stride] 156 if (d->wake_buf)
141 |= irq_data->mask; 157 d->wake_buf[irq_data->reg_offset / map->reg_stride]
158 |= irq_data->mask;
142 d->wake_count--; 159 d->wake_count--;
143 } 160 }
144 161
@@ -167,30 +184,75 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
167 if (ret < 0) { 184 if (ret < 0) {
168 dev_err(map->dev, "IRQ thread failed to resume: %d\n", 185 dev_err(map->dev, "IRQ thread failed to resume: %d\n",
169 ret); 186 ret);
187 pm_runtime_put(map->dev);
170 return IRQ_NONE; 188 return IRQ_NONE;
171 } 189 }
172 } 190 }
173 191
174 /* 192 /*
175 * Ignore masked IRQs and ack if we need to; we ack early so 193 * Read in the statuses, using a single bulk read if possible
176 * there is no race between handling and acknowleding the 194 * in order to reduce the I/O overheads.
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.
180 */ 195 */
181 for (i = 0; i < data->chip->num_regs; i++) { 196 if (!map->use_single_rw && map->reg_stride == 1 &&
182 ret = regmap_read(map, chip->status_base + (i * map->reg_stride 197 data->irq_reg_stride == 1) {
183 * data->irq_reg_stride), 198 u8 *buf8 = data->status_reg_buf;
184 &data->status_buf[i]); 199 u16 *buf16 = data->status_reg_buf;
200 u32 *buf32 = data->status_reg_buf;
185 201
202 BUG_ON(!data->status_reg_buf);
203
204 ret = regmap_bulk_read(map, chip->status_base,
205 data->status_reg_buf,
206 chip->num_regs);
186 if (ret != 0) { 207 if (ret != 0) {
187 dev_err(map->dev, "Failed to read IRQ status: %d\n", 208 dev_err(map->dev, "Failed to read IRQ status: %d\n",
188 ret); 209 ret);
189 if (chip->runtime_pm)
190 pm_runtime_put(map->dev);
191 return IRQ_NONE; 210 return IRQ_NONE;
192 } 211 }
193 212
213 for (i = 0; i < data->chip->num_regs; i++) {
214 switch (map->format.val_bytes) {
215 case 1:
216 data->status_buf[i] = buf8[i];
217 break;
218 case 2:
219 data->status_buf[i] = buf16[i];
220 break;
221 case 4:
222 data->status_buf[i] = buf32[i];
223 break;
224 default:
225 BUG();
226 return IRQ_NONE;
227 }
228 }
229
230 } else {
231 for (i = 0; i < data->chip->num_regs; i++) {
232 ret = regmap_read(map, chip->status_base +
233 (i * map->reg_stride
234 * data->irq_reg_stride),
235 &data->status_buf[i]);
236
237 if (ret != 0) {
238 dev_err(map->dev,
239 "Failed to read IRQ status: %d\n",
240 ret);
241 if (chip->runtime_pm)
242 pm_runtime_put(map->dev);
243 return IRQ_NONE;
244 }
245 }
246 }
247
248 /*
249 * Ignore masked IRQs and ack if we need to; we ack early so
250 * there is no race between handling and acknowleding the
251 * interrupt. We assume that typically few of the interrupts
252 * will fire simultaneously so don't worry about overhead from
253 * doing a write per register.
254 */
255 for (i = 0; i < data->chip->num_regs; i++) {
194 data->status_buf[i] &= ~data->mask_buf[i]; 256 data->status_buf[i] &= ~data->mask_buf[i];
195 257
196 if (data->status_buf[i] && chip->ack_base) { 258 if (data->status_buf[i] && chip->ack_base) {
@@ -316,11 +378,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
316 378
317 d->irq_chip = regmap_irq_chip; 379 d->irq_chip = regmap_irq_chip;
318 d->irq_chip.name = chip->name; 380 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 d->irq = irq; 381 d->irq = irq;
325 d->map = map; 382 d->map = map;
326 d->chip = chip; 383 d->chip = chip;
@@ -331,6 +388,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
331 else 388 else
332 d->irq_reg_stride = 1; 389 d->irq_reg_stride = 1;
333 390
391 if (!map->use_single_rw && map->reg_stride == 1 &&
392 d->irq_reg_stride == 1) {
393 d->status_reg_buf = kmalloc(map->format.val_bytes *
394 chip->num_regs, GFP_KERNEL);
395 if (!d->status_reg_buf)
396 goto err_alloc;
397 }
398
334 mutex_init(&d->lock); 399 mutex_init(&d->lock);
335 400
336 for (i = 0; i < chip->num_irqs; i++) 401 for (i = 0; i < chip->num_irqs; i++)
@@ -361,8 +426,15 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
361 d->wake_buf[i] = d->mask_buf_def[i]; 426 d->wake_buf[i] = d->mask_buf_def[i];
362 reg = chip->wake_base + 427 reg = chip->wake_base +
363 (i * map->reg_stride * d->irq_reg_stride); 428 (i * map->reg_stride * d->irq_reg_stride);
364 ret = regmap_update_bits(map, reg, d->wake_buf[i], 429
365 d->wake_buf[i]); 430 if (chip->wake_invert)
431 ret = regmap_update_bits(map, reg,
432 d->mask_buf_def[i],
433 0);
434 else
435 ret = regmap_update_bits(map, reg,
436 d->mask_buf_def[i],
437 d->wake_buf[i]);
366 if (ret != 0) { 438 if (ret != 0) {
367 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", 439 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
368 reg, ret); 440 reg, ret);
@@ -401,6 +473,7 @@ err_alloc:
401 kfree(d->mask_buf_def); 473 kfree(d->mask_buf_def);
402 kfree(d->mask_buf); 474 kfree(d->mask_buf);
403 kfree(d->status_buf); 475 kfree(d->status_buf);
476 kfree(d->status_reg_buf);
404 kfree(d); 477 kfree(d);
405 return ret; 478 return ret;
406} 479}
@@ -422,6 +495,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
422 kfree(d->wake_buf); 495 kfree(d->wake_buf);
423 kfree(d->mask_buf_def); 496 kfree(d->mask_buf_def);
424 kfree(d->mask_buf); 497 kfree(d->mask_buf);
498 kfree(d->status_reg_buf);
425 kfree(d->status_buf); 499 kfree(d->status_buf);
426 kfree(d); 500 kfree(d);
427} 501}