diff options
author | Anton Vorontsov <anton@enomsg.org> | 2013-01-05 20:14:22 -0500 |
---|---|---|
committer | Anton Vorontsov <anton@enomsg.org> | 2013-01-05 20:14:22 -0500 |
commit | 240fbe2347f1bb58c45fe07fd7c1e5ed96e2e983 (patch) | |
tree | 8481027b056197db888e51eae47a8f95931b84cb /drivers/power/ab8500_btemp.c | |
parent | 2fbb520d2079186727786b728ebc5bf20fc85520 (diff) | |
parent | 215cf5c93d2deda4df38d0c9b2429ab2e86808a5 (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.c | 96 |
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 | */ |
88 | struct ab8500_btemp { | 89 | struct 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[] = { | |||
967 | static int ab8500_btemp_probe(struct platform_device *pdev) | 976 | static 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; |