diff options
author | Johan Bjornstedt <johan.bjornstedt@stericsson.com> | 2013-01-11 08:12:50 -0500 |
---|---|---|
committer | Anton Vorontsov <anton@enomsg.org> | 2013-01-15 20:10:17 -0500 |
commit | 3988a4df3499e604a3f2ae979372d27fc5664f77 (patch) | |
tree | efe7b3265c2e4b9a6cdd51d268ce733ced2c3959 /drivers | |
parent | defbfa9cf879c8e7dde6f7ee9aa95a010efa2e34 (diff) |
ab8500_bm: Skip first CCEOC irq for instant current
When enabling the CCEOC irq we might get false interrupt
from ab8500-driver due to the latched value will be saved
and interpreted as an IRQ when enabled
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Johan Bjornstedt <johan.bjornstedt@stericsson.com>
Signed-off-by: Henrik Solver <henrik.solver@stericsson.com>
Reviewed-by: Karl KOMIEROWSKI <karl.komierowski@stericsson.com>
Signed-off-by: Anton Vorontsov <anton@enomsg.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/power/ab8500_btemp.c | 11 | ||||
-rw-r--r-- | drivers/power/ab8500_fg.c | 63 |
2 files changed, 59 insertions, 15 deletions
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index e1d28039ce7b..4a570b6c9e47 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c | |||
@@ -374,13 +374,10 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di) | |||
374 | return ret; | 374 | return ret; |
375 | } | 375 | } |
376 | 376 | ||
377 | /* | 377 | do { |
378 | * Since there is no interrupt when current measurement is done, | 378 | msleep(20); |
379 | * loop for over 250ms (250ms is one sample conversion time | 379 | } while (!ab8500_fg_inst_curr_started(di->fg)); |
380 | * with 32.768 Khz RTC clock). Note that a stop time must be set | 380 | |
381 | * since the ab8500_btemp_read_batctrl_voltage call can block and | ||
382 | * take an unknown amount of time to complete. | ||
383 | */ | ||
384 | i = 0; | 381 | i = 0; |
385 | 382 | ||
386 | do { | 383 | do { |
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index 3d05c73813c8..0f40c968286c 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c | |||
@@ -160,6 +160,7 @@ struct inst_curr_result_list { | |||
160 | * @recovery_cnt: Counter for recovery mode | 160 | * @recovery_cnt: Counter for recovery mode |
161 | * @high_curr_cnt: Counter for high current mode | 161 | * @high_curr_cnt: Counter for high current mode |
162 | * @init_cnt: Counter for init mode | 162 | * @init_cnt: Counter for init mode |
163 | * @nbr_cceoc_irq_cnt Counter for number of CCEOC irqs received since enabled | ||
163 | * @recovery_needed: Indicate if recovery is needed | 164 | * @recovery_needed: Indicate if recovery is needed |
164 | * @high_curr_mode: Indicate if we're in high current mode | 165 | * @high_curr_mode: Indicate if we're in high current mode |
165 | * @init_capacity: Indicate if initial capacity measuring should be done | 166 | * @init_capacity: Indicate if initial capacity measuring should be done |
@@ -167,6 +168,7 @@ struct inst_curr_result_list { | |||
167 | * @calib_state State during offset calibration | 168 | * @calib_state State during offset calibration |
168 | * @discharge_state: Current discharge state | 169 | * @discharge_state: Current discharge state |
169 | * @charge_state: Current charge state | 170 | * @charge_state: Current charge state |
171 | * @ab8500_fg_started Completion struct used for the instant current start | ||
170 | * @ab8500_fg_complete Completion struct used for the instant current reading | 172 | * @ab8500_fg_complete Completion struct used for the instant current reading |
171 | * @flags: Structure for information about events triggered | 173 | * @flags: Structure for information about events triggered |
172 | * @bat_cap: Structure for battery capacity specific parameters | 174 | * @bat_cap: Structure for battery capacity specific parameters |
@@ -199,6 +201,7 @@ struct ab8500_fg { | |||
199 | int recovery_cnt; | 201 | int recovery_cnt; |
200 | int high_curr_cnt; | 202 | int high_curr_cnt; |
201 | int init_cnt; | 203 | int init_cnt; |
204 | int nbr_cceoc_irq_cnt; | ||
202 | bool recovery_needed; | 205 | bool recovery_needed; |
203 | bool high_curr_mode; | 206 | bool high_curr_mode; |
204 | bool init_capacity; | 207 | bool init_capacity; |
@@ -206,6 +209,7 @@ struct ab8500_fg { | |||
206 | enum ab8500_fg_calibration_state calib_state; | 209 | enum ab8500_fg_calibration_state calib_state; |
207 | enum ab8500_fg_discharge_state discharge_state; | 210 | enum ab8500_fg_discharge_state discharge_state; |
208 | enum ab8500_fg_charge_state charge_state; | 211 | enum ab8500_fg_charge_state charge_state; |
212 | struct completion ab8500_fg_started; | ||
209 | struct completion ab8500_fg_complete; | 213 | struct completion ab8500_fg_complete; |
210 | struct ab8500_fg_flags flags; | 214 | struct ab8500_fg_flags flags; |
211 | struct ab8500_fg_battery_capacity bat_cap; | 215 | struct ab8500_fg_battery_capacity bat_cap; |
@@ -524,13 +528,14 @@ cc_err: | |||
524 | * Note: This is part "one" and has to be called before | 528 | * Note: This is part "one" and has to be called before |
525 | * ab8500_fg_inst_curr_finalize() | 529 | * ab8500_fg_inst_curr_finalize() |
526 | */ | 530 | */ |
527 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di) | 531 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di) |
528 | { | 532 | { |
529 | u8 reg_val; | 533 | u8 reg_val; |
530 | int ret; | 534 | int ret; |
531 | 535 | ||
532 | mutex_lock(&di->cc_lock); | 536 | mutex_lock(&di->cc_lock); |
533 | 537 | ||
538 | di->nbr_cceoc_irq_cnt = 0; | ||
534 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | 539 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, |
535 | AB8500_RTC_CC_CONF_REG, ®_val); | 540 | AB8500_RTC_CC_CONF_REG, ®_val); |
536 | if (ret < 0) | 541 | if (ret < 0) |
@@ -558,6 +563,7 @@ cc_err: | |||
558 | } | 563 | } |
559 | 564 | ||
560 | /* Return and WFI */ | 565 | /* Return and WFI */ |
566 | INIT_COMPLETION(di->ab8500_fg_started); | ||
561 | INIT_COMPLETION(di->ab8500_fg_complete); | 567 | INIT_COMPLETION(di->ab8500_fg_complete); |
562 | enable_irq(di->irq); | 568 | enable_irq(di->irq); |
563 | 569 | ||
@@ -569,6 +575,17 @@ fail: | |||
569 | } | 575 | } |
570 | 576 | ||
571 | /** | 577 | /** |
578 | * ab8500_fg_inst_curr_started() - check if fg conversion has started | ||
579 | * @di: pointer to the ab8500_fg structure | ||
580 | * | ||
581 | * Returns 1 if conversion started, 0 if still waiting | ||
582 | */ | ||
583 | int ab8500_fg_inst_curr_started(struct ab8500_fg *di) | ||
584 | { | ||
585 | return completion_done(&di->ab8500_fg_started); | ||
586 | } | ||
587 | |||
588 | /** | ||
572 | * ab8500_fg_inst_curr_done() - check if fg conversion is done | 589 | * ab8500_fg_inst_curr_done() - check if fg conversion is done |
573 | * @di: pointer to the ab8500_fg structure | 590 | * @di: pointer to the ab8500_fg structure |
574 | * | 591 | * |
@@ -596,13 +613,15 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | |||
596 | int timeout; | 613 | int timeout; |
597 | 614 | ||
598 | if (!completion_done(&di->ab8500_fg_complete)) { | 615 | if (!completion_done(&di->ab8500_fg_complete)) { |
599 | timeout = wait_for_completion_timeout(&di->ab8500_fg_complete, | 616 | timeout = wait_for_completion_timeout( |
617 | &di->ab8500_fg_complete, | ||
600 | INS_CURR_TIMEOUT); | 618 | INS_CURR_TIMEOUT); |
601 | dev_dbg(di->dev, "Finalize time: %d ms\n", | 619 | dev_dbg(di->dev, "Finalize time: %d ms\n", |
602 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); | 620 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); |
603 | if (!timeout) { | 621 | if (!timeout) { |
604 | ret = -ETIME; | 622 | ret = -ETIME; |
605 | disable_irq(di->irq); | 623 | disable_irq(di->irq); |
624 | di->nbr_cceoc_irq_cnt = 0; | ||
606 | dev_err(di->dev, "completion timed out [%d]\n", | 625 | dev_err(di->dev, "completion timed out [%d]\n", |
607 | __LINE__); | 626 | __LINE__); |
608 | goto fail; | 627 | goto fail; |
@@ -610,6 +629,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | |||
610 | } | 629 | } |
611 | 630 | ||
612 | disable_irq(di->irq); | 631 | disable_irq(di->irq); |
632 | di->nbr_cceoc_irq_cnt = 0; | ||
613 | 633 | ||
614 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 634 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
615 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, | 635 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, |
@@ -684,6 +704,7 @@ fail: | |||
684 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) | 704 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) |
685 | { | 705 | { |
686 | int ret; | 706 | int ret; |
707 | int timeout; | ||
687 | int res = 0; | 708 | int res = 0; |
688 | 709 | ||
689 | ret = ab8500_fg_inst_curr_start(di); | 710 | ret = ab8500_fg_inst_curr_start(di); |
@@ -692,13 +713,32 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) | |||
692 | return 0; | 713 | return 0; |
693 | } | 714 | } |
694 | 715 | ||
716 | /* Wait for CC to actually start */ | ||
717 | if (!completion_done(&di->ab8500_fg_started)) { | ||
718 | timeout = wait_for_completion_timeout( | ||
719 | &di->ab8500_fg_started, | ||
720 | INS_CURR_TIMEOUT); | ||
721 | dev_dbg(di->dev, "Start time: %d ms\n", | ||
722 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); | ||
723 | if (!timeout) { | ||
724 | ret = -ETIME; | ||
725 | dev_err(di->dev, "completion timed out [%d]\n", | ||
726 | __LINE__); | ||
727 | goto fail; | ||
728 | } | ||
729 | } | ||
730 | |||
695 | ret = ab8500_fg_inst_curr_finalize(di, &res); | 731 | ret = ab8500_fg_inst_curr_finalize(di, &res); |
696 | if (ret) { | 732 | if (ret) { |
697 | dev_err(di->dev, "Failed to finalize fg_inst\n"); | 733 | dev_err(di->dev, "Failed to finalize fg_inst\n"); |
698 | return 0; | 734 | return 0; |
699 | } | 735 | } |
700 | 736 | ||
737 | dev_dbg(di->dev, "%s instant current: %d", __func__, res); | ||
701 | return res; | 738 | return res; |
739 | fail: | ||
740 | mutex_unlock(&di->cc_lock); | ||
741 | return ret; | ||
702 | } | 742 | } |
703 | 743 | ||
704 | /** | 744 | /** |
@@ -1523,8 +1563,6 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1523 | 1563 | ||
1524 | case AB8500_FG_DISCHARGE_WAKEUP: | 1564 | case AB8500_FG_DISCHARGE_WAKEUP: |
1525 | ab8500_fg_coulomb_counter(di, true); | 1565 | ab8500_fg_coulomb_counter(di, true); |
1526 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1527 | |||
1528 | ab8500_fg_calc_cap_discharge_voltage(di, true); | 1566 | ab8500_fg_calc_cap_discharge_voltage(di, true); |
1529 | 1567 | ||
1530 | di->fg_samples = SEC_TO_SAMPLE( | 1568 | di->fg_samples = SEC_TO_SAMPLE( |
@@ -1641,8 +1679,6 @@ static void ab8500_fg_periodic_work(struct work_struct *work) | |||
1641 | fg_periodic_work.work); | 1679 | fg_periodic_work.work); |
1642 | 1680 | ||
1643 | if (di->init_capacity) { | 1681 | if (di->init_capacity) { |
1644 | /* A dummy read that will return 0 */ | ||
1645 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1646 | /* Get an initial capacity calculation */ | 1682 | /* Get an initial capacity calculation */ |
1647 | ab8500_fg_calc_cap_discharge_voltage(di, true); | 1683 | ab8500_fg_calc_cap_discharge_voltage(di, true); |
1648 | ab8500_fg_check_capacity_limits(di, true); | 1684 | ab8500_fg_check_capacity_limits(di, true); |
@@ -1828,7 +1864,13 @@ static void ab8500_fg_instant_work(struct work_struct *work) | |||
1828 | static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) | 1864 | static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) |
1829 | { | 1865 | { |
1830 | struct ab8500_fg *di = _di; | 1866 | struct ab8500_fg *di = _di; |
1831 | complete(&di->ab8500_fg_complete); | 1867 | if (!di->nbr_cceoc_irq_cnt) { |
1868 | di->nbr_cceoc_irq_cnt++; | ||
1869 | complete(&di->ab8500_fg_started); | ||
1870 | } else { | ||
1871 | di->nbr_cceoc_irq_cnt = 0; | ||
1872 | complete(&di->ab8500_fg_complete); | ||
1873 | } | ||
1832 | return IRQ_HANDLED; | 1874 | return IRQ_HANDLED; |
1833 | } | 1875 | } |
1834 | 1876 | ||
@@ -2551,7 +2593,11 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2551 | di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); | 2593 | di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); |
2552 | ab8500_fg_coulomb_counter(di, true); | 2594 | ab8500_fg_coulomb_counter(di, true); |
2553 | 2595 | ||
2554 | /* Initialize completion used to notify completion of inst current */ | 2596 | /* |
2597 | * Initialize completion used to notify completion and start | ||
2598 | * of inst current | ||
2599 | */ | ||
2600 | init_completion(&di->ab8500_fg_started); | ||
2555 | init_completion(&di->ab8500_fg_complete); | 2601 | init_completion(&di->ab8500_fg_complete); |
2556 | 2602 | ||
2557 | /* Register interrupts */ | 2603 | /* Register interrupts */ |
@@ -2571,6 +2617,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2571 | } | 2617 | } |
2572 | di->irq = platform_get_irq_byname(pdev, "CCEOC"); | 2618 | di->irq = platform_get_irq_byname(pdev, "CCEOC"); |
2573 | disable_irq(di->irq); | 2619 | disable_irq(di->irq); |
2620 | di->nbr_cceoc_irq_cnt = 0; | ||
2574 | 2621 | ||
2575 | platform_set_drvdata(pdev, di); | 2622 | platform_set_drvdata(pdev, di); |
2576 | 2623 | ||