aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2010-05-11 20:10:55 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2010-05-27 19:37:49 -0400
commitf7b2a77fe6f7b13b9cbf1909f032adef0be63ce1 (patch)
treee698cc1ab7e777f8820d0d3c412865edfe25002c
parent6438a694b670cd188c2fd2f75e0cd6b0ae21bea9 (diff)
mfd: Use threaded irq for pcf50633
Use threaded oneshot irq handler instead of normal irq handler and a workqueue. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/pcf50633-core.c57
2 files changed, 10 insertions, 49 deletions
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 4c684c137d43..85934966a593 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -57,7 +57,7 @@ obj-$(CONFIG_PMIC_DA903X) += da903x.o
57max8925-objs := max8925-core.o max8925-i2c.o 57max8925-objs := max8925-core.o max8925-i2c.o
58obj-$(CONFIG_MFD_MAX8925) += max8925.o 58obj-$(CONFIG_MFD_MAX8925) += max8925.o
59 59
60obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o 60obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o pcf50633-irq.o
61obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o 61obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
62obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o 62obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
63obj-$(CONFIG_ABX500_CORE) += abx500-core.o 63obj-$(CONFIG_ABX500_CORE) += abx500-core.o
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 37618b2be9a2..b3bef4998744 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -325,14 +325,12 @@ static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
325/* Maximum amount of time ONKEY is held before emergency action is taken */ 325/* Maximum amount of time ONKEY is held before emergency action is taken */
326#define PCF50633_ONKEY1S_TIMEOUT 8 326#define PCF50633_ONKEY1S_TIMEOUT 8
327 327
328static void pcf50633_irq_worker(struct work_struct *work) 328static irqreturn_t pcf50633_irq(int irq, void *data)
329{ 329{
330 struct pcf50633 *pcf; 330 struct pcf50633 *pcf = data;
331 int ret, i, j; 331 int ret, i, j;
332 u8 pcf_int[5], chgstat; 332 u8 pcf_int[5], chgstat;
333 333
334 pcf = container_of(work, struct pcf50633, irq_work);
335
336 /* Read the 5 INT regs in one transaction */ 334 /* Read the 5 INT regs in one transaction */
337 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1, 335 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
338 ARRAY_SIZE(pcf_int), pcf_int); 336 ARRAY_SIZE(pcf_int), pcf_int);
@@ -436,21 +434,7 @@ static void pcf50633_irq_worker(struct work_struct *work)
436 } 434 }
437 435
438out: 436out:
439 put_device(pcf->dev); 437 return IRQ_HANDLED
440 enable_irq(pcf->irq);
441}
442
443static irqreturn_t pcf50633_irq(int irq, void *data)
444{
445 struct pcf50633 *pcf = data;
446
447 dev_dbg(pcf->dev, "pcf50633_irq\n");
448
449 get_device(pcf->dev);
450 disable_irq_nosync(pcf->irq);
451 queue_work(pcf->work_queue, &pcf->irq_work);
452
453 return IRQ_HANDLED;
454} 438}
455 439
456static void 440static void
@@ -488,9 +472,6 @@ static int pcf50633_suspend(struct i2c_client *client, pm_message_t state)
488 * henceforth */ 472 * henceforth */
489 disable_irq(pcf->irq); 473 disable_irq(pcf->irq);
490 474
491 /* Make sure that any running IRQ worker has quit */
492 cancel_work_sync(&pcf->irq_work);
493
494 /* Save the masks */ 475 /* Save the masks */
495 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M, 476 ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
496 ARRAY_SIZE(pcf->suspend_irq_masks), 477 ARRAY_SIZE(pcf->suspend_irq_masks),
@@ -531,16 +512,7 @@ static int pcf50633_resume(struct i2c_client *client)
531 if (ret < 0) 512 if (ret < 0)
532 dev_err(pcf->dev, "Error restoring saved suspend masks\n"); 513 dev_err(pcf->dev, "Error restoring saved suspend masks\n");
533 514
534 /* Restore regulators' state */ 515 enable_irq(pcf->irq);
535
536
537 get_device(pcf->dev);
538
539 /*
540 * Clear any pending interrupts and set resume reason if any.
541 * This will leave with enable_irq()
542 */
543 pcf50633_irq_worker(&pcf->irq_work);
544 516
545 return 0; 517 return 0;
546} 518}
@@ -574,22 +546,13 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
574 pcf->dev = &client->dev; 546 pcf->dev = &client->dev;
575 pcf->i2c_client = client; 547 pcf->i2c_client = client;
576 pcf->irq = client->irq; 548 pcf->irq = client->irq;
577 pcf->work_queue = create_singlethread_workqueue("pcf50633");
578
579 if (!pcf->work_queue) {
580 dev_err(&client->dev, "Failed to alloc workqueue\n");
581 ret = -ENOMEM;
582 goto err_free;
583 }
584
585 INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
586 549
587 version = pcf50633_reg_read(pcf, 0); 550 version = pcf50633_reg_read(pcf, 0);
588 variant = pcf50633_reg_read(pcf, 1); 551 variant = pcf50633_reg_read(pcf, 1);
589 if (version < 0 || variant < 0) { 552 if (version < 0 || variant < 0) {
590 dev_err(pcf->dev, "Unable to probe pcf50633\n"); 553 dev_err(pcf->dev, "Unable to probe pcf50633\n");
591 ret = -ENODEV; 554 ret = -ENODEV;
592 goto err_destroy_workqueue; 555 goto err_free;
593 } 556 }
594 557
595 dev_info(pcf->dev, "Probed device version %d variant %d\n", 558 dev_info(pcf->dev, "Probed device version %d variant %d\n",
@@ -603,12 +566,13 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
603 pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00); 566 pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
604 pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00); 567 pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
605 568
606 ret = request_irq(client->irq, pcf50633_irq, 569 ret = request_threaded_irq(client->irq, NULL, pcf50633_irq,
607 IRQF_TRIGGER_LOW, "pcf50633", pcf); 570 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
571 "pcf50633", pcf);
608 572
609 if (ret) { 573 if (ret) {
610 dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); 574 dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
611 goto err_destroy_workqueue; 575 goto err_free;
612 } 576 }
613 577
614 /* Create sub devices */ 578 /* Create sub devices */
@@ -654,8 +618,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
654 618
655 return 0; 619 return 0;
656 620
657err_destroy_workqueue:
658 destroy_workqueue(pcf->work_queue);
659err_free: 621err_free:
660 i2c_set_clientdata(client, NULL); 622 i2c_set_clientdata(client, NULL);
661 kfree(pcf); 623 kfree(pcf);
@@ -669,7 +631,6 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
669 int i; 631 int i;
670 632
671 free_irq(pcf->irq, pcf); 633 free_irq(pcf->irq, pcf);
672 destroy_workqueue(pcf->work_queue);
673 634
674 platform_device_unregister(pcf->input_pdev); 635 platform_device_unregister(pcf->input_pdev);
675 platform_device_unregister(pcf->rtc_pdev); 636 platform_device_unregister(pcf->rtc_pdev);