aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/wm831x-core.c9
-rw-r--r--drivers/mfd/wm831x-irq.c209
-rw-r--r--include/linux/mfd/wm831x/core.h40
-rw-r--r--include/linux/mfd/wm831x/pdata.h1
4 files changed, 122 insertions, 137 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 163029f06185..223a90c7492f 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -1504,19 +1504,19 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1504 case WM8310: 1504 case WM8310:
1505 ret = mfd_add_devices(wm831x->dev, -1, 1505 ret = mfd_add_devices(wm831x->dev, -1,
1506 wm8310_devs, ARRAY_SIZE(wm8310_devs), 1506 wm8310_devs, ARRAY_SIZE(wm8310_devs),
1507 NULL, 0); 1507 NULL, wm831x->irq_base);
1508 break; 1508 break;
1509 1509
1510 case WM8311: 1510 case WM8311:
1511 ret = mfd_add_devices(wm831x->dev, -1, 1511 ret = mfd_add_devices(wm831x->dev, -1,
1512 wm8311_devs, ARRAY_SIZE(wm8311_devs), 1512 wm8311_devs, ARRAY_SIZE(wm8311_devs),
1513 NULL, 0); 1513 NULL, wm831x->irq_base);
1514 break; 1514 break;
1515 1515
1516 case WM8312: 1516 case WM8312:
1517 ret = mfd_add_devices(wm831x->dev, -1, 1517 ret = mfd_add_devices(wm831x->dev, -1,
1518 wm8312_devs, ARRAY_SIZE(wm8312_devs), 1518 wm8312_devs, ARRAY_SIZE(wm8312_devs),
1519 NULL, 0); 1519 NULL, wm831x->irq_base);
1520 break; 1520 break;
1521 1521
1522 case WM8320: 1522 case WM8320:
@@ -1538,7 +1538,8 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1538 if (pdata && pdata->backlight) { 1538 if (pdata && pdata->backlight) {
1539 /* Treat errors as non-critical */ 1539 /* Treat errors as non-critical */
1540 ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, 1540 ret = mfd_add_devices(wm831x->dev, -1, backlight_devs,
1541 ARRAY_SIZE(backlight_devs), NULL, 0); 1541 ARRAY_SIZE(backlight_devs), NULL,
1542 wm831x->irq_base);
1542 if (ret < 0) 1543 if (ret < 0)
1543 dev_err(wm831x->dev, "Failed to add backlight: %d\n", 1544 dev_err(wm831x->dev, "Failed to add backlight: %d\n",
1544 ret); 1545 ret);
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index ac056ea6b66e..301327697117 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -15,6 +15,7 @@
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/i2c.h> 17#include <linux/i2c.h>
18#include <linux/irq.h>
18#include <linux/mfd/core.h> 19#include <linux/mfd/core.h>
19#include <linux/interrupt.h> 20#include <linux/interrupt.h>
20 21
@@ -339,110 +340,71 @@ static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data)
339 return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg; 340 return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
340} 341}
341 342
342static void __wm831x_enable_irq(struct wm831x *wm831x, int irq) 343static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x,
344 int irq)
343{ 345{
344 struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; 346 return &wm831x_irqs[irq - wm831x->irq_base];
345
346 wm831x->irq_masks[irq_data->reg - 1] &= ~irq_data->mask;
347 wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data),
348 wm831x->irq_masks[irq_data->reg - 1]);
349} 347}
350 348
351void wm831x_enable_irq(struct wm831x *wm831x, int irq) 349static void wm831x_irq_lock(unsigned int irq)
352{ 350{
353 mutex_lock(&wm831x->irq_lock); 351 struct wm831x *wm831x = get_irq_chip_data(irq);
354 __wm831x_enable_irq(wm831x, irq);
355 mutex_unlock(&wm831x->irq_lock);
356}
357EXPORT_SYMBOL_GPL(wm831x_enable_irq);
358 352
359static void __wm831x_disable_irq(struct wm831x *wm831x, int irq)
360{
361 struct wm831x_irq_data *irq_data = &wm831x_irqs[irq];
362
363 wm831x->irq_masks[irq_data->reg - 1] |= irq_data->mask;
364 wm831x_reg_write(wm831x, irq_data_to_mask_reg(irq_data),
365 wm831x->irq_masks[irq_data->reg - 1]);
366}
367
368void wm831x_disable_irq(struct wm831x *wm831x, int irq)
369{
370 mutex_lock(&wm831x->irq_lock); 353 mutex_lock(&wm831x->irq_lock);
371 __wm831x_disable_irq(wm831x, irq);
372 mutex_unlock(&wm831x->irq_lock);
373} 354}
374EXPORT_SYMBOL_GPL(wm831x_disable_irq);
375 355
376int wm831x_request_irq(struct wm831x *wm831x, 356static void wm831x_irq_sync_unlock(unsigned int irq)
377 unsigned int irq, irq_handler_t handler,
378 unsigned long flags, const char *name,
379 void *dev)
380{ 357{
381 int ret = 0; 358 struct wm831x *wm831x = get_irq_chip_data(irq);
382 359 int i;
383 if (irq < 0 || irq >= WM831X_NUM_IRQS) 360
384 return -EINVAL; 361 for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
385 362 /* If there's been a change in the mask write it back
386 mutex_lock(&wm831x->irq_lock); 363 * to the hardware. */
387 364 if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
388 if (wm831x_irqs[irq].handler) { 365 wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
389 dev_err(wm831x->dev, "Already have handler for IRQ %d\n", irq); 366 wm831x_reg_write(wm831x,
390 ret = -EINVAL; 367 WM831X_INTERRUPT_STATUS_1_MASK + i,
391 goto out; 368 wm831x->irq_masks_cur[i]);
369 }
392 } 370 }
393 371
394 wm831x_irqs[irq].handler = handler;
395 wm831x_irqs[irq].handler_data = dev;
396
397 __wm831x_enable_irq(wm831x, irq);
398
399out:
400 mutex_unlock(&wm831x->irq_lock); 372 mutex_unlock(&wm831x->irq_lock);
401
402 return ret;
403} 373}
404EXPORT_SYMBOL_GPL(wm831x_request_irq);
405 374
406void wm831x_free_irq(struct wm831x *wm831x, unsigned int irq, void *data) 375static void wm831x_irq_unmask(unsigned int irq)
407{ 376{
408 if (irq < 0 || irq >= WM831X_NUM_IRQS) 377 struct wm831x *wm831x = get_irq_chip_data(irq);
409 return; 378 struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
410
411 mutex_lock(&wm831x->irq_lock);
412 379
413 wm831x_irqs[irq].handler = NULL; 380 wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
414 wm831x_irqs[irq].handler_data = NULL;
415
416 __wm831x_disable_irq(wm831x, irq);
417
418 mutex_unlock(&wm831x->irq_lock);
419} 381}
420EXPORT_SYMBOL_GPL(wm831x_free_irq);
421 382
422 383static void wm831x_irq_mask(unsigned int irq)
423static void wm831x_handle_irq(struct wm831x *wm831x, int irq, int status)
424{ 384{
425 struct wm831x_irq_data *irq_data = &wm831x_irqs[irq]; 385 struct wm831x *wm831x = get_irq_chip_data(irq);
426 386 struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
427 if (irq_data->handler) { 387
428 irq_data->handler(irq, irq_data->handler_data); 388 wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
429 wm831x_reg_write(wm831x, irq_data_to_status_reg(irq_data),
430 irq_data->mask);
431 } else {
432 dev_err(wm831x->dev, "Unhandled IRQ %d, masking\n", irq);
433 __wm831x_disable_irq(wm831x, irq);
434 }
435} 389}
436 390
437/* Main interrupt handling occurs in a workqueue since we need 391static struct irq_chip wm831x_irq_chip = {
438 * interrupts enabled to interact with the chip. */ 392 .name = "wm831x",
439static void wm831x_irq_worker(struct work_struct *work) 393 .bus_lock = wm831x_irq_lock,
394 .bus_sync_unlock = wm831x_irq_sync_unlock,
395 .mask = wm831x_irq_mask,
396 .unmask = wm831x_irq_unmask,
397};
398
399/* The processing of the primary interrupt occurs in a thread so that
400 * we can interact with the device over I2C or SPI. */
401static irqreturn_t wm831x_irq_thread(int irq, void *data)
440{ 402{
441 struct wm831x *wm831x = container_of(work, struct wm831x, irq_work); 403 struct wm831x *wm831x = data;
442 unsigned int i; 404 unsigned int i;
443 int primary; 405 int primary;
444 int status_regs[5]; 406 int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
445 int read[5] = { 0 }; 407 int read[WM831X_NUM_IRQ_REGS] = { 0 };
446 int *status; 408 int *status;
447 409
448 primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS); 410 primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS);
@@ -452,8 +414,6 @@ static void wm831x_irq_worker(struct work_struct *work)
452 goto out; 414 goto out;
453 } 415 }
454 416
455 mutex_lock(&wm831x->irq_lock);
456
457 for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { 417 for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
458 int offset = wm831x_irqs[i].reg - 1; 418 int offset = wm831x_irqs[i].reg - 1;
459 419
@@ -471,41 +431,34 @@ static void wm831x_irq_worker(struct work_struct *work)
471 dev_err(wm831x->dev, 431 dev_err(wm831x->dev,
472 "Failed to read IRQ status: %d\n", 432 "Failed to read IRQ status: %d\n",
473 *status); 433 *status);
474 goto out_lock; 434 goto out;
475 } 435 }
476 436
477 /* Mask out the disabled IRQs */
478 *status &= ~wm831x->irq_masks[offset];
479 read[offset] = 1; 437 read[offset] = 1;
480 } 438 }
481 439
482 if (*status & wm831x_irqs[i].mask) 440 /* Report it if it isn't masked, or forget the status. */
483 wm831x_handle_irq(wm831x, i, *status); 441 if ((*status & ~wm831x->irq_masks_cur[offset])
442 & wm831x_irqs[i].mask)
443 handle_nested_irq(wm831x->irq_base + i);
444 else
445 *status &= ~wm831x_irqs[i].mask;
484 } 446 }
485 447
486out_lock:
487 mutex_unlock(&wm831x->irq_lock);
488out: 448out:
489 enable_irq(wm831x->irq); 449 for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
490} 450 if (status_regs[i])
491 451 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
492 452 status_regs[i]);
493static irqreturn_t wm831x_cpu_irq(int irq, void *data) 453 }
494{
495 struct wm831x *wm831x = data;
496
497 /* Shut the interrupt to the CPU up and schedule the actual
498 * handler; we can't check that the IRQ is asserted. */
499 disable_irq_nosync(irq);
500
501 queue_work(wm831x->irq_wq, &wm831x->irq_work);
502 454
503 return IRQ_HANDLED; 455 return IRQ_HANDLED;
504} 456}
505 457
506int wm831x_irq_init(struct wm831x *wm831x, int irq) 458int wm831x_irq_init(struct wm831x *wm831x, int irq)
507{ 459{
508 int i, ret; 460 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
461 int i, cur_irq, ret;
509 462
510 mutex_init(&wm831x->irq_lock); 463 mutex_init(&wm831x->irq_lock);
511 464
@@ -515,41 +468,53 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
515 return 0; 468 return 0;
516 } 469 }
517 470
518 471 if (!pdata || !pdata->irq_base) {
519 wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq"); 472 dev_err(wm831x->dev,
520 if (!wm831x->irq_wq) { 473 "No interrupt base specified, no interrupts\n");
521 dev_err(wm831x->dev, "Failed to allocate IRQ worker\n"); 474 return 0;
522 return -ESRCH;
523 } 475 }
524 476
525 wm831x->irq = irq; 477 wm831x->irq = irq;
526 INIT_WORK(&wm831x->irq_work, wm831x_irq_worker); 478 wm831x->irq_base = pdata->irq_base;
527 479
528 /* Mask the individual interrupt sources */ 480 /* Mask the individual interrupt sources */
529 for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks); i++) { 481 for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
530 wm831x->irq_masks[i] = 0xffff; 482 wm831x->irq_masks_cur[i] = 0xffff;
483 wm831x->irq_masks_cache[i] = 0xffff;
531 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, 484 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i,
532 0xffff); 485 0xffff);
533 } 486 }
534 487
535 /* Enable top level interrupts, we mask at secondary level */ 488 /* Register them with genirq */
536 wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); 489 for (cur_irq = wm831x->irq_base;
490 cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
491 cur_irq++) {
492 set_irq_chip_data(cur_irq, wm831x);
493 set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip,
494 handle_edge_irq);
495 set_irq_nested_thread(cur_irq, 1);
496
497 /* ARM needs us to explicitly flag the IRQ as valid
498 * and will set them noprobe when we do so. */
499#ifdef CONFIG_ARM
500 set_irq_flags(cur_irq, IRQF_VALID);
501#else
502 set_irq_noprobe(cur_irq);
503#endif
504 }
537 505
538 /* We're good to go. We set IRQF_SHARED since there's a 506 ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
539 * chance the driver will interoperate with another driver but 507 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
540 * the need to disable the IRQ while handing via I2C/SPI means 508 "wm831x", wm831x);
541 * that this may break and performance will be impacted. If
542 * this does happen it's a hardware design issue and the only
543 * other alternative would be polling.
544 */
545 ret = request_irq(irq, wm831x_cpu_irq, IRQF_TRIGGER_LOW | IRQF_SHARED,
546 "wm831x", wm831x);
547 if (ret != 0) { 509 if (ret != 0) {
548 dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n", 510 dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
549 irq, ret); 511 irq, ret);
550 return ret; 512 return ret;
551 } 513 }
552 514
515 /* Enable top level interrupts, we mask at secondary level */
516 wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
517
553 return 0; 518 return 0;
554} 519}
555 520
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index d01d293a6b25..5184b79c700b 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -16,7 +16,6 @@
16#define __MFD_WM831X_CORE_H__ 16#define __MFD_WM831X_CORE_H__
17 17
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/workqueue.h>
20 19
21/* 20/*
22 * Register values. 21 * Register values.
@@ -236,6 +235,8 @@
236 235
237struct regulator_dev; 236struct regulator_dev;
238 237
238#define WM831X_NUM_IRQ_REGS 5
239
239struct wm831x { 240struct wm831x {
240 struct mutex io_lock; 241 struct mutex io_lock;
241 242
@@ -249,10 +250,9 @@ struct wm831x {
249 250
250 int irq; /* Our chip IRQ */ 251 int irq; /* Our chip IRQ */
251 struct mutex irq_lock; 252 struct mutex irq_lock;
252 struct workqueue_struct *irq_wq;
253 struct work_struct irq_work;
254 unsigned int irq_base; 253 unsigned int irq_base;
255 int irq_masks[5]; 254 int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
255 int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
256 256
257 int num_gpio; 257 int num_gpio;
258 258
@@ -281,12 +281,30 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
281int wm831x_irq_init(struct wm831x *wm831x, int irq); 281int wm831x_irq_init(struct wm831x *wm831x, int irq);
282void wm831x_irq_exit(struct wm831x *wm831x); 282void wm831x_irq_exit(struct wm831x *wm831x);
283 283
284int __must_check wm831x_request_irq(struct wm831x *wm831x, 284static inline int __must_check wm831x_request_irq(struct wm831x *wm831x,
285 unsigned int irq, irq_handler_t handler, 285 unsigned int irq,
286 unsigned long flags, const char *name, 286 irq_handler_t handler,
287 void *dev); 287 unsigned long flags,
288void wm831x_free_irq(struct wm831x *wm831x, unsigned int, void *); 288 const char *name,
289void wm831x_disable_irq(struct wm831x *wm831x, int irq); 289 void *dev)
290void wm831x_enable_irq(struct wm831x *wm831x, int irq); 290{
291 return request_threaded_irq(irq, NULL, handler, flags, name, dev);
292}
293
294static inline void wm831x_free_irq(struct wm831x *wm831x,
295 unsigned int irq, void *dev)
296{
297 free_irq(irq, dev);
298}
299
300static inline void wm831x_disable_irq(struct wm831x *wm831x, int irq)
301{
302 disable_irq(irq);
303}
304
305static inline void wm831x_enable_irq(struct wm831x *wm831x, int irq)
306{
307 enable_irq(irq);
308}
291 309
292#endif 310#endif
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index 90d820260aad..415c228743d5 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -91,6 +91,7 @@ struct wm831x_pdata {
91 /** Called after subdevices are set up */ 91 /** Called after subdevices are set up */
92 int (*post_init)(struct wm831x *wm831x); 92 int (*post_init)(struct wm831x *wm831x);
93 93
94 int irq_base;
94 int gpio_base; 95 int gpio_base;
95 struct wm831x_backlight_pdata *backlight; 96 struct wm831x_backlight_pdata *backlight;
96 struct wm831x_backup_pdata *backup; 97 struct wm831x_backup_pdata *backup;