diff options
Diffstat (limited to 'drivers/mfd/ab8500-gpadc.c')
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 3fb1f40d6389..b1f3561b023f 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,11 @@ | |||
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 | |||
89 | #define CONVERSION_TIME 500 /* ms */ | ||
90 | |||
85 | enum cal_channels { | 91 | enum cal_channels { |
86 | ADC_INPUT_VMAIN = 0, | 92 | ADC_INPUT_VMAIN = 0, |
87 | ADC_INPUT_BTEMP, | 93 | ADC_INPUT_BTEMP, |
@@ -102,10 +108,10 @@ struct adc_cal_data { | |||
102 | 108 | ||
103 | /** | 109 | /** |
104 | * struct ab8500_gpadc - AB8500 GPADC device information | 110 | * struct ab8500_gpadc - AB8500 GPADC device information |
105 | * @chip_id ABB chip id | ||
106 | * @dev: pointer to the struct device | 111 | * @dev: pointer to the struct device |
107 | * @node: a list of AB8500 GPADCs, hence prepared for | 112 | * @node: a list of AB8500 GPADCs, hence prepared for |
108 | reentrance | 113 | reentrance |
114 | * @parent: pointer to the struct ab8500 | ||
109 | * @ab8500_gpadc_complete: pointer to the struct completion, to indicate | 115 | * @ab8500_gpadc_complete: pointer to the struct completion, to indicate |
110 | * the completion of gpadc conversion | 116 | * the completion of gpadc conversion |
111 | * @ab8500_gpadc_lock: structure of type mutex | 117 | * @ab8500_gpadc_lock: structure of type mutex |
@@ -114,9 +120,9 @@ struct adc_cal_data { | |||
114 | * @cal_data array of ADC calibration data structs | 120 | * @cal_data array of ADC calibration data structs |
115 | */ | 121 | */ |
116 | struct ab8500_gpadc { | 122 | struct ab8500_gpadc { |
117 | u8 chip_id; | ||
118 | struct device *dev; | 123 | struct device *dev; |
119 | struct list_head node; | 124 | struct list_head node; |
125 | struct ab8500 *parent; | ||
120 | struct completion ab8500_gpadc_complete; | 126 | struct completion ab8500_gpadc_complete; |
121 | struct mutex ab8500_gpadc_lock; | 127 | struct mutex ab8500_gpadc_lock; |
122 | struct regulator *regu; | 128 | struct regulator *regu; |
@@ -282,8 +288,9 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
282 | return -ENODEV; | 288 | return -ENODEV; |
283 | 289 | ||
284 | mutex_lock(&gpadc->ab8500_gpadc_lock); | 290 | mutex_lock(&gpadc->ab8500_gpadc_lock); |
291 | |||
285 | /* Enable VTVout LDO this is required for GPADC */ | 292 | /* Enable VTVout LDO this is required for GPADC */ |
286 | regulator_enable(gpadc->regu); | 293 | pm_runtime_get_sync(gpadc->dev); |
287 | 294 | ||
288 | /* Check if ADC is not busy, lock and proceed */ | 295 | /* Check if ADC is not busy, lock and proceed */ |
289 | do { | 296 | do { |
@@ -332,7 +339,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
332 | EN_BUF | EN_ICHAR); | 339 | EN_BUF | EN_ICHAR); |
333 | break; | 340 | break; |
334 | case BTEMP_BALL: | 341 | case BTEMP_BALL: |
335 | if (gpadc->chip_id >= AB8500_CUT3P0) { | 342 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { |
336 | /* Turn on btemp pull-up on ABB 3.0 */ | 343 | /* Turn on btemp pull-up on ABB 3.0 */ |
337 | ret = abx500_mask_and_set_register_interruptible( | 344 | ret = abx500_mask_and_set_register_interruptible( |
338 | gpadc->dev, | 345 | gpadc->dev, |
@@ -344,7 +351,7 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
344 | * Delay might be needed for ABB8500 cut 3.0, if not, remove | 351 | * Delay might be needed for ABB8500 cut 3.0, if not, remove |
345 | * when hardware will be available | 352 | * when hardware will be available |
346 | */ | 353 | */ |
347 | msleep(1); | 354 | usleep_range(1000, 1000); |
348 | break; | 355 | break; |
349 | } | 356 | } |
350 | /* Intentional fallthrough */ | 357 | /* Intentional fallthrough */ |
@@ -367,7 +374,8 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
367 | goto out; | 374 | goto out; |
368 | } | 375 | } |
369 | /* wait for completion of conversion */ | 376 | /* wait for completion of conversion */ |
370 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, 2*HZ)) { | 377 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
378 | msecs_to_jiffies(CONVERSION_TIME))) { | ||
371 | dev_err(gpadc->dev, | 379 | dev_err(gpadc->dev, |
372 | "timeout: didn't receive GPADC conversion interrupt\n"); | 380 | "timeout: didn't receive GPADC conversion interrupt\n"); |
373 | ret = -EINVAL; | 381 | ret = -EINVAL; |
@@ -397,8 +405,10 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | |||
397 | dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); | 405 | dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n"); |
398 | goto out; | 406 | goto out; |
399 | } | 407 | } |
400 | /* Disable VTVout LDO this is required for GPADC */ | 408 | |
401 | regulator_disable(gpadc->regu); | 409 | pm_runtime_mark_last_busy(gpadc->dev); |
410 | pm_runtime_put_autosuspend(gpadc->dev); | ||
411 | |||
402 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 412 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
403 | 413 | ||
404 | return (high_data << 8) | low_data; | 414 | return (high_data << 8) | low_data; |
@@ -412,7 +422,9 @@ out: | |||
412 | */ | 422 | */ |
413 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 423 | (void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
414 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 424 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
415 | regulator_disable(gpadc->regu); | 425 | |
426 | pm_runtime_put(gpadc->dev); | ||
427 | |||
416 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 428 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
417 | dev_err(gpadc->dev, | 429 | dev_err(gpadc->dev, |
418 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); | 430 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); |
@@ -571,6 +583,28 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
571 | gpadc->cal_data[ADC_INPUT_VBAT].offset); | 583 | gpadc->cal_data[ADC_INPUT_VBAT].offset); |
572 | } | 584 | } |
573 | 585 | ||
586 | static int ab8500_gpadc_runtime_suspend(struct device *dev) | ||
587 | { | ||
588 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | ||
589 | |||
590 | regulator_disable(gpadc->regu); | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static int ab8500_gpadc_runtime_resume(struct device *dev) | ||
595 | { | ||
596 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | ||
597 | |||
598 | regulator_enable(gpadc->regu); | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int ab8500_gpadc_runtime_idle(struct device *dev) | ||
603 | { | ||
604 | pm_runtime_suspend(dev); | ||
605 | return 0; | ||
606 | } | ||
607 | |||
574 | static int ab8500_gpadc_probe(struct platform_device *pdev) | 608 | static int ab8500_gpadc_probe(struct platform_device *pdev) |
575 | { | 609 | { |
576 | int ret = 0; | 610 | int ret = 0; |
@@ -591,6 +625,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
591 | } | 625 | } |
592 | 626 | ||
593 | gpadc->dev = &pdev->dev; | 627 | gpadc->dev = &pdev->dev; |
628 | gpadc->parent = dev_get_drvdata(pdev->dev.parent); | ||
594 | mutex_init(&gpadc->ab8500_gpadc_lock); | 629 | mutex_init(&gpadc->ab8500_gpadc_lock); |
595 | 630 | ||
596 | /* Initialize completion used to notify completion of conversion */ | 631 | /* Initialize completion used to notify completion of conversion */ |
@@ -607,14 +642,6 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
607 | goto fail; | 642 | goto fail; |
608 | } | 643 | } |
609 | 644 | ||
610 | /* Get Chip ID of the ABB ASIC */ | ||
611 | ret = abx500_get_chip_id(gpadc->dev); | ||
612 | if (ret < 0) { | ||
613 | dev_err(gpadc->dev, "failed to get chip ID\n"); | ||
614 | goto fail_irq; | ||
615 | } | ||
616 | gpadc->chip_id = (u8) ret; | ||
617 | |||
618 | /* VTVout LDO used to power up ab8500-GPADC */ | 645 | /* VTVout LDO used to power up ab8500-GPADC */ |
619 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); | 646 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); |
620 | if (IS_ERR(gpadc->regu)) { | 647 | if (IS_ERR(gpadc->regu)) { |
@@ -622,6 +649,16 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
622 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); | 649 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); |
623 | goto fail_irq; | 650 | goto fail_irq; |
624 | } | 651 | } |
652 | |||
653 | platform_set_drvdata(pdev, gpadc); | ||
654 | |||
655 | regulator_enable(gpadc->regu); | ||
656 | |||
657 | pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); | ||
658 | pm_runtime_use_autosuspend(gpadc->dev); | ||
659 | pm_runtime_set_active(gpadc->dev); | ||
660 | pm_runtime_enable(gpadc->dev); | ||
661 | |||
625 | ab8500_gpadc_read_calibration_data(gpadc); | 662 | ab8500_gpadc_read_calibration_data(gpadc); |
626 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); | 663 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); |
627 | dev_dbg(gpadc->dev, "probe success\n"); | 664 | dev_dbg(gpadc->dev, "probe success\n"); |
@@ -642,19 +679,34 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) | |||
642 | list_del(&gpadc->node); | 679 | list_del(&gpadc->node); |
643 | /* remove interrupt - completion of Sw ADC conversion */ | 680 | /* remove interrupt - completion of Sw ADC conversion */ |
644 | free_irq(gpadc->irq, gpadc); | 681 | free_irq(gpadc->irq, gpadc); |
645 | /* disable VTVout LDO that is being used by GPADC */ | 682 | |
646 | regulator_put(gpadc->regu); | 683 | pm_runtime_get_sync(gpadc->dev); |
684 | pm_runtime_disable(gpadc->dev); | ||
685 | |||
686 | regulator_disable(gpadc->regu); | ||
687 | |||
688 | pm_runtime_set_suspended(gpadc->dev); | ||
689 | |||
690 | pm_runtime_put_noidle(gpadc->dev); | ||
691 | |||
647 | kfree(gpadc); | 692 | kfree(gpadc); |
648 | gpadc = NULL; | 693 | gpadc = NULL; |
649 | return 0; | 694 | return 0; |
650 | } | 695 | } |
651 | 696 | ||
697 | static const struct dev_pm_ops ab8500_gpadc_pm_ops = { | ||
698 | SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, | ||
699 | ab8500_gpadc_runtime_resume, | ||
700 | ab8500_gpadc_runtime_idle) | ||
701 | }; | ||
702 | |||
652 | static struct platform_driver ab8500_gpadc_driver = { | 703 | static struct platform_driver ab8500_gpadc_driver = { |
653 | .probe = ab8500_gpadc_probe, | 704 | .probe = ab8500_gpadc_probe, |
654 | .remove = ab8500_gpadc_remove, | 705 | .remove = ab8500_gpadc_remove, |
655 | .driver = { | 706 | .driver = { |
656 | .name = "ab8500-gpadc", | 707 | .name = "ab8500-gpadc", |
657 | .owner = THIS_MODULE, | 708 | .owner = THIS_MODULE, |
709 | .pm = &ab8500_gpadc_pm_ops, | ||
658 | }, | 710 | }, |
659 | }; | 711 | }; |
660 | 712 | ||