aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/ab8500_btemp.c
diff options
context:
space:
mode:
authorAnton Vorontsov <anton@enomsg.org>2013-01-05 20:14:22 -0500
committerAnton Vorontsov <anton@enomsg.org>2013-01-05 20:14:22 -0500
commit240fbe2347f1bb58c45fe07fd7c1e5ed96e2e983 (patch)
tree8481027b056197db888e51eae47a8f95931b84cb /drivers/power/ab8500_btemp.c
parent2fbb520d2079186727786b728ebc5bf20fc85520 (diff)
parent215cf5c93d2deda4df38d0c9b2429ab2e86808a5 (diff)
Merge branch 'for-anton' of git://git.linaro.org/people/ljones/linux-3.0-ux500
Diffstat (limited to 'drivers/power/ab8500_btemp.c')
-rw-r--r--drivers/power/ab8500_btemp.c96
1 files changed, 51 insertions, 45 deletions
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index 20e2a7d3ef43..e1d28039ce7b 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -78,12 +78,13 @@ struct ab8500_btemp_ranges {
78 * @parent: Pointer to the struct ab8500 78 * @parent: Pointer to the struct ab8500
79 * @gpadc: Pointer to the struct gpadc 79 * @gpadc: Pointer to the struct gpadc
80 * @fg: Pointer to the struct fg 80 * @fg: Pointer to the struct fg
81 * @bat: Pointer to the abx500_bm platform data 81 * @bm: Platform specific battery management information
82 * @btemp_psy: Structure for BTEMP specific battery properties 82 * @btemp_psy: Structure for BTEMP specific battery properties
83 * @events: Structure for information about events triggered 83 * @events: Structure for information about events triggered
84 * @btemp_ranges: Battery temperature range structure 84 * @btemp_ranges: Battery temperature range structure
85 * @btemp_wq: Work queue for measuring the temperature periodically 85 * @btemp_wq: Work queue for measuring the temperature periodically
86 * @btemp_periodic_work: Work for measuring the temperature periodically 86 * @btemp_periodic_work: Work for measuring the temperature periodically
87 * @initialized: True if battery id read.
87 */ 88 */
88struct ab8500_btemp { 89struct ab8500_btemp {
89 struct device *dev; 90 struct device *dev;
@@ -94,12 +95,13 @@ struct ab8500_btemp {
94 struct ab8500 *parent; 95 struct ab8500 *parent;
95 struct ab8500_gpadc *gpadc; 96 struct ab8500_gpadc *gpadc;
96 struct ab8500_fg *fg; 97 struct ab8500_fg *fg;
97 struct abx500_bm_data *bat; 98 struct abx500_bm_data *bm;
98 struct power_supply btemp_psy; 99 struct power_supply btemp_psy;
99 struct ab8500_btemp_events events; 100 struct ab8500_btemp_events events;
100 struct ab8500_btemp_ranges btemp_ranges; 101 struct ab8500_btemp_ranges btemp_ranges;
101 struct workqueue_struct *btemp_wq; 102 struct workqueue_struct *btemp_wq;
102 struct delayed_work btemp_periodic_work; 103 struct delayed_work btemp_periodic_work;
104 bool initialized;
103}; 105};
104 106
105/* BTEMP power supply properties */ 107/* BTEMP power supply properties */
@@ -147,13 +149,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
147 return (450000 * (v_batctrl)) / (1800 - v_batctrl); 149 return (450000 * (v_batctrl)) / (1800 - v_batctrl);
148 } 150 }
149 151
150 if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) { 152 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
151 /* 153 /*
152 * If the battery has internal NTC, we use the current 154 * If the battery has internal NTC, we use the current
153 * source to calculate the resistance, 7uA or 20uA 155 * source to calculate the resistance, 7uA or 20uA
154 */ 156 */
155 rbs = (v_batctrl * 1000 157 rbs = (v_batctrl * 1000
156 - di->bat->gnd_lift_resistance * inst_curr) 158 - di->bm->gnd_lift_resistance * inst_curr)
157 / di->curr_source; 159 / di->curr_source;
158 } else { 160 } else {
159 /* 161 /*
@@ -209,7 +211,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
209 return 0; 211 return 0;
210 212
211 /* Only do this for batteries with internal NTC */ 213 /* Only do this for batteries with internal NTC */
212 if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { 214 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
213 if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA) 215 if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
214 curr = BAT_CTRL_7U_ENA; 216 curr = BAT_CTRL_7U_ENA;
215 else 217 else
@@ -241,7 +243,7 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
241 __func__); 243 __func__);
242 goto disable_curr_source; 244 goto disable_curr_source;
243 } 245 }
244 } else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { 246 } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
245 dev_dbg(di->dev, "Disable BATCTRL curr source\n"); 247 dev_dbg(di->dev, "Disable BATCTRL curr source\n");
246 248
247 /* Write 0 to the curr bits */ 249 /* Write 0 to the curr bits */
@@ -457,9 +459,9 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
457 int rbat, rntc, vntc; 459 int rbat, rntc, vntc;
458 u8 id; 460 u8 id;
459 461
460 id = di->bat->batt_id; 462 id = di->bm->batt_id;
461 463
462 if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && 464 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
463 id != BATTERY_UNKNOWN) { 465 id != BATTERY_UNKNOWN) {
464 466
465 rbat = ab8500_btemp_get_batctrl_res(di); 467 rbat = ab8500_btemp_get_batctrl_res(di);
@@ -474,8 +476,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
474 } 476 }
475 477
476 temp = ab8500_btemp_res_to_temp(di, 478 temp = ab8500_btemp_res_to_temp(di,
477 di->bat->bat_type[id].r_to_t_tbl, 479 di->bm->bat_type[id].r_to_t_tbl,
478 di->bat->bat_type[id].n_temp_tbl_elements, rbat); 480 di->bm->bat_type[id].n_temp_tbl_elements, rbat);
479 } else { 481 } else {
480 vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL); 482 vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
481 if (vntc < 0) { 483 if (vntc < 0) {
@@ -491,8 +493,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
491 rntc = 230000 * vntc / (VTVOUT_V - vntc); 493 rntc = 230000 * vntc / (VTVOUT_V - vntc);
492 494
493 temp = ab8500_btemp_res_to_temp(di, 495 temp = ab8500_btemp_res_to_temp(di,
494 di->bat->bat_type[id].r_to_t_tbl, 496 di->bm->bat_type[id].r_to_t_tbl,
495 di->bat->bat_type[id].n_temp_tbl_elements, rntc); 497 di->bm->bat_type[id].n_temp_tbl_elements, rntc);
496 prev = temp; 498 prev = temp;
497 } 499 }
498 dev_dbg(di->dev, "Battery temperature is %d\n", temp); 500 dev_dbg(di->dev, "Battery temperature is %d\n", temp);
@@ -513,7 +515,7 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
513 u8 i; 515 u8 i;
514 516
515 di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; 517 di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
516 di->bat->batt_id = BATTERY_UNKNOWN; 518 di->bm->batt_id = BATTERY_UNKNOWN;
517 519
518 res = ab8500_btemp_get_batctrl_res(di); 520 res = ab8500_btemp_get_batctrl_res(di);
519 if (res < 0) { 521 if (res < 0) {
@@ -522,23 +524,23 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
522 } 524 }
523 525
524 /* BATTERY_UNKNOWN is defined on position 0, skip it! */ 526 /* BATTERY_UNKNOWN is defined on position 0, skip it! */
525 for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) { 527 for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
526 if ((res <= di->bat->bat_type[i].resis_high) && 528 if ((res <= di->bm->bat_type[i].resis_high) &&
527 (res >= di->bat->bat_type[i].resis_low)) { 529 (res >= di->bm->bat_type[i].resis_low)) {
528 dev_dbg(di->dev, "Battery detected on %s" 530 dev_dbg(di->dev, "Battery detected on %s"
529 " low %d < res %d < high: %d" 531 " low %d < res %d < high: %d"
530 " index: %d\n", 532 " index: %d\n",
531 di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ? 533 di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
532 "BATCTRL" : "BATTEMP", 534 "BATCTRL" : "BATTEMP",
533 di->bat->bat_type[i].resis_low, res, 535 di->bm->bat_type[i].resis_low, res,
534 di->bat->bat_type[i].resis_high, i); 536 di->bm->bat_type[i].resis_high, i);
535 537
536 di->bat->batt_id = i; 538 di->bm->batt_id = i;
537 break; 539 break;
538 } 540 }
539 } 541 }
540 542
541 if (di->bat->batt_id == BATTERY_UNKNOWN) { 543 if (di->bm->batt_id == BATTERY_UNKNOWN) {
542 dev_warn(di->dev, "Battery identified as unknown" 544 dev_warn(di->dev, "Battery identified as unknown"
543 ", resistance %d Ohm\n", res); 545 ", resistance %d Ohm\n", res);
544 return -ENXIO; 546 return -ENXIO;
@@ -548,13 +550,13 @@ static int ab8500_btemp_id(struct ab8500_btemp *di)
548 * We only have to change current source if the 550 * We only have to change current source if the
549 * detected type is Type 1, else we use the 7uA source 551 * detected type is Type 1, else we use the 7uA source
550 */ 552 */
551 if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && 553 if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
552 di->bat->batt_id == 1) { 554 di->bm->batt_id == 1) {
553 dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); 555 dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
554 di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA; 556 di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
555 } 557 }
556 558
557 return di->bat->batt_id; 559 return di->bm->batt_id;
558} 560}
559 561
560/** 562/**
@@ -569,6 +571,13 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
569 struct ab8500_btemp *di = container_of(work, 571 struct ab8500_btemp *di = container_of(work,
570 struct ab8500_btemp, btemp_periodic_work.work); 572 struct ab8500_btemp, btemp_periodic_work.work);
571 573
574 if (!di->initialized) {
575 di->initialized = true;
576 /* Identify the battery */
577 if (ab8500_btemp_id(di) < 0)
578 dev_warn(di->dev, "failed to identify the battery\n");
579 }
580
572 di->bat_temp = ab8500_btemp_measure_temp(di); 581 di->bat_temp = ab8500_btemp_measure_temp(di);
573 582
574 if (di->bat_temp != di->prev_bat_temp) { 583 if (di->bat_temp != di->prev_bat_temp) {
@@ -577,9 +586,9 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
577 } 586 }
578 587
579 if (di->events.ac_conn || di->events.usb_conn) 588 if (di->events.ac_conn || di->events.usb_conn)
580 interval = di->bat->temp_interval_chg; 589 interval = di->bm->temp_interval_chg;
581 else 590 else
582 interval = di->bat->temp_interval_nochg; 591 interval = di->bm->temp_interval_nochg;
583 592
584 /* Schedule a new measurement */ 593 /* Schedule a new measurement */
585 queue_delayed_work(di->btemp_wq, 594 queue_delayed_work(di->btemp_wq,
@@ -806,7 +815,7 @@ static int ab8500_btemp_get_property(struct power_supply *psy,
806 val->intval = 1; 815 val->intval = 1;
807 break; 816 break;
808 case POWER_SUPPLY_PROP_TECHNOLOGY: 817 case POWER_SUPPLY_PROP_TECHNOLOGY:
809 val->intval = di->bat->bat_type[di->bat->batt_id].name; 818 val->intval = di->bm->bat_type[di->bm->batt_id].name;
810 break; 819 break;
811 case POWER_SUPPLY_PROP_TEMP: 820 case POWER_SUPPLY_PROP_TEMP:
812 val->intval = ab8500_btemp_get_temp(di); 821 val->intval = ab8500_btemp_get_temp(di);
@@ -967,6 +976,7 @@ static char *supply_interface[] = {
967static int ab8500_btemp_probe(struct platform_device *pdev) 976static int ab8500_btemp_probe(struct platform_device *pdev)
968{ 977{
969 struct device_node *np = pdev->dev.of_node; 978 struct device_node *np = pdev->dev.of_node;
979 struct abx500_bm_data *plat = pdev->dev.platform_data;
970 struct ab8500_btemp *di; 980 struct ab8500_btemp *di;
971 int irq, i, ret = 0; 981 int irq, i, ret = 0;
972 u8 val; 982 u8 val;
@@ -976,21 +986,19 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
976 dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); 986 dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
977 return -ENOMEM; 987 return -ENOMEM;
978 } 988 }
979 di->bat = pdev->mfd_cell->platform_data; 989
980 if (!di->bat) { 990 if (!plat) {
981 if (np) { 991 dev_err(&pdev->dev, "no battery management data supplied\n");
982 ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); 992 return -EINVAL;
983 if (ret) { 993 }
984 dev_err(&pdev->dev, 994 di->bm = plat;
985 "failed to get battery information\n"); 995
986 return ret; 996 if (np) {
987 } 997 ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
988 } else { 998 if (ret) {
989 dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n"); 999 dev_err(&pdev->dev, "failed to get battery information\n");
990 return -EINVAL; 1000 return ret;
991 } 1001 }
992 } else {
993 dev_info(&pdev->dev, "falling back to legacy platform data\n");
994 } 1002 }
995 1003
996 /* get parent data */ 1004 /* get parent data */
@@ -998,6 +1006,8 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
998 di->parent = dev_get_drvdata(pdev->dev.parent); 1006 di->parent = dev_get_drvdata(pdev->dev.parent);
999 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); 1007 di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1000 1008
1009 di->initialized = false;
1010
1001 /* BTEMP supply */ 1011 /* BTEMP supply */
1002 di->btemp_psy.name = "ab8500_btemp"; 1012 di->btemp_psy.name = "ab8500_btemp";
1003 di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; 1013 di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
@@ -1022,10 +1032,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
1022 INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, 1032 INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
1023 ab8500_btemp_periodic_work); 1033 ab8500_btemp_periodic_work);
1024 1034
1025 /* Identify the battery */
1026 if (ab8500_btemp_id(di) < 0)
1027 dev_warn(di->dev, "failed to identify the battery\n");
1028
1029 /* Set BTEMP thermal limits. Low and Med are fixed */ 1035 /* Set BTEMP thermal limits. Low and Med are fixed */
1030 di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; 1036 di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
1031 di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; 1037 di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;