aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/abx500_chargalg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/abx500_chargalg.c')
-rw-r--r--drivers/power/abx500_chargalg.c204
1 files changed, 123 insertions, 81 deletions
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 297089146064..f043c0851a76 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -33,9 +33,6 @@
33/* End-of-charge criteria counter */ 33/* End-of-charge criteria counter */
34#define EOC_COND_CNT 10 34#define EOC_COND_CNT 10
35 35
36/* Recharge criteria counter */
37#define RCH_COND_CNT 3
38
39#define to_abx500_chargalg_device_info(x) container_of((x), \ 36#define to_abx500_chargalg_device_info(x) container_of((x), \
40 struct abx500_chargalg, chargalg_psy); 37 struct abx500_chargalg, chargalg_psy);
41 38
@@ -196,7 +193,6 @@ enum maxim_ret {
196 * @dev: pointer to the structure device 193 * @dev: pointer to the structure device
197 * @charge_status: battery operating status 194 * @charge_status: battery operating status
198 * @eoc_cnt: counter used to determine end-of_charge 195 * @eoc_cnt: counter used to determine end-of_charge
199 * @rch_cnt: counter used to determine start of recharge
200 * @maintenance_chg: indicate if maintenance charge is active 196 * @maintenance_chg: indicate if maintenance charge is active
201 * @t_hyst_norm temperature hysteresis when the temperature has been 197 * @t_hyst_norm temperature hysteresis when the temperature has been
202 * over or under normal limits 198 * over or under normal limits
@@ -207,7 +203,7 @@ enum maxim_ret {
207 * @chg_info: information about connected charger types 203 * @chg_info: information about connected charger types
208 * @batt_data: data of the battery 204 * @batt_data: data of the battery
209 * @susp_status: current charger suspension status 205 * @susp_status: current charger suspension status
210 * @bat: pointer to the abx500_bm platform data 206 * @bm: Platform specific battery management information
211 * @chargalg_psy: structure that holds the battery properties exposed by 207 * @chargalg_psy: structure that holds the battery properties exposed by
212 * the charging algorithm 208 * the charging algorithm
213 * @events: structure for information about events triggered 209 * @events: structure for information about events triggered
@@ -223,7 +219,6 @@ struct abx500_chargalg {
223 struct device *dev; 219 struct device *dev;
224 int charge_status; 220 int charge_status;
225 int eoc_cnt; 221 int eoc_cnt;
226 int rch_cnt;
227 bool maintenance_chg; 222 bool maintenance_chg;
228 int t_hyst_norm; 223 int t_hyst_norm;
229 int t_hyst_lowhigh; 224 int t_hyst_lowhigh;
@@ -232,7 +227,7 @@ struct abx500_chargalg {
232 struct abx500_chargalg_charger_info chg_info; 227 struct abx500_chargalg_charger_info chg_info;
233 struct abx500_chargalg_battery_data batt_data; 228 struct abx500_chargalg_battery_data batt_data;
234 struct abx500_chargalg_suspension_status susp_status; 229 struct abx500_chargalg_suspension_status susp_status;
235 struct abx500_bm_data *bat; 230 struct abx500_bm_data *bm;
236 struct power_supply chargalg_psy; 231 struct power_supply chargalg_psy;
237 struct ux500_charger *ac_chg; 232 struct ux500_charger *ac_chg;
238 struct ux500_charger *usb_chg; 233 struct ux500_charger *usb_chg;
@@ -367,13 +362,13 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
367 case AC_CHG: 362 case AC_CHG:
368 timer_expiration = 363 timer_expiration =
369 round_jiffies(jiffies + 364 round_jiffies(jiffies +
370 (di->bat->main_safety_tmr_h * 3600 * HZ)); 365 (di->bm->main_safety_tmr_h * 3600 * HZ));
371 break; 366 break;
372 367
373 case USB_CHG: 368 case USB_CHG:
374 timer_expiration = 369 timer_expiration =
375 round_jiffies(jiffies + 370 round_jiffies(jiffies +
376 (di->bat->usb_safety_tmr_h * 3600 * HZ)); 371 (di->bm->usb_safety_tmr_h * 3600 * HZ));
377 break; 372 break;
378 373
379 default: 374 default:
@@ -450,8 +445,18 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di)
450{ 445{
451 /* Check if charger exists and kick watchdog if charging */ 446 /* Check if charger exists and kick watchdog if charging */
452 if (di->ac_chg && di->ac_chg->ops.kick_wd && 447 if (di->ac_chg && di->ac_chg->ops.kick_wd &&
453 di->chg_info.online_chg & AC_CHG) 448 di->chg_info.online_chg & AC_CHG) {
449 /*
450 * If AB charger watchdog expired, pm2xxx charging
451 * gets disabled. To be safe, kick both AB charger watchdog
452 * and pm2xxx watchdog.
453 */
454 if (di->ac_chg->external &&
455 di->usb_chg && di->usb_chg->ops.kick_wd)
456 di->usb_chg->ops.kick_wd(di->usb_chg);
457
454 return di->ac_chg->ops.kick_wd(di->ac_chg); 458 return di->ac_chg->ops.kick_wd(di->ac_chg);
459 }
455 else if (di->usb_chg && di->usb_chg->ops.kick_wd && 460 else if (di->usb_chg && di->usb_chg->ops.kick_wd &&
456 di->chg_info.online_chg & USB_CHG) 461 di->chg_info.online_chg & USB_CHG)
457 return di->usb_chg->ops.kick_wd(di->usb_chg); 462 return di->usb_chg->ops.kick_wd(di->usb_chg);
@@ -608,6 +613,8 @@ static void abx500_chargalg_hold_charging(struct abx500_chargalg *di)
608static void abx500_chargalg_start_charging(struct abx500_chargalg *di, 613static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
609 int vset, int iset) 614 int vset, int iset)
610{ 615{
616 bool start_chargalg_wd = true;
617
611 switch (di->chg_info.charger_type) { 618 switch (di->chg_info.charger_type) {
612 case AC_CHG: 619 case AC_CHG:
613 dev_dbg(di->dev, 620 dev_dbg(di->dev,
@@ -625,8 +632,12 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
625 632
626 default: 633 default:
627 dev_err(di->dev, "Unknown charger to charge from\n"); 634 dev_err(di->dev, "Unknown charger to charge from\n");
635 start_chargalg_wd = false;
628 break; 636 break;
629 } 637 }
638
639 if (start_chargalg_wd && !delayed_work_pending(&di->chargalg_wd_work))
640 queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0);
630} 641}
631 642
632/** 643/**
@@ -638,32 +649,32 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
638 */ 649 */
639static void abx500_chargalg_check_temp(struct abx500_chargalg *di) 650static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
640{ 651{
641 if (di->batt_data.temp > (di->bat->temp_low + di->t_hyst_norm) && 652 if (di->batt_data.temp > (di->bm->temp_low + di->t_hyst_norm) &&
642 di->batt_data.temp < (di->bat->temp_high - di->t_hyst_norm)) { 653 di->batt_data.temp < (di->bm->temp_high - di->t_hyst_norm)) {
643 /* Temp OK! */ 654 /* Temp OK! */
644 di->events.btemp_underover = false; 655 di->events.btemp_underover = false;
645 di->events.btemp_lowhigh = false; 656 di->events.btemp_lowhigh = false;
646 di->t_hyst_norm = 0; 657 di->t_hyst_norm = 0;
647 di->t_hyst_lowhigh = 0; 658 di->t_hyst_lowhigh = 0;
648 } else { 659 } else {
649 if (((di->batt_data.temp >= di->bat->temp_high) && 660 if (((di->batt_data.temp >= di->bm->temp_high) &&
650 (di->batt_data.temp < 661 (di->batt_data.temp <
651 (di->bat->temp_over - di->t_hyst_lowhigh))) || 662 (di->bm->temp_over - di->t_hyst_lowhigh))) ||
652 ((di->batt_data.temp > 663 ((di->batt_data.temp >
653 (di->bat->temp_under + di->t_hyst_lowhigh)) && 664 (di->bm->temp_under + di->t_hyst_lowhigh)) &&
654 (di->batt_data.temp <= di->bat->temp_low))) { 665 (di->batt_data.temp <= di->bm->temp_low))) {
655 /* TEMP minor!!!!! */ 666 /* TEMP minor!!!!! */
656 di->events.btemp_underover = false; 667 di->events.btemp_underover = false;
657 di->events.btemp_lowhigh = true; 668 di->events.btemp_lowhigh = true;
658 di->t_hyst_norm = di->bat->temp_hysteresis; 669 di->t_hyst_norm = di->bm->temp_hysteresis;
659 di->t_hyst_lowhigh = 0; 670 di->t_hyst_lowhigh = 0;
660 } else if (di->batt_data.temp <= di->bat->temp_under || 671 } else if (di->batt_data.temp <= di->bm->temp_under ||
661 di->batt_data.temp >= di->bat->temp_over) { 672 di->batt_data.temp >= di->bm->temp_over) {
662 /* TEMP major!!!!! */ 673 /* TEMP major!!!!! */
663 di->events.btemp_underover = true; 674 di->events.btemp_underover = true;
664 di->events.btemp_lowhigh = false; 675 di->events.btemp_lowhigh = false;
665 di->t_hyst_norm = 0; 676 di->t_hyst_norm = 0;
666 di->t_hyst_lowhigh = di->bat->temp_hysteresis; 677 di->t_hyst_lowhigh = di->bm->temp_hysteresis;
667 } else { 678 } else {
668 /* Within hysteresis */ 679 /* Within hysteresis */
669 dev_dbg(di->dev, "Within hysteresis limit temp: %d " 680 dev_dbg(di->dev, "Within hysteresis limit temp: %d "
@@ -682,12 +693,12 @@ static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
682 */ 693 */
683static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di) 694static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di)
684{ 695{
685 if (di->chg_info.usb_volt > di->bat->chg_params->usb_volt_max) 696 if (di->chg_info.usb_volt > di->bm->chg_params->usb_volt_max)
686 di->chg_info.usb_chg_ok = false; 697 di->chg_info.usb_chg_ok = false;
687 else 698 else
688 di->chg_info.usb_chg_ok = true; 699 di->chg_info.usb_chg_ok = true;
689 700
690 if (di->chg_info.ac_volt > di->bat->chg_params->ac_volt_max) 701 if (di->chg_info.ac_volt > di->bm->chg_params->ac_volt_max)
691 di->chg_info.ac_chg_ok = false; 702 di->chg_info.ac_chg_ok = false;
692 else 703 else
693 di->chg_info.ac_chg_ok = true; 704 di->chg_info.ac_chg_ok = true;
@@ -707,10 +718,10 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
707 if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING && 718 if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
708 di->charge_state == STATE_NORMAL && 719 di->charge_state == STATE_NORMAL &&
709 !di->maintenance_chg && (di->batt_data.volt >= 720 !di->maintenance_chg && (di->batt_data.volt >=
710 di->bat->bat_type[di->bat->batt_id].termination_vol || 721 di->bm->bat_type[di->bm->batt_id].termination_vol ||
711 di->events.usb_cv_active || di->events.ac_cv_active) && 722 di->events.usb_cv_active || di->events.ac_cv_active) &&
712 di->batt_data.avg_curr < 723 di->batt_data.avg_curr <
713 di->bat->bat_type[di->bat->batt_id].termination_curr && 724 di->bm->bat_type[di->bm->batt_id].termination_curr &&
714 di->batt_data.avg_curr > 0) { 725 di->batt_data.avg_curr > 0) {
715 if (++di->eoc_cnt >= EOC_COND_CNT) { 726 if (++di->eoc_cnt >= EOC_COND_CNT) {
716 di->eoc_cnt = 0; 727 di->eoc_cnt = 0;
@@ -733,12 +744,12 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
733static void init_maxim_chg_curr(struct abx500_chargalg *di) 744static void init_maxim_chg_curr(struct abx500_chargalg *di)
734{ 745{
735 di->ccm.original_iset = 746 di->ccm.original_iset =
736 di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; 747 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
737 di->ccm.current_iset = 748 di->ccm.current_iset =
738 di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; 749 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
739 di->ccm.test_delta_i = di->bat->maxi->charger_curr_step; 750 di->ccm.test_delta_i = di->bm->maxi->charger_curr_step;
740 di->ccm.max_current = di->bat->maxi->chg_curr; 751 di->ccm.max_current = di->bm->maxi->chg_curr;
741 di->ccm.condition_cnt = di->bat->maxi->wait_cycles; 752 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
742 di->ccm.level = 0; 753 di->ccm.level = 0;
743} 754}
744 755
@@ -755,7 +766,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
755{ 766{
756 int delta_i; 767 int delta_i;
757 768
758 if (!di->bat->maxi->ena_maxi) 769 if (!di->bm->maxi->ena_maxi)
759 return MAXIM_RET_NOACTION; 770 return MAXIM_RET_NOACTION;
760 771
761 delta_i = di->ccm.original_iset - di->batt_data.inst_curr; 772 delta_i = di->ccm.original_iset - di->batt_data.inst_curr;
@@ -766,7 +777,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
766 if (di->ccm.wait_cnt == 0) { 777 if (di->ccm.wait_cnt == 0) {
767 dev_dbg(di->dev, "lowering current\n"); 778 dev_dbg(di->dev, "lowering current\n");
768 di->ccm.wait_cnt++; 779 di->ccm.wait_cnt++;
769 di->ccm.condition_cnt = di->bat->maxi->wait_cycles; 780 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
770 di->ccm.max_current = 781 di->ccm.max_current =
771 di->ccm.current_iset - di->ccm.test_delta_i; 782 di->ccm.current_iset - di->ccm.test_delta_i;
772 di->ccm.current_iset = di->ccm.max_current; 783 di->ccm.current_iset = di->ccm.max_current;
@@ -791,7 +802,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
791 if (di->ccm.current_iset == di->ccm.original_iset) 802 if (di->ccm.current_iset == di->ccm.original_iset)
792 return MAXIM_RET_NOACTION; 803 return MAXIM_RET_NOACTION;
793 804
794 di->ccm.condition_cnt = di->bat->maxi->wait_cycles; 805 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
795 di->ccm.current_iset = di->ccm.original_iset; 806 di->ccm.current_iset = di->ccm.original_iset;
796 di->ccm.level = 0; 807 di->ccm.level = 0;
797 808
@@ -803,7 +814,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
803 di->ccm.max_current) { 814 di->ccm.max_current) {
804 if (di->ccm.condition_cnt-- == 0) { 815 if (di->ccm.condition_cnt-- == 0) {
805 /* Increse the iset with cco.test_delta_i */ 816 /* Increse the iset with cco.test_delta_i */
806 di->ccm.condition_cnt = di->bat->maxi->wait_cycles; 817 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
807 di->ccm.current_iset += di->ccm.test_delta_i; 818 di->ccm.current_iset += di->ccm.test_delta_i;
808 di->ccm.level++; 819 di->ccm.level++;
809 dev_dbg(di->dev, " Maximization needed, increase" 820 dev_dbg(di->dev, " Maximization needed, increase"
@@ -818,7 +829,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
818 return MAXIM_RET_NOACTION; 829 return MAXIM_RET_NOACTION;
819 } 830 }
820 } else { 831 } else {
821 di->ccm.condition_cnt = di->bat->maxi->wait_cycles; 832 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
822 return MAXIM_RET_NOACTION; 833 return MAXIM_RET_NOACTION;
823 } 834 }
824} 835}
@@ -838,7 +849,7 @@ static void handle_maxim_chg_curr(struct abx500_chargalg *di)
838 break; 849 break;
839 case MAXIM_RET_IBAT_TOO_HIGH: 850 case MAXIM_RET_IBAT_TOO_HIGH:
840 result = abx500_chargalg_update_chg_curr(di, 851 result = abx500_chargalg_update_chg_curr(di,
841 di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); 852 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
842 if (result) 853 if (result)
843 dev_err(di->dev, "failed to set chg curr\n"); 854 dev_err(di->dev, "failed to set chg curr\n");
844 break; 855 break;
@@ -858,6 +869,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
858 union power_supply_propval ret; 869 union power_supply_propval ret;
859 int i, j; 870 int i, j;
860 bool psy_found = false; 871 bool psy_found = false;
872 bool capacity_updated = false;
861 873
862 psy = (struct power_supply *)data; 874 psy = (struct power_supply *)data;
863 ext = dev_get_drvdata(dev); 875 ext = dev_get_drvdata(dev);
@@ -870,6 +882,16 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
870 if (!psy_found) 882 if (!psy_found)
871 return 0; 883 return 0;
872 884
885 /*
886 * If external is not registering 'POWER_SUPPLY_PROP_CAPACITY' to its
887 * property because of handling that sysfs entry on its own, this is
888 * the place to get the battery capacity.
889 */
890 if (!ext->get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
891 di->batt_data.percent = ret.intval;
892 capacity_updated = true;
893 }
894
873 /* Go through all properties for the psy */ 895 /* Go through all properties for the psy */
874 for (j = 0; j < ext->num_properties; j++) { 896 for (j = 0; j < ext->num_properties; j++) {
875 enum power_supply_property prop; 897 enum power_supply_property prop;
@@ -1154,7 +1176,8 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
1154 } 1176 }
1155 break; 1177 break;
1156 case POWER_SUPPLY_PROP_CAPACITY: 1178 case POWER_SUPPLY_PROP_CAPACITY:
1157 di->batt_data.percent = ret.intval; 1179 if (!capacity_updated)
1180 di->batt_data.percent = ret.intval;
1158 break; 1181 break;
1159 default: 1182 default:
1160 break; 1183 break;
@@ -1210,7 +1233,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1210 * this way 1233 * this way
1211 */ 1234 */
1212 if (!charger_status || 1235 if (!charger_status ||
1213 (di->events.batt_unknown && !di->bat->chg_unknown_bat)) { 1236 (di->events.batt_unknown && !di->bm->chg_unknown_bat)) {
1214 if (di->charge_state != STATE_HANDHELD) { 1237 if (di->charge_state != STATE_HANDHELD) {
1215 di->events.safety_timer_expired = false; 1238 di->events.safety_timer_expired = false;
1216 abx500_chargalg_state_to(di, STATE_HANDHELD_INIT); 1239 abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
@@ -1394,8 +1417,8 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1394 1417
1395 case STATE_NORMAL_INIT: 1418 case STATE_NORMAL_INIT:
1396 abx500_chargalg_start_charging(di, 1419 abx500_chargalg_start_charging(di,
1397 di->bat->bat_type[di->bat->batt_id].normal_vol_lvl, 1420 di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
1398 di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); 1421 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
1399 abx500_chargalg_state_to(di, STATE_NORMAL); 1422 abx500_chargalg_state_to(di, STATE_NORMAL);
1400 abx500_chargalg_start_safety_timer(di); 1423 abx500_chargalg_start_safety_timer(di);
1401 abx500_chargalg_stop_maintenance_timer(di); 1424 abx500_chargalg_stop_maintenance_timer(di);
@@ -1411,7 +1434,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1411 handle_maxim_chg_curr(di); 1434 handle_maxim_chg_curr(di);
1412 if (di->charge_status == POWER_SUPPLY_STATUS_FULL && 1435 if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
1413 di->maintenance_chg) { 1436 di->maintenance_chg) {
1414 if (di->bat->no_maintenance) 1437 if (di->bm->no_maintenance)
1415 abx500_chargalg_state_to(di, 1438 abx500_chargalg_state_to(di,
1416 STATE_WAIT_FOR_RECHARGE_INIT); 1439 STATE_WAIT_FOR_RECHARGE_INIT);
1417 else 1440 else
@@ -1424,28 +1447,25 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1424 case STATE_WAIT_FOR_RECHARGE_INIT: 1447 case STATE_WAIT_FOR_RECHARGE_INIT:
1425 abx500_chargalg_hold_charging(di); 1448 abx500_chargalg_hold_charging(di);
1426 abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE); 1449 abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE);
1427 di->rch_cnt = RCH_COND_CNT;
1428 /* Intentional fallthrough */ 1450 /* Intentional fallthrough */
1429 1451
1430 case STATE_WAIT_FOR_RECHARGE: 1452 case STATE_WAIT_FOR_RECHARGE:
1431 if (di->batt_data.volt <= 1453 if (di->batt_data.percent <=
1432 di->bat->bat_type[di->bat->batt_id].recharge_vol) { 1454 di->bm->bat_type[di->bm->batt_id].
1433 if (di->rch_cnt-- == 0) 1455 recharge_cap)
1434 abx500_chargalg_state_to(di, STATE_NORMAL_INIT); 1456 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1435 } else
1436 di->rch_cnt = RCH_COND_CNT;
1437 break; 1457 break;
1438 1458
1439 case STATE_MAINTENANCE_A_INIT: 1459 case STATE_MAINTENANCE_A_INIT:
1440 abx500_chargalg_stop_safety_timer(di); 1460 abx500_chargalg_stop_safety_timer(di);
1441 abx500_chargalg_start_maintenance_timer(di, 1461 abx500_chargalg_start_maintenance_timer(di,
1442 di->bat->bat_type[ 1462 di->bm->bat_type[
1443 di->bat->batt_id].maint_a_chg_timer_h); 1463 di->bm->batt_id].maint_a_chg_timer_h);
1444 abx500_chargalg_start_charging(di, 1464 abx500_chargalg_start_charging(di,
1445 di->bat->bat_type[ 1465 di->bm->bat_type[
1446 di->bat->batt_id].maint_a_vol_lvl, 1466 di->bm->batt_id].maint_a_vol_lvl,
1447 di->bat->bat_type[ 1467 di->bm->bat_type[
1448 di->bat->batt_id].maint_a_cur_lvl); 1468 di->bm->batt_id].maint_a_cur_lvl);
1449 abx500_chargalg_state_to(di, STATE_MAINTENANCE_A); 1469 abx500_chargalg_state_to(di, STATE_MAINTENANCE_A);
1450 power_supply_changed(&di->chargalg_psy); 1470 power_supply_changed(&di->chargalg_psy);
1451 /* Intentional fallthrough*/ 1471 /* Intentional fallthrough*/
@@ -1459,13 +1479,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1459 1479
1460 case STATE_MAINTENANCE_B_INIT: 1480 case STATE_MAINTENANCE_B_INIT:
1461 abx500_chargalg_start_maintenance_timer(di, 1481 abx500_chargalg_start_maintenance_timer(di,
1462 di->bat->bat_type[ 1482 di->bm->bat_type[
1463 di->bat->batt_id].maint_b_chg_timer_h); 1483 di->bm->batt_id].maint_b_chg_timer_h);
1464 abx500_chargalg_start_charging(di, 1484 abx500_chargalg_start_charging(di,
1465 di->bat->bat_type[ 1485 di->bm->bat_type[
1466 di->bat->batt_id].maint_b_vol_lvl, 1486 di->bm->batt_id].maint_b_vol_lvl,
1467 di->bat->bat_type[ 1487 di->bm->bat_type[
1468 di->bat->batt_id].maint_b_cur_lvl); 1488 di->bm->batt_id].maint_b_cur_lvl);
1469 abx500_chargalg_state_to(di, STATE_MAINTENANCE_B); 1489 abx500_chargalg_state_to(di, STATE_MAINTENANCE_B);
1470 power_supply_changed(&di->chargalg_psy); 1490 power_supply_changed(&di->chargalg_psy);
1471 /* Intentional fallthrough*/ 1491 /* Intentional fallthrough*/
@@ -1479,10 +1499,10 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1479 1499
1480 case STATE_TEMP_LOWHIGH_INIT: 1500 case STATE_TEMP_LOWHIGH_INIT:
1481 abx500_chargalg_start_charging(di, 1501 abx500_chargalg_start_charging(di,
1482 di->bat->bat_type[ 1502 di->bm->bat_type[
1483 di->bat->batt_id].low_high_vol_lvl, 1503 di->bm->batt_id].low_high_vol_lvl,
1484 di->bat->bat_type[ 1504 di->bm->bat_type[
1485 di->bat->batt_id].low_high_cur_lvl); 1505 di->bm->batt_id].low_high_cur_lvl);
1486 abx500_chargalg_stop_maintenance_timer(di); 1506 abx500_chargalg_stop_maintenance_timer(di);
1487 di->charge_status = POWER_SUPPLY_STATUS_CHARGING; 1507 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
1488 abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); 1508 abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
@@ -1543,11 +1563,11 @@ static void abx500_chargalg_periodic_work(struct work_struct *work)
1543 if (di->chg_info.conn_chg) 1563 if (di->chg_info.conn_chg)
1544 queue_delayed_work(di->chargalg_wq, 1564 queue_delayed_work(di->chargalg_wq,
1545 &di->chargalg_periodic_work, 1565 &di->chargalg_periodic_work,
1546 di->bat->interval_charging * HZ); 1566 di->bm->interval_charging * HZ);
1547 else 1567 else
1548 queue_delayed_work(di->chargalg_wq, 1568 queue_delayed_work(di->chargalg_wq,
1549 &di->chargalg_periodic_work, 1569 &di->chargalg_periodic_work,
1550 di->bat->interval_not_charging * HZ); 1570 di->bm->interval_not_charging * HZ);
1551} 1571}
1552 1572
1553/** 1573/**
@@ -1614,10 +1634,13 @@ static int abx500_chargalg_get_property(struct power_supply *psy,
1614 if (di->events.batt_ovv) { 1634 if (di->events.batt_ovv) {
1615 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 1635 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1616 } else if (di->events.btemp_underover) { 1636 } else if (di->events.btemp_underover) {
1617 if (di->batt_data.temp <= di->bat->temp_under) 1637 if (di->batt_data.temp <= di->bm->temp_under)
1618 val->intval = POWER_SUPPLY_HEALTH_COLD; 1638 val->intval = POWER_SUPPLY_HEALTH_COLD;
1619 else 1639 else
1620 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 1640 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
1641 } else if (di->charge_state == STATE_SAFETY_TIMER_EXPIRED ||
1642 di->charge_state == STATE_SAFETY_TIMER_EXPIRED_INIT) {
1643 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
1621 } else { 1644 } else {
1622 val->intval = POWER_SUPPLY_HEALTH_GOOD; 1645 val->intval = POWER_SUPPLY_HEALTH_GOOD;
1623 } 1646 }
@@ -1631,6 +1654,25 @@ static int abx500_chargalg_get_property(struct power_supply *psy,
1631/* Exposure to the sysfs interface */ 1654/* Exposure to the sysfs interface */
1632 1655
1633/** 1656/**
1657 * abx500_chargalg_sysfs_show() - sysfs show operations
1658 * @kobj: pointer to the struct kobject
1659 * @attr: pointer to the struct attribute
1660 * @buf: buffer that holds the parameter to send to userspace
1661 *
1662 * Returns a buffer to be displayed in user space
1663 */
1664static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
1665 struct attribute *attr, char *buf)
1666{
1667 struct abx500_chargalg *di = container_of(kobj,
1668 struct abx500_chargalg, chargalg_kobject);
1669
1670 return sprintf(buf, "%d\n",
1671 di->susp_status.ac_suspended &&
1672 di->susp_status.usb_suspended);
1673}
1674
1675/**
1634 * abx500_chargalg_sysfs_charger() - sysfs store operations 1676 * abx500_chargalg_sysfs_charger() - sysfs store operations
1635 * @kobj: pointer to the struct kobject 1677 * @kobj: pointer to the struct kobject
1636 * @attr: pointer to the struct attribute 1678 * @attr: pointer to the struct attribute
@@ -1698,7 +1740,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj,
1698static struct attribute abx500_chargalg_en_charger = \ 1740static struct attribute abx500_chargalg_en_charger = \
1699{ 1741{
1700 .name = "chargalg", 1742 .name = "chargalg",
1701 .mode = S_IWUGO, 1743 .mode = S_IRUGO | S_IWUSR,
1702}; 1744};
1703 1745
1704static struct attribute *abx500_chargalg_chg[] = { 1746static struct attribute *abx500_chargalg_chg[] = {
@@ -1707,6 +1749,7 @@ static struct attribute *abx500_chargalg_chg[] = {
1707}; 1749};
1708 1750
1709static const struct sysfs_ops abx500_chargalg_sysfs_ops = { 1751static const struct sysfs_ops abx500_chargalg_sysfs_ops = {
1752 .show = abx500_chargalg_sysfs_show,
1710 .store = abx500_chargalg_sysfs_charger, 1753 .store = abx500_chargalg_sysfs_charger,
1711}; 1754};
1712 1755
@@ -1806,6 +1849,7 @@ static char *supply_interface[] = {
1806static int abx500_chargalg_probe(struct platform_device *pdev) 1849static int abx500_chargalg_probe(struct platform_device *pdev)
1807{ 1850{
1808 struct device_node *np = pdev->dev.of_node; 1851 struct device_node *np = pdev->dev.of_node;
1852 struct abx500_bm_data *plat = pdev->dev.platform_data;
1809 struct abx500_chargalg *di; 1853 struct abx500_chargalg *di;
1810 int ret = 0; 1854 int ret = 0;
1811 1855
@@ -1814,21 +1858,19 @@ static int abx500_chargalg_probe(struct platform_device *pdev)
1814 dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); 1858 dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
1815 return -ENOMEM; 1859 return -ENOMEM;
1816 } 1860 }
1817 di->bat = pdev->mfd_cell->platform_data; 1861
1818 if (!di->bat) { 1862 if (!plat) {
1819 if (np) { 1863 dev_err(&pdev->dev, "no battery management data supplied\n");
1820 ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); 1864 return -EINVAL;
1821 if (ret) { 1865 }
1822 dev_err(&pdev->dev, 1866 di->bm = plat;
1823 "failed to get battery information\n"); 1867
1824 return ret; 1868 if (np) {
1825 } 1869 ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
1826 } else { 1870 if (ret) {
1827 dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n"); 1871 dev_err(&pdev->dev, "failed to get battery information\n");
1828 return -EINVAL; 1872 return ret;
1829 } 1873 }
1830 } else {
1831 dev_info(&pdev->dev, "falling back to legacy platform data\n");
1832 } 1874 }
1833 1875
1834 /* get device struct */ 1876 /* get device struct */