aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-gpadc.c
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2013-02-04 03:33:13 -0500
committerLee Jones <lee.jones@linaro.org>2013-02-04 03:33:13 -0500
commit5f8aaef4fdf97bfe504ff2c78244a53a145917dc (patch)
tree208d3e78144a06c6db90f46908786d0df0de94f0 /drivers/mfd/ab8500-gpadc.c
parent8f0eb43be5f461a28341fe724686f265b0719dd3 (diff)
mfd: ab8500-gpadc: Add runtime pm support
Add runtime pm support to speed up multiple ADC reads in a row. Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> Reviewed-by: Ulf HANSSON <ulf.hansson@stericsson.com>
Diffstat (limited to 'drivers/mfd/ab8500-gpadc.c')
-rw-r--r--drivers/mfd/ab8500-gpadc.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index 61b176fc457b..580f1008d67a 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -12,6 +12,7 @@
12#include <linux/interrupt.h> 12#include <linux/interrupt.h>
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/pm_runtime.h>
15#include <linux/platform_device.h> 16#include <linux/platform_device.h>
16#include <linux/completion.h> 17#include <linux/completion.h>
17#include <linux/regulator/consumer.h> 18#include <linux/regulator/consumer.h>
@@ -82,6 +83,9 @@
82/* This is used to not lose precision when dividing to get gain and offset */ 83/* This is used to not lose precision when dividing to get gain and offset */
83#define CALIB_SCALE 1000 84#define CALIB_SCALE 1000
84 85
86/* Time in ms before disabling regulator */
87#define GPADC_AUDOSUSPEND_DELAY 1
88
85enum cal_channels { 89enum cal_channels {
86 ADC_INPUT_VMAIN = 0, 90 ADC_INPUT_VMAIN = 0,
87 ADC_INPUT_BTEMP, 91 ADC_INPUT_BTEMP,
@@ -282,8 +286,9 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
282 return -ENODEV; 286 return -ENODEV;
283 287
284 mutex_lock(&gpadc->ab8500_gpadc_lock); 288 mutex_lock(&gpadc->ab8500_gpadc_lock);
289
285 /* Enable VTVout LDO this is required for GPADC */ 290 /* Enable VTVout LDO this is required for GPADC */
286 regulator_enable(gpadc->regu); 291 pm_runtime_get_sync(gpadc->dev);
287 292
288 /* Check if ADC is not busy, lock and proceed */ 293 /* Check if ADC is not busy, lock and proceed */
289 do { 294 do {
@@ -397,8 +402,10 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
397 dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); 402 dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n");
398 goto out; 403 goto out;
399 } 404 }
400 /* Disable VTVout LDO this is required for GPADC */ 405
401 regulator_disable(gpadc->regu); 406 pm_runtime_mark_last_busy(gpadc->dev);
407 pm_runtime_put_autosuspend(gpadc->dev);
408
402 mutex_unlock(&gpadc->ab8500_gpadc_lock); 409 mutex_unlock(&gpadc->ab8500_gpadc_lock);
403 410
404 return (high_data << 8) | low_data; 411 return (high_data << 8) | low_data;
@@ -412,7 +419,9 @@ out:
412 */ 419 */
413 (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, 420 (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
414 AB8500_GPADC_CTRL1_REG, DIS_GPADC); 421 AB8500_GPADC_CTRL1_REG, DIS_GPADC);
415 regulator_disable(gpadc->regu); 422
423 pm_runtime_put(gpadc->dev);
424
416 mutex_unlock(&gpadc->ab8500_gpadc_lock); 425 mutex_unlock(&gpadc->ab8500_gpadc_lock);
417 dev_err(gpadc->dev, 426 dev_err(gpadc->dev,
418 "gpadc_conversion: Failed to AD convert channel %d\n", channel); 427 "gpadc_conversion: Failed to AD convert channel %d\n", channel);
@@ -571,6 +580,30 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
571 gpadc->cal_data[ADC_INPUT_VBAT].offset); 580 gpadc->cal_data[ADC_INPUT_VBAT].offset);
572} 581}
573 582
583static int ab8500_gpadc_runtime_suspend(struct device *dev)
584{
585 struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
586
587 regulator_disable(gpadc->regu);
588 return 0;
589}
590
591static int ab8500_gpadc_runtime_resume(struct device *dev)
592{
593 struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
594
595 regulator_enable(gpadc->regu);
596 return 0;
597}
598
599static int ab8500_gpadc_runtime_idle(struct device *dev)
600{
601 struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
602
603 pm_runtime_suspend(dev);
604 return 0;
605}
606
574static int ab8500_gpadc_probe(struct platform_device *pdev) 607static int ab8500_gpadc_probe(struct platform_device *pdev)
575{ 608{
576 int ret = 0; 609 int ret = 0;
@@ -615,6 +648,16 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
615 dev_err(gpadc->dev, "failed to get vtvout LDO\n"); 648 dev_err(gpadc->dev, "failed to get vtvout LDO\n");
616 goto fail_irq; 649 goto fail_irq;
617 } 650 }
651
652 platform_set_drvdata(pdev, gpadc);
653
654 regulator_enable(gpadc->regu);
655
656 pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY);
657 pm_runtime_use_autosuspend(gpadc->dev);
658 pm_runtime_set_active(gpadc->dev);
659 pm_runtime_enable(gpadc->dev);
660
618 ab8500_gpadc_read_calibration_data(gpadc); 661 ab8500_gpadc_read_calibration_data(gpadc);
619 list_add_tail(&gpadc->node, &ab8500_gpadc_list); 662 list_add_tail(&gpadc->node, &ab8500_gpadc_list);
620 dev_dbg(gpadc->dev, "probe success\n"); 663 dev_dbg(gpadc->dev, "probe success\n");
@@ -635,19 +678,34 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
635 list_del(&gpadc->node); 678 list_del(&gpadc->node);
636 /* remove interrupt - completion of Sw ADC conversion */ 679 /* remove interrupt - completion of Sw ADC conversion */
637 free_irq(gpadc->irq, gpadc); 680 free_irq(gpadc->irq, gpadc);
638 /* disable VTVout LDO that is being used by GPADC */ 681
639 regulator_put(gpadc->regu); 682 pm_runtime_get_sync(gpadc->dev);
683 pm_runtime_disable(gpadc->dev);
684
685 regulator_disable(gpadc->regu);
686
687 pm_runtime_set_suspended(gpadc->dev);
688
689 pm_runtime_put_noidle(gpadc->dev);
690
640 kfree(gpadc); 691 kfree(gpadc);
641 gpadc = NULL; 692 gpadc = NULL;
642 return 0; 693 return 0;
643} 694}
644 695
696static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
697 SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
698 ab8500_gpadc_runtime_resume,
699 ab8500_gpadc_runtime_idle)
700};
701
645static struct platform_driver ab8500_gpadc_driver = { 702static struct platform_driver ab8500_gpadc_driver = {
646 .probe = ab8500_gpadc_probe, 703 .probe = ab8500_gpadc_probe,
647 .remove = ab8500_gpadc_remove, 704 .remove = ab8500_gpadc_remove,
648 .driver = { 705 .driver = {
649 .name = "ab8500-gpadc", 706 .name = "ab8500-gpadc",
650 .owner = THIS_MODULE, 707 .owner = THIS_MODULE,
708 .pm = &ab8500_gpadc_pm_ops,
651 }, 709 },
652}; 710};
653 711