diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2010-05-11 20:10:55 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2010-05-27 19:37:49 -0400 |
commit | f7b2a77fe6f7b13b9cbf1909f032adef0be63ce1 (patch) | |
tree | e698cc1ab7e777f8820d0d3c412865edfe25002c /drivers/mfd/pcf50633-core.c | |
parent | 6438a694b670cd188c2fd2f75e0cd6b0ae21bea9 (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>
Diffstat (limited to 'drivers/mfd/pcf50633-core.c')
-rw-r--r-- | drivers/mfd/pcf50633-core.c | 57 |
1 files changed, 9 insertions, 48 deletions
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 | ||
328 | static void pcf50633_irq_worker(struct work_struct *work) | 328 | static 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 | ||
438 | out: | 436 | out: |
439 | put_device(pcf->dev); | 437 | return IRQ_HANDLED |
440 | enable_irq(pcf->irq); | ||
441 | } | ||
442 | |||
443 | static 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 | ||
456 | static void | 440 | static 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 | ||
657 | err_destroy_workqueue: | ||
658 | destroy_workqueue(pcf->work_queue); | ||
659 | err_free: | 621 | err_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); |