diff options
Diffstat (limited to 'drivers/power/ab8500_btemp.c')
-rw-r--r-- | drivers/power/ab8500_btemp.c | 80 |
1 files changed, 63 insertions, 17 deletions
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index 07689064996e..d412d34bf3df 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c | |||
@@ -42,6 +42,9 @@ | |||
42 | #define BTEMP_BATCTRL_CURR_SRC_16UA 16 | 42 | #define BTEMP_BATCTRL_CURR_SRC_16UA 16 |
43 | #define BTEMP_BATCTRL_CURR_SRC_18UA 18 | 43 | #define BTEMP_BATCTRL_CURR_SRC_18UA 18 |
44 | 44 | ||
45 | #define BTEMP_BATCTRL_CURR_SRC_60UA 60 | ||
46 | #define BTEMP_BATCTRL_CURR_SRC_120UA 120 | ||
47 | |||
45 | #define to_ab8500_btemp_device_info(x) container_of((x), \ | 48 | #define to_ab8500_btemp_device_info(x) container_of((x), \ |
46 | struct ab8500_btemp, btemp_psy); | 49 | struct ab8500_btemp, btemp_psy); |
47 | 50 | ||
@@ -76,8 +79,8 @@ struct ab8500_btemp_ranges { | |||
76 | * @dev: Pointer to the structure device | 79 | * @dev: Pointer to the structure device |
77 | * @node: List of AB8500 BTEMPs, hence prepared for reentrance | 80 | * @node: List of AB8500 BTEMPs, hence prepared for reentrance |
78 | * @curr_source: What current source we use, in uA | 81 | * @curr_source: What current source we use, in uA |
79 | * @bat_temp: Battery temperature in degree Celcius | 82 | * @bat_temp: Dispatched battery temperature in degree Celcius |
80 | * @prev_bat_temp Last dispatched battery temperature | 83 | * @prev_bat_temp Last measured battery temperature in degree Celcius |
81 | * @parent: Pointer to the struct ab8500 | 84 | * @parent: Pointer to the struct ab8500 |
82 | * @gpadc: Pointer to the struct gpadc | 85 | * @gpadc: Pointer to the struct gpadc |
83 | * @fg: Pointer to the struct fg | 86 | * @fg: Pointer to the struct fg |
@@ -128,6 +131,7 @@ struct ab8500_btemp *ab8500_btemp_get(void) | |||
128 | 131 | ||
129 | return btemp; | 132 | return btemp; |
130 | } | 133 | } |
134 | EXPORT_SYMBOL(ab8500_btemp_get); | ||
131 | 135 | ||
132 | /** | 136 | /** |
133 | * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance | 137 | * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance |
@@ -155,7 +159,7 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, | |||
155 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) { | 159 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) { |
156 | /* | 160 | /* |
157 | * If the battery has internal NTC, we use the current | 161 | * If the battery has internal NTC, we use the current |
158 | * source to calculate the resistance, 7uA or 20uA | 162 | * source to calculate the resistance. |
159 | */ | 163 | */ |
160 | rbs = (v_batctrl * 1000 | 164 | rbs = (v_batctrl * 1000 |
161 | - di->bm->gnd_lift_resistance * inst_curr) | 165 | - di->bm->gnd_lift_resistance * inst_curr) |
@@ -216,7 +220,12 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
216 | /* Only do this for batteries with internal NTC */ | 220 | /* Only do this for batteries with internal NTC */ |
217 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { | 221 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { |
218 | 222 | ||
219 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 223 | if (is_ab8540(di->parent)) { |
224 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA) | ||
225 | curr = BAT_CTRL_60U_ENA; | ||
226 | else | ||
227 | curr = BAT_CTRL_120U_ENA; | ||
228 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
220 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA) | 229 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA) |
221 | curr = BAT_CTRL_16U_ENA; | 230 | curr = BAT_CTRL_16U_ENA; |
222 | else | 231 | else |
@@ -257,7 +266,14 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
257 | } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { | 266 | } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { |
258 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); | 267 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); |
259 | 268 | ||
260 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 269 | if (is_ab8540(di->parent)) { |
270 | /* Write 0 to the curr bits */ | ||
271 | ret = abx500_mask_and_set_register_interruptible( | ||
272 | di->dev, | ||
273 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
274 | BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA, | ||
275 | ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA)); | ||
276 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
261 | /* Write 0 to the curr bits */ | 277 | /* Write 0 to the curr bits */ |
262 | ret = abx500_mask_and_set_register_interruptible( | 278 | ret = abx500_mask_and_set_register_interruptible( |
263 | di->dev, | 279 | di->dev, |
@@ -314,7 +330,13 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
314 | * if we got an error above | 330 | * if we got an error above |
315 | */ | 331 | */ |
316 | disable_curr_source: | 332 | disable_curr_source: |
317 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 333 | if (is_ab8540(di->parent)) { |
334 | /* Write 0 to the curr bits */ | ||
335 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
336 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
337 | BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA, | ||
338 | ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA)); | ||
339 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
318 | /* Write 0 to the curr bits */ | 340 | /* Write 0 to the curr bits */ |
319 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 341 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
320 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | 342 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, |
@@ -541,7 +563,9 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
541 | { | 563 | { |
542 | int res; | 564 | int res; |
543 | u8 i; | 565 | u8 i; |
544 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) | 566 | if (is_ab8540(di->parent)) |
567 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA; | ||
568 | else if (is_ab9540(di->parent) || is_ab8505(di->parent)) | ||
545 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; | 569 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; |
546 | else | 570 | else |
547 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; | 571 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; |
@@ -579,12 +603,17 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
579 | 603 | ||
580 | /* | 604 | /* |
581 | * We only have to change current source if the | 605 | * We only have to change current source if the |
582 | * detected type is Type 1, else we use the 7uA source | 606 | * detected type is Type 1. |
583 | */ | 607 | */ |
584 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && | 608 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && |
585 | di->bm->batt_id == 1) { | 609 | di->bm->batt_id == 1) { |
586 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | 610 | if (is_ab8540(di->parent)) { |
587 | dev_dbg(di->dev, "Set BATCTRL current source to 16uA\n"); | 611 | dev_dbg(di->dev, |
612 | "Set BATCTRL current source to 60uA\n"); | ||
613 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA; | ||
614 | } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
615 | dev_dbg(di->dev, | ||
616 | "Set BATCTRL current source to 16uA\n"); | ||
588 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; | 617 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; |
589 | } else { | 618 | } else { |
590 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); | 619 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); |
@@ -604,22 +633,37 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
604 | static void ab8500_btemp_periodic_work(struct work_struct *work) | 633 | static void ab8500_btemp_periodic_work(struct work_struct *work) |
605 | { | 634 | { |
606 | int interval; | 635 | int interval; |
636 | int bat_temp; | ||
607 | struct ab8500_btemp *di = container_of(work, | 637 | struct ab8500_btemp *di = container_of(work, |
608 | struct ab8500_btemp, btemp_periodic_work.work); | 638 | struct ab8500_btemp, btemp_periodic_work.work); |
609 | 639 | ||
610 | if (!di->initialized) { | 640 | if (!di->initialized) { |
611 | di->initialized = true; | ||
612 | /* Identify the battery */ | 641 | /* Identify the battery */ |
613 | if (ab8500_btemp_id(di) < 0) | 642 | if (ab8500_btemp_id(di) < 0) |
614 | dev_warn(di->dev, "failed to identify the battery\n"); | 643 | dev_warn(di->dev, "failed to identify the battery\n"); |
615 | } | 644 | } |
616 | 645 | ||
617 | di->bat_temp = ab8500_btemp_measure_temp(di); | 646 | bat_temp = ab8500_btemp_measure_temp(di); |
618 | 647 | /* | |
619 | if (di->bat_temp != di->prev_bat_temp) { | 648 | * Filter battery temperature. |
620 | di->prev_bat_temp = di->bat_temp; | 649 | * Allow direct updates on temperature only if two samples result in |
650 | * same temperature. Else only allow 1 degree change from previous | ||
651 | * reported value in the direction of the new measurement. | ||
652 | */ | ||
653 | if ((bat_temp == di->prev_bat_temp) || !di->initialized) { | ||
654 | if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) { | ||
655 | di->initialized = true; | ||
656 | di->bat_temp = bat_temp; | ||
657 | power_supply_changed(&di->btemp_psy); | ||
658 | } | ||
659 | } else if (bat_temp < di->prev_bat_temp) { | ||
660 | di->bat_temp--; | ||
661 | power_supply_changed(&di->btemp_psy); | ||
662 | } else if (bat_temp > di->prev_bat_temp) { | ||
663 | di->bat_temp++; | ||
621 | power_supply_changed(&di->btemp_psy); | 664 | power_supply_changed(&di->btemp_psy); |
622 | } | 665 | } |
666 | di->prev_bat_temp = bat_temp; | ||
623 | 667 | ||
624 | if (di->events.ac_conn || di->events.usb_conn) | 668 | if (di->events.ac_conn || di->events.usb_conn) |
625 | interval = di->bm->temp_interval_chg; | 669 | interval = di->bm->temp_interval_chg; |
@@ -772,7 +816,7 @@ static void ab8500_btemp_periodic(struct ab8500_btemp *di, | |||
772 | * | 816 | * |
773 | * Returns battery temperature | 817 | * Returns battery temperature |
774 | */ | 818 | */ |
775 | static int ab8500_btemp_get_temp(struct ab8500_btemp *di) | 819 | int ab8500_btemp_get_temp(struct ab8500_btemp *di) |
776 | { | 820 | { |
777 | int temp = 0; | 821 | int temp = 0; |
778 | 822 | ||
@@ -808,6 +852,7 @@ static int ab8500_btemp_get_temp(struct ab8500_btemp *di) | |||
808 | } | 852 | } |
809 | return temp; | 853 | return temp; |
810 | } | 854 | } |
855 | EXPORT_SYMBOL(ab8500_btemp_get_temp); | ||
811 | 856 | ||
812 | /** | 857 | /** |
813 | * ab8500_btemp_get_batctrl_temp() - get the temperature | 858 | * ab8500_btemp_get_batctrl_temp() - get the temperature |
@@ -819,6 +864,7 @@ int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp) | |||
819 | { | 864 | { |
820 | return btemp->bat_temp * 1000; | 865 | return btemp->bat_temp * 1000; |
821 | } | 866 | } |
867 | EXPORT_SYMBOL(ab8500_btemp_get_batctrl_temp); | ||
822 | 868 | ||
823 | /** | 869 | /** |
824 | * ab8500_btemp_get_property() - get the btemp properties | 870 | * ab8500_btemp_get_property() - get the btemp properties |