aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/ab8500_btemp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/ab8500_btemp.c')
-rw-r--r--drivers/power/ab8500_btemp.c80
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}
134EXPORT_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 */
316disable_curr_source: 332disable_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)
604static void ab8500_btemp_periodic_work(struct work_struct *work) 633static 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 */
775static int ab8500_btemp_get_temp(struct ab8500_btemp *di) 819int 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}
855EXPORT_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}
867EXPORT_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