1851 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) ST-Ericsson SA 20124 * Copyright (c) 2012 Sony Mobile Communications AB5 *6 * Charging algorithm driver for AB85007 *8 * Authors:9 * Johan Palsson <johan.palsson@stericsson.com>10 * Karl Komierowski <karl.komierowski@stericsson.com>11 * Arun R Murthy <arun.murthy@stericsson.com>12 * Author: Imre Sunyi <imre.sunyi@sonymobile.com>13 */14 15#include <linux/init.h>16#include <linux/module.h>17#include <linux/device.h>18#include <linux/component.h>19#include <linux/hrtimer.h>20#include <linux/interrupt.h>21#include <linux/delay.h>22#include <linux/slab.h>23#include <linux/platform_device.h>24#include <linux/power_supply.h>25#include <linux/completion.h>26#include <linux/workqueue.h>27#include <linux/kobject.h>28#include <linux/of.h>29#include <linux/mfd/core.h>30#include <linux/mfd/abx500.h>31#include <linux/mfd/abx500/ab8500.h>32#include <linux/notifier.h>33 34#include "ab8500-bm.h"35#include "ab8500-chargalg.h"36 37/* Watchdog kick interval */38#define CHG_WD_INTERVAL (6 * HZ)39 40/* End-of-charge criteria counter */41#define EOC_COND_CNT 1042 43/* One hour expressed in seconds */44#define ONE_HOUR_IN_SECONDS 360045 46/* Five minutes expressed in seconds */47#define FIVE_MINUTES_IN_SECONDS 30048 49/*50 * This is the battery capacity limit that will trigger a new51 * full charging cycle in the case where maintenance charging52 * has been disabled53 */54#define AB8500_RECHARGE_CAP 9555 56enum ab8500_chargers {57 NO_CHG,58 AC_CHG,59 USB_CHG,60};61 62struct ab8500_chargalg_charger_info {63 enum ab8500_chargers conn_chg;64 enum ab8500_chargers prev_conn_chg;65 enum ab8500_chargers online_chg;66 enum ab8500_chargers prev_online_chg;67 enum ab8500_chargers charger_type;68 bool usb_chg_ok;69 bool ac_chg_ok;70 int usb_volt_uv;71 int usb_curr_ua;72 int ac_volt_uv;73 int ac_curr_ua;74 int usb_vset_uv;75 int usb_iset_ua;76 int ac_vset_uv;77 int ac_iset_ua;78};79 80struct ab8500_chargalg_battery_data {81 int temp;82 int volt_uv;83 int avg_curr_ua;84 int inst_curr_ua;85 int percent;86};87 88enum ab8500_chargalg_states {89 STATE_HANDHELD_INIT,90 STATE_HANDHELD,91 STATE_CHG_NOT_OK_INIT,92 STATE_CHG_NOT_OK,93 STATE_HW_TEMP_PROTECT_INIT,94 STATE_HW_TEMP_PROTECT,95 STATE_NORMAL_INIT,96 STATE_NORMAL,97 STATE_WAIT_FOR_RECHARGE_INIT,98 STATE_WAIT_FOR_RECHARGE,99 STATE_MAINTENANCE_A_INIT,100 STATE_MAINTENANCE_A,101 STATE_MAINTENANCE_B_INIT,102 STATE_MAINTENANCE_B,103 STATE_TEMP_UNDEROVER_INIT,104 STATE_TEMP_UNDEROVER,105 STATE_TEMP_LOWHIGH_INIT,106 STATE_TEMP_LOWHIGH,107 STATE_OVV_PROTECT_INIT,108 STATE_OVV_PROTECT,109 STATE_SAFETY_TIMER_EXPIRED_INIT,110 STATE_SAFETY_TIMER_EXPIRED,111 STATE_BATT_REMOVED_INIT,112 STATE_BATT_REMOVED,113 STATE_WD_EXPIRED_INIT,114 STATE_WD_EXPIRED,115};116 117static const char * const states[] = {118 "HANDHELD_INIT",119 "HANDHELD",120 "CHG_NOT_OK_INIT",121 "CHG_NOT_OK",122 "HW_TEMP_PROTECT_INIT",123 "HW_TEMP_PROTECT",124 "NORMAL_INIT",125 "NORMAL",126 "WAIT_FOR_RECHARGE_INIT",127 "WAIT_FOR_RECHARGE",128 "MAINTENANCE_A_INIT",129 "MAINTENANCE_A",130 "MAINTENANCE_B_INIT",131 "MAINTENANCE_B",132 "TEMP_UNDEROVER_INIT",133 "TEMP_UNDEROVER",134 "TEMP_LOWHIGH_INIT",135 "TEMP_LOWHIGH",136 "OVV_PROTECT_INIT",137 "OVV_PROTECT",138 "SAFETY_TIMER_EXPIRED_INIT",139 "SAFETY_TIMER_EXPIRED",140 "BATT_REMOVED_INIT",141 "BATT_REMOVED",142 "WD_EXPIRED_INIT",143 "WD_EXPIRED",144};145 146struct ab8500_chargalg_events {147 bool batt_unknown;148 bool mainextchnotok;149 bool batt_ovv;150 bool batt_rem;151 bool btemp_underover;152 bool btemp_low;153 bool btemp_high;154 bool main_thermal_prot;155 bool usb_thermal_prot;156 bool main_ovv;157 bool vbus_ovv;158 bool usbchargernotok;159 bool safety_timer_expired;160 bool maintenance_timer_expired;161 bool ac_wd_expired;162 bool usb_wd_expired;163 bool ac_cv_active;164 bool usb_cv_active;165 bool vbus_collapsed;166};167 168/**169 * struct ab8500_charge_curr_maximization - Charger maximization parameters170 * @original_iset_ua: the non optimized/maximised charger current171 * @current_iset_ua: the charging current used at this moment172 * @condition_cnt: number of iterations needed before a new charger current173 is set174 * @max_current_ua: maximum charger current175 * @wait_cnt: to avoid too fast current step down in case of charger176 * voltage collapse, we insert this delay between step177 * down178 * @level: tells in how many steps the charging current has been179 increased180 */181struct ab8500_charge_curr_maximization {182 int original_iset_ua;183 int current_iset_ua;184 int condition_cnt;185 int max_current_ua;186 int wait_cnt;187 u8 level;188};189 190enum maxim_ret {191 MAXIM_RET_NOACTION,192 MAXIM_RET_CHANGE,193 MAXIM_RET_IBAT_TOO_HIGH,194};195 196/**197 * struct ab8500_chargalg - ab8500 Charging algorithm device information198 * @dev: pointer to the structure device199 * @charge_status: battery operating status200 * @eoc_cnt: counter used to determine end-of_charge201 * @maintenance_chg: indicate if maintenance charge is active202 * @t_hyst_norm temperature hysteresis when the temperature has been203 * over or under normal limits204 * @t_hyst_lowhigh temperature hysteresis when the temperature has been205 * over or under the high or low limits206 * @charge_state: current state of the charging algorithm207 * @ccm charging current maximization parameters208 * @chg_info: information about connected charger types209 * @batt_data: data of the battery210 * @bm: Platform specific battery management information211 * @parent: pointer to the struct ab8500212 * @chargalg_psy: structure that holds the battery properties exposed by213 * the charging algorithm214 * @events: structure for information about events triggered215 * @chargalg_wq: work queue for running the charging algorithm216 * @chargalg_periodic_work: work to run the charging algorithm periodically217 * @chargalg_wd_work: work to kick the charger watchdog periodically218 * @chargalg_work: work to run the charging algorithm instantly219 * @safety_timer: charging safety timer220 * @maintenance_timer: maintenance charging timer221 * @chargalg_kobject: structure of type kobject222 */223struct ab8500_chargalg {224 struct device *dev;225 int charge_status;226 int eoc_cnt;227 bool maintenance_chg;228 int t_hyst_norm;229 int t_hyst_lowhigh;230 enum ab8500_chargalg_states charge_state;231 struct ab8500_charge_curr_maximization ccm;232 struct ab8500_chargalg_charger_info chg_info;233 struct ab8500_chargalg_battery_data batt_data;234 struct ab8500 *parent;235 struct ab8500_bm_data *bm;236 struct power_supply *chargalg_psy;237 struct ux500_charger *ac_chg;238 struct ux500_charger *usb_chg;239 struct ab8500_chargalg_events events;240 struct workqueue_struct *chargalg_wq;241 struct delayed_work chargalg_periodic_work;242 struct delayed_work chargalg_wd_work;243 struct work_struct chargalg_work;244 struct hrtimer safety_timer;245 struct hrtimer maintenance_timer;246 struct kobject chargalg_kobject;247};248 249/* Main battery properties */250static enum power_supply_property ab8500_chargalg_props[] = {251 POWER_SUPPLY_PROP_STATUS,252 POWER_SUPPLY_PROP_HEALTH,253};254 255/**256 * ab8500_chargalg_safety_timer_expired() - Expiration of the safety timer257 * @timer: pointer to the hrtimer structure258 *259 * This function gets called when the safety timer for the charger260 * expires261 */262static enum hrtimer_restart263ab8500_chargalg_safety_timer_expired(struct hrtimer *timer)264{265 struct ab8500_chargalg *di = container_of(timer, struct ab8500_chargalg,266 safety_timer);267 dev_err(di->dev, "Safety timer expired\n");268 di->events.safety_timer_expired = true;269 270 /* Trigger execution of the algorithm instantly */271 queue_work(di->chargalg_wq, &di->chargalg_work);272 273 return HRTIMER_NORESTART;274}275 276/**277 * ab8500_chargalg_maintenance_timer_expired() - Expiration of278 * the maintenance timer279 * @timer: pointer to the timer structure280 *281 * This function gets called when the maintenance timer282 * expires283 */284static enum hrtimer_restart285ab8500_chargalg_maintenance_timer_expired(struct hrtimer *timer)286{287 288 struct ab8500_chargalg *di = container_of(timer, struct ab8500_chargalg,289 maintenance_timer);290 291 dev_dbg(di->dev, "Maintenance timer expired\n");292 di->events.maintenance_timer_expired = true;293 294 /* Trigger execution of the algorithm instantly */295 queue_work(di->chargalg_wq, &di->chargalg_work);296 297 return HRTIMER_NORESTART;298}299 300/**301 * ab8500_chargalg_state_to() - Change charge state302 * @di: pointer to the ab8500_chargalg structure303 *304 * This function gets called when a charge state change should occur305 */306static void ab8500_chargalg_state_to(struct ab8500_chargalg *di,307 enum ab8500_chargalg_states state)308{309 dev_dbg(di->dev,310 "State changed: %s (From state: [%d] %s =to=> [%d] %s )\n",311 di->charge_state == state ? "NO" : "YES",312 di->charge_state,313 states[di->charge_state],314 state,315 states[state]);316 317 di->charge_state = state;318}319 320static int ab8500_chargalg_check_charger_enable(struct ab8500_chargalg *di)321{322 struct power_supply_battery_info *bi = di->bm->bi;323 324 switch (di->charge_state) {325 case STATE_NORMAL:326 case STATE_MAINTENANCE_A:327 case STATE_MAINTENANCE_B:328 break;329 default:330 return 0;331 }332 333 if (di->chg_info.charger_type & USB_CHG) {334 return di->usb_chg->ops.check_enable(di->usb_chg,335 bi->constant_charge_voltage_max_uv,336 bi->constant_charge_current_max_ua);337 } else if (di->chg_info.charger_type & AC_CHG) {338 return di->ac_chg->ops.check_enable(di->ac_chg,339 bi->constant_charge_voltage_max_uv,340 bi->constant_charge_current_max_ua);341 }342 return 0;343}344 345/**346 * ab8500_chargalg_check_charger_connection() - Check charger connection change347 * @di: pointer to the ab8500_chargalg structure348 *349 * This function will check if there is a change in the charger connection350 * and change charge state accordingly. AC has precedence over USB.351 */352static int ab8500_chargalg_check_charger_connection(struct ab8500_chargalg *di)353{354 if (di->chg_info.conn_chg != di->chg_info.prev_conn_chg) {355 /* Charger state changed since last update */356 if (di->chg_info.conn_chg & AC_CHG) {357 dev_info(di->dev, "Charging source is AC\n");358 if (di->chg_info.charger_type != AC_CHG) {359 di->chg_info.charger_type = AC_CHG;360 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);361 }362 } else if (di->chg_info.conn_chg & USB_CHG) {363 dev_info(di->dev, "Charging source is USB\n");364 di->chg_info.charger_type = USB_CHG;365 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);366 } else {367 dev_dbg(di->dev, "Charging source is OFF\n");368 di->chg_info.charger_type = NO_CHG;369 ab8500_chargalg_state_to(di, STATE_HANDHELD_INIT);370 }371 di->chg_info.prev_conn_chg = di->chg_info.conn_chg;372 }373 return di->chg_info.conn_chg;374}375 376/**377 * ab8500_chargalg_start_safety_timer() - Start charging safety timer378 * @di: pointer to the ab8500_chargalg structure379 *380 * The safety timer is used to avoid overcharging of old or bad batteries.381 * There are different timers for AC and USB382 */383static void ab8500_chargalg_start_safety_timer(struct ab8500_chargalg *di)384{385 /* Charger-dependent expiration time in hours*/386 int timer_expiration = 0;387 388 switch (di->chg_info.charger_type) {389 case AC_CHG:390 timer_expiration = di->bm->main_safety_tmr_h;391 break;392 393 case USB_CHG:394 timer_expiration = di->bm->usb_safety_tmr_h;395 break;396 397 default:398 dev_err(di->dev, "Unknown charger to charge from\n");399 break;400 }401 402 di->events.safety_timer_expired = false;403 hrtimer_set_expires_range(&di->safety_timer,404 ktime_set(timer_expiration * ONE_HOUR_IN_SECONDS, 0),405 ktime_set(FIVE_MINUTES_IN_SECONDS, 0));406 hrtimer_start_expires(&di->safety_timer, HRTIMER_MODE_REL);407}408 409/**410 * ab8500_chargalg_stop_safety_timer() - Stop charging safety timer411 * @di: pointer to the ab8500_chargalg structure412 *413 * The safety timer is stopped whenever the NORMAL state is exited414 */415static void ab8500_chargalg_stop_safety_timer(struct ab8500_chargalg *di)416{417 if (hrtimer_try_to_cancel(&di->safety_timer) >= 0)418 di->events.safety_timer_expired = false;419}420 421/**422 * ab8500_chargalg_start_maintenance_timer() - Start charging maintenance timer423 * @di: pointer to the ab8500_chargalg structure424 * @duration: duration of the maintenance timer in minutes425 *426 * The maintenance timer is used to maintain the charge in the battery once427 * the battery is considered full. These timers are chosen to match the428 * discharge curve of the battery429 */430static void ab8500_chargalg_start_maintenance_timer(struct ab8500_chargalg *di,431 int duration)432{433 /* Set a timer in minutes with a 30 second range */434 hrtimer_set_expires_range(&di->maintenance_timer,435 ktime_set(duration * 60, 0),436 ktime_set(30, 0));437 di->events.maintenance_timer_expired = false;438 hrtimer_start_expires(&di->maintenance_timer, HRTIMER_MODE_REL);439}440 441/**442 * ab8500_chargalg_stop_maintenance_timer() - Stop maintenance timer443 * @di: pointer to the ab8500_chargalg structure444 *445 * The maintenance timer is stopped whenever maintenance ends or when another446 * state is entered447 */448static void ab8500_chargalg_stop_maintenance_timer(struct ab8500_chargalg *di)449{450 if (hrtimer_try_to_cancel(&di->maintenance_timer) >= 0)451 di->events.maintenance_timer_expired = false;452}453 454/**455 * ab8500_chargalg_kick_watchdog() - Kick charger watchdog456 * @di: pointer to the ab8500_chargalg structure457 *458 * The charger watchdog have to be kicked periodically whenever the charger is459 * on, else the ABB will reset the system460 */461static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di)462{463 /* Check if charger exists and kick watchdog if charging */464 if (di->ac_chg && di->ac_chg->ops.kick_wd &&465 di->chg_info.online_chg & AC_CHG) {466 return di->ac_chg->ops.kick_wd(di->ac_chg);467 } else if (di->usb_chg && di->usb_chg->ops.kick_wd &&468 di->chg_info.online_chg & USB_CHG)469 return di->usb_chg->ops.kick_wd(di->usb_chg);470 471 return -ENXIO;472}473 474/**475 * ab8500_chargalg_ac_en() - Turn on/off the AC charger476 * @di: pointer to the ab8500_chargalg structure477 * @enable: charger on/off478 * @vset_uv: requested charger output voltage in microvolt479 * @iset_ua: requested charger output current in microampere480 *481 * The AC charger will be turned on/off with the requested charge voltage and482 * current483 */484static int ab8500_chargalg_ac_en(struct ab8500_chargalg *di, int enable,485 int vset_uv, int iset_ua)486{487 if (!di->ac_chg || !di->ac_chg->ops.enable)488 return -ENXIO;489 490 /* Select maximum of what both the charger and the battery supports */491 if (di->ac_chg->max_out_volt_uv)492 vset_uv = min(vset_uv, di->ac_chg->max_out_volt_uv);493 if (di->ac_chg->max_out_curr_ua)494 iset_ua = min(iset_ua, di->ac_chg->max_out_curr_ua);495 496 di->chg_info.ac_iset_ua = iset_ua;497 di->chg_info.ac_vset_uv = vset_uv;498 499 return di->ac_chg->ops.enable(di->ac_chg, enable, vset_uv, iset_ua);500}501 502/**503 * ab8500_chargalg_usb_en() - Turn on/off the USB charger504 * @di: pointer to the ab8500_chargalg structure505 * @enable: charger on/off506 * @vset_uv: requested charger output voltage in microvolt507 * @iset_ua: requested charger output current in microampere508 *509 * The USB charger will be turned on/off with the requested charge voltage and510 * current511 */512static int ab8500_chargalg_usb_en(struct ab8500_chargalg *di, int enable,513 int vset_uv, int iset_ua)514{515 if (!di->usb_chg || !di->usb_chg->ops.enable)516 return -ENXIO;517 518 /* Select maximum of what both the charger and the battery supports */519 if (di->usb_chg->max_out_volt_uv)520 vset_uv = min(vset_uv, di->usb_chg->max_out_volt_uv);521 if (di->usb_chg->max_out_curr_ua)522 iset_ua = min(iset_ua, di->usb_chg->max_out_curr_ua);523 524 di->chg_info.usb_iset_ua = iset_ua;525 di->chg_info.usb_vset_uv = vset_uv;526 527 return di->usb_chg->ops.enable(di->usb_chg, enable, vset_uv, iset_ua);528}529 530/**531 * ab8500_chargalg_update_chg_curr() - Update charger current532 * @di: pointer to the ab8500_chargalg structure533 * @iset_ua: requested charger output current in microampere534 *535 * The charger output current will be updated for the charger536 * that is currently in use537 */538static int ab8500_chargalg_update_chg_curr(struct ab8500_chargalg *di,539 int iset_ua)540{541 /* Check if charger exists and update current if charging */542 if (di->ac_chg && di->ac_chg->ops.update_curr &&543 di->chg_info.charger_type & AC_CHG) {544 /*545 * Select maximum of what both the charger546 * and the battery supports547 */548 if (di->ac_chg->max_out_curr_ua)549 iset_ua = min(iset_ua, di->ac_chg->max_out_curr_ua);550 551 di->chg_info.ac_iset_ua = iset_ua;552 553 return di->ac_chg->ops.update_curr(di->ac_chg, iset_ua);554 } else if (di->usb_chg && di->usb_chg->ops.update_curr &&555 di->chg_info.charger_type & USB_CHG) {556 /*557 * Select maximum of what both the charger558 * and the battery supports559 */560 if (di->usb_chg->max_out_curr_ua)561 iset_ua = min(iset_ua, di->usb_chg->max_out_curr_ua);562 563 di->chg_info.usb_iset_ua = iset_ua;564 565 return di->usb_chg->ops.update_curr(di->usb_chg, iset_ua);566 }567 568 return -ENXIO;569}570 571/**572 * ab8500_chargalg_stop_charging() - Stop charging573 * @di: pointer to the ab8500_chargalg structure574 *575 * This function is called from any state where charging should be stopped.576 * All charging is disabled and all status parameters and timers are changed577 * accordingly578 */579static void ab8500_chargalg_stop_charging(struct ab8500_chargalg *di)580{581 ab8500_chargalg_ac_en(di, false, 0, 0);582 ab8500_chargalg_usb_en(di, false, 0, 0);583 ab8500_chargalg_stop_safety_timer(di);584 ab8500_chargalg_stop_maintenance_timer(di);585 di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;586 di->maintenance_chg = false;587 cancel_delayed_work(&di->chargalg_wd_work);588 power_supply_changed(di->chargalg_psy);589}590 591/**592 * ab8500_chargalg_hold_charging() - Pauses charging593 * @di: pointer to the ab8500_chargalg structure594 *595 * This function is called in the case where maintenance charging has been596 * disabled and instead a battery voltage mode is entered to check when the597 * battery voltage has reached a certain recharge voltage598 */599static void ab8500_chargalg_hold_charging(struct ab8500_chargalg *di)600{601 ab8500_chargalg_ac_en(di, false, 0, 0);602 ab8500_chargalg_usb_en(di, false, 0, 0);603 ab8500_chargalg_stop_safety_timer(di);604 ab8500_chargalg_stop_maintenance_timer(di);605 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;606 di->maintenance_chg = false;607 cancel_delayed_work(&di->chargalg_wd_work);608 power_supply_changed(di->chargalg_psy);609}610 611/**612 * ab8500_chargalg_start_charging() - Start the charger613 * @di: pointer to the ab8500_chargalg structure614 * @vset_uv: requested charger output voltage in microvolt615 * @iset_ua: requested charger output current in microampere616 *617 * A charger will be enabled depending on the requested charger type that was618 * detected previously.619 */620static void ab8500_chargalg_start_charging(struct ab8500_chargalg *di,621 int vset_uv, int iset_ua)622{623 switch (di->chg_info.charger_type) {624 case AC_CHG:625 dev_dbg(di->dev,626 "AC parameters: Vset %d, Ich %d\n", vset_uv, iset_ua);627 ab8500_chargalg_usb_en(di, false, 0, 0);628 ab8500_chargalg_ac_en(di, true, vset_uv, iset_ua);629 break;630 631 case USB_CHG:632 dev_dbg(di->dev,633 "USB parameters: Vset %d, Ich %d\n", vset_uv, iset_ua);634 ab8500_chargalg_ac_en(di, false, 0, 0);635 ab8500_chargalg_usb_en(di, true, vset_uv, iset_ua);636 break;637 638 default:639 dev_err(di->dev, "Unknown charger to charge from\n");640 break;641 }642}643 644/**645 * ab8500_chargalg_check_temp() - Check battery temperature ranges646 * @di: pointer to the ab8500_chargalg structure647 *648 * The battery temperature is checked against the predefined limits and the649 * charge state is changed accordingly650 */651static void ab8500_chargalg_check_temp(struct ab8500_chargalg *di)652{653 struct power_supply_battery_info *bi = di->bm->bi;654 655 if (di->batt_data.temp > (bi->temp_alert_min + di->t_hyst_norm) &&656 di->batt_data.temp < (bi->temp_alert_max - di->t_hyst_norm)) {657 /* Temp OK! */658 di->events.btemp_underover = false;659 di->events.btemp_low = false;660 di->events.btemp_high = false;661 di->t_hyst_norm = 0;662 di->t_hyst_lowhigh = 0;663 } else {664 if ((di->batt_data.temp >= bi->temp_alert_max) &&665 (di->batt_data.temp < (bi->temp_max - di->t_hyst_lowhigh))) {666 /* Alert zone for high temperature */667 di->events.btemp_underover = false;668 di->events.btemp_high = true;669 di->t_hyst_norm = di->bm->temp_hysteresis;670 di->t_hyst_lowhigh = 0;671 } else if ((di->batt_data.temp > (bi->temp_min + di->t_hyst_lowhigh)) &&672 (di->batt_data.temp <= bi->temp_alert_min)) {673 /* Alert zone for low temperature */674 di->events.btemp_underover = false;675 di->events.btemp_low = true;676 di->t_hyst_norm = di->bm->temp_hysteresis;677 di->t_hyst_lowhigh = 0;678 } else if (di->batt_data.temp <= bi->temp_min ||679 di->batt_data.temp >= bi->temp_max) {680 /* TEMP major!!!!! */681 di->events.btemp_underover = true;682 di->events.btemp_low = false;683 di->events.btemp_high = false;684 di->t_hyst_norm = 0;685 di->t_hyst_lowhigh = di->bm->temp_hysteresis;686 } else {687 /* Within hysteresis */688 dev_dbg(di->dev, "Within hysteresis limit temp: %d "689 "hyst_lowhigh %d, hyst normal %d\n",690 di->batt_data.temp, di->t_hyst_lowhigh,691 di->t_hyst_norm);692 }693 }694}695 696/**697 * ab8500_chargalg_check_charger_voltage() - Check charger voltage698 * @di: pointer to the ab8500_chargalg structure699 *700 * Charger voltage is checked against maximum limit701 */702static void ab8500_chargalg_check_charger_voltage(struct ab8500_chargalg *di)703{704 if (di->chg_info.usb_volt_uv > di->bm->chg_params->usb_volt_max_uv)705 di->chg_info.usb_chg_ok = false;706 else707 di->chg_info.usb_chg_ok = true;708 709 if (di->chg_info.ac_volt_uv > di->bm->chg_params->ac_volt_max_uv)710 di->chg_info.ac_chg_ok = false;711 else712 di->chg_info.ac_chg_ok = true;713 714}715 716/**717 * ab8500_chargalg_end_of_charge() - Check if end-of-charge criteria is fulfilled718 * @di: pointer to the ab8500_chargalg structure719 *720 * End-of-charge criteria is fulfilled when the battery voltage is above a721 * certain limit and the battery current is below a certain limit for a722 * predefined number of consecutive seconds. If true, the battery is full723 */724static void ab8500_chargalg_end_of_charge(struct ab8500_chargalg *di)725{726 if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&727 di->charge_state == STATE_NORMAL &&728 !di->maintenance_chg && (di->batt_data.volt_uv >=729 di->bm->bi->voltage_max_design_uv ||730 di->events.usb_cv_active || di->events.ac_cv_active) &&731 di->batt_data.avg_curr_ua <732 di->bm->bi->charge_term_current_ua &&733 di->batt_data.avg_curr_ua > 0) {734 if (++di->eoc_cnt >= EOC_COND_CNT) {735 di->eoc_cnt = 0;736 di->charge_status = POWER_SUPPLY_STATUS_FULL;737 di->maintenance_chg = true;738 dev_dbg(di->dev, "EOC reached!\n");739 power_supply_changed(di->chargalg_psy);740 } else {741 dev_dbg(di->dev,742 " EOC limit reached for the %d"743 " time, out of %d before EOC\n",744 di->eoc_cnt,745 EOC_COND_CNT);746 }747 } else {748 di->eoc_cnt = 0;749 }750}751 752static void init_maxim_chg_curr(struct ab8500_chargalg *di)753{754 struct power_supply_battery_info *bi = di->bm->bi;755 756 di->ccm.original_iset_ua = bi->constant_charge_current_max_ua;757 di->ccm.current_iset_ua = bi->constant_charge_current_max_ua;758 di->ccm.max_current_ua = di->bm->maxi->chg_curr_ua;759 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;760 di->ccm.level = 0;761}762 763/**764 * ab8500_chargalg_chg_curr_maxim - increases the charger current to765 * compensate for the system load766 * @di pointer to the ab8500_chargalg structure767 *768 * This maximization function is used to raise the charger current to get the769 * battery current as close to the optimal value as possible. The battery770 * current during charging is affected by the system load771 */772static enum maxim_ret ab8500_chargalg_chg_curr_maxim(struct ab8500_chargalg *di)773{774 775 if (!di->bm->maxi->ena_maxi)776 return MAXIM_RET_NOACTION;777 778 if (di->events.vbus_collapsed) {779 dev_dbg(di->dev, "Charger voltage has collapsed %d\n",780 di->ccm.wait_cnt);781 if (di->ccm.wait_cnt == 0) {782 dev_dbg(di->dev, "lowering current\n");783 di->ccm.wait_cnt++;784 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;785 di->ccm.max_current_ua = di->ccm.current_iset_ua;786 di->ccm.current_iset_ua = di->ccm.max_current_ua;787 di->ccm.level--;788 return MAXIM_RET_CHANGE;789 } else {790 dev_dbg(di->dev, "waiting\n");791 /* Let's go in here twice before lowering curr again */792 di->ccm.wait_cnt = (di->ccm.wait_cnt + 1) % 3;793 return MAXIM_RET_NOACTION;794 }795 }796 797 di->ccm.wait_cnt = 0;798 799 if (di->batt_data.inst_curr_ua > di->ccm.original_iset_ua) {800 dev_dbg(di->dev, " Maximization Ibat (%duA) too high"801 " (limit %duA) (current iset: %duA)!\n",802 di->batt_data.inst_curr_ua, di->ccm.original_iset_ua,803 di->ccm.current_iset_ua);804 805 if (di->ccm.current_iset_ua == di->ccm.original_iset_ua)806 return MAXIM_RET_NOACTION;807 808 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;809 di->ccm.current_iset_ua = di->ccm.original_iset_ua;810 di->ccm.level = 0;811 812 return MAXIM_RET_IBAT_TOO_HIGH;813 }814 815 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;816 return MAXIM_RET_NOACTION;817}818 819static void handle_maxim_chg_curr(struct ab8500_chargalg *di)820{821 struct power_supply_battery_info *bi = di->bm->bi;822 enum maxim_ret ret;823 int result;824 825 ret = ab8500_chargalg_chg_curr_maxim(di);826 switch (ret) {827 case MAXIM_RET_CHANGE:828 result = ab8500_chargalg_update_chg_curr(di,829 di->ccm.current_iset_ua);830 if (result)831 dev_err(di->dev, "failed to set chg curr\n");832 break;833 case MAXIM_RET_IBAT_TOO_HIGH:834 result = ab8500_chargalg_update_chg_curr(di,835 bi->constant_charge_current_max_ua);836 if (result)837 dev_err(di->dev, "failed to set chg curr\n");838 break;839 840 case MAXIM_RET_NOACTION:841 default:842 /* Do nothing..*/843 break;844 }845}846 847static int ab8500_chargalg_get_ext_psy_data(struct device *dev, void *data)848{849 struct power_supply *psy;850 struct power_supply *ext = dev_get_drvdata(dev);851 const char **supplicants = (const char **)ext->supplied_to;852 struct ab8500_chargalg *di;853 union power_supply_propval ret;854 int j;855 bool capacity_updated = false;856 857 psy = (struct power_supply *)data;858 di = power_supply_get_drvdata(psy);859 /* For all psy where the driver name appears in any supplied_to */860 j = match_string(supplicants, ext->num_supplicants, psy->desc->name);861 if (j < 0)862 return 0;863 864 /*865 * If external is not registering 'POWER_SUPPLY_PROP_CAPACITY' to its866 * property because of handling that sysfs entry on its own, this is867 * the place to get the battery capacity.868 */869 if (!power_supply_get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {870 di->batt_data.percent = ret.intval;871 capacity_updated = true;872 }873 874 /* Go through all properties for the psy */875 for (j = 0; j < ext->desc->num_properties; j++) {876 enum power_supply_property prop;877 prop = ext->desc->properties[j];878 879 /*880 * Initialize chargers if not already done.881 * The ab8500_charger*/882 if (!di->ac_chg &&883 ext->desc->type == POWER_SUPPLY_TYPE_MAINS)884 di->ac_chg = psy_to_ux500_charger(ext);885 else if (!di->usb_chg &&886 ext->desc->type == POWER_SUPPLY_TYPE_USB)887 di->usb_chg = psy_to_ux500_charger(ext);888 889 if (power_supply_get_property(ext, prop, &ret))890 continue;891 switch (prop) {892 case POWER_SUPPLY_PROP_PRESENT:893 switch (ext->desc->type) {894 case POWER_SUPPLY_TYPE_BATTERY:895 /* Battery present */896 if (ret.intval)897 di->events.batt_rem = false;898 /* Battery removed */899 else900 di->events.batt_rem = true;901 break;902 case POWER_SUPPLY_TYPE_MAINS:903 /* AC disconnected */904 if (!ret.intval &&905 (di->chg_info.conn_chg & AC_CHG)) {906 di->chg_info.prev_conn_chg =907 di->chg_info.conn_chg;908 di->chg_info.conn_chg &= ~AC_CHG;909 }910 /* AC connected */911 else if (ret.intval &&912 !(di->chg_info.conn_chg & AC_CHG)) {913 di->chg_info.prev_conn_chg =914 di->chg_info.conn_chg;915 di->chg_info.conn_chg |= AC_CHG;916 }917 break;918 case POWER_SUPPLY_TYPE_USB:919 /* USB disconnected */920 if (!ret.intval &&921 (di->chg_info.conn_chg & USB_CHG)) {922 di->chg_info.prev_conn_chg =923 di->chg_info.conn_chg;924 di->chg_info.conn_chg &= ~USB_CHG;925 }926 /* USB connected */927 else if (ret.intval &&928 !(di->chg_info.conn_chg & USB_CHG)) {929 di->chg_info.prev_conn_chg =930 di->chg_info.conn_chg;931 di->chg_info.conn_chg |= USB_CHG;932 }933 break;934 default:935 break;936 }937 break;938 939 case POWER_SUPPLY_PROP_ONLINE:940 switch (ext->desc->type) {941 case POWER_SUPPLY_TYPE_BATTERY:942 break;943 case POWER_SUPPLY_TYPE_MAINS:944 /* AC offline */945 if (!ret.intval &&946 (di->chg_info.online_chg & AC_CHG)) {947 di->chg_info.prev_online_chg =948 di->chg_info.online_chg;949 di->chg_info.online_chg &= ~AC_CHG;950 }951 /* AC online */952 else if (ret.intval &&953 !(di->chg_info.online_chg & AC_CHG)) {954 di->chg_info.prev_online_chg =955 di->chg_info.online_chg;956 di->chg_info.online_chg |= AC_CHG;957 queue_delayed_work(di->chargalg_wq,958 &di->chargalg_wd_work, 0);959 }960 break;961 case POWER_SUPPLY_TYPE_USB:962 /* USB offline */963 if (!ret.intval &&964 (di->chg_info.online_chg & USB_CHG)) {965 di->chg_info.prev_online_chg =966 di->chg_info.online_chg;967 di->chg_info.online_chg &= ~USB_CHG;968 }969 /* USB online */970 else if (ret.intval &&971 !(di->chg_info.online_chg & USB_CHG)) {972 di->chg_info.prev_online_chg =973 di->chg_info.online_chg;974 di->chg_info.online_chg |= USB_CHG;975 queue_delayed_work(di->chargalg_wq,976 &di->chargalg_wd_work, 0);977 }978 break;979 default:980 break;981 }982 break;983 984 case POWER_SUPPLY_PROP_HEALTH:985 switch (ext->desc->type) {986 case POWER_SUPPLY_TYPE_BATTERY:987 break;988 case POWER_SUPPLY_TYPE_MAINS:989 switch (ret.intval) {990 case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:991 di->events.mainextchnotok = true;992 di->events.main_thermal_prot = false;993 di->events.main_ovv = false;994 di->events.ac_wd_expired = false;995 break;996 case POWER_SUPPLY_HEALTH_DEAD:997 di->events.ac_wd_expired = true;998 di->events.mainextchnotok = false;999 di->events.main_ovv = false;1000 di->events.main_thermal_prot = false;1001 break;1002 case POWER_SUPPLY_HEALTH_COLD:1003 case POWER_SUPPLY_HEALTH_OVERHEAT:1004 di->events.main_thermal_prot = true;1005 di->events.mainextchnotok = false;1006 di->events.main_ovv = false;1007 di->events.ac_wd_expired = false;1008 break;1009 case POWER_SUPPLY_HEALTH_OVERVOLTAGE:1010 di->events.main_ovv = true;1011 di->events.mainextchnotok = false;1012 di->events.main_thermal_prot = false;1013 di->events.ac_wd_expired = false;1014 break;1015 case POWER_SUPPLY_HEALTH_GOOD:1016 di->events.main_thermal_prot = false;1017 di->events.mainextchnotok = false;1018 di->events.main_ovv = false;1019 di->events.ac_wd_expired = false;1020 break;1021 default:1022 break;1023 }1024 break;1025 1026 case POWER_SUPPLY_TYPE_USB:1027 switch (ret.intval) {1028 case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:1029 di->events.usbchargernotok = true;1030 di->events.usb_thermal_prot = false;1031 di->events.vbus_ovv = false;1032 di->events.usb_wd_expired = false;1033 break;1034 case POWER_SUPPLY_HEALTH_DEAD:1035 di->events.usb_wd_expired = true;1036 di->events.usbchargernotok = false;1037 di->events.usb_thermal_prot = false;1038 di->events.vbus_ovv = false;1039 break;1040 case POWER_SUPPLY_HEALTH_COLD:1041 case POWER_SUPPLY_HEALTH_OVERHEAT:1042 di->events.usb_thermal_prot = true;1043 di->events.usbchargernotok = false;1044 di->events.vbus_ovv = false;1045 di->events.usb_wd_expired = false;1046 break;1047 case POWER_SUPPLY_HEALTH_OVERVOLTAGE:1048 di->events.vbus_ovv = true;1049 di->events.usbchargernotok = false;1050 di->events.usb_thermal_prot = false;1051 di->events.usb_wd_expired = false;1052 break;1053 case POWER_SUPPLY_HEALTH_GOOD:1054 di->events.usbchargernotok = false;1055 di->events.usb_thermal_prot = false;1056 di->events.vbus_ovv = false;1057 di->events.usb_wd_expired = false;1058 break;1059 default:1060 break;1061 }1062 break;1063 default:1064 break;1065 }1066 break;1067 1068 case POWER_SUPPLY_PROP_VOLTAGE_NOW:1069 switch (ext->desc->type) {1070 case POWER_SUPPLY_TYPE_BATTERY:1071 di->batt_data.volt_uv = ret.intval;1072 break;1073 case POWER_SUPPLY_TYPE_MAINS:1074 di->chg_info.ac_volt_uv = ret.intval;1075 break;1076 case POWER_SUPPLY_TYPE_USB:1077 di->chg_info.usb_volt_uv = ret.intval;1078 break;1079 default:1080 break;1081 }1082 break;1083 1084 case POWER_SUPPLY_PROP_VOLTAGE_AVG:1085 switch (ext->desc->type) {1086 case POWER_SUPPLY_TYPE_MAINS:1087 /* AVG is used to indicate when we are1088 * in CV mode */1089 if (ret.intval)1090 di->events.ac_cv_active = true;1091 else1092 di->events.ac_cv_active = false;1093 1094 break;1095 case POWER_SUPPLY_TYPE_USB:1096 /* AVG is used to indicate when we are1097 * in CV mode */1098 if (ret.intval)1099 di->events.usb_cv_active = true;1100 else1101 di->events.usb_cv_active = false;1102 1103 break;1104 default:1105 break;1106 }1107 break;1108 1109 case POWER_SUPPLY_PROP_TECHNOLOGY:1110 switch (ext->desc->type) {1111 case POWER_SUPPLY_TYPE_BATTERY:1112 if (ret.intval)1113 di->events.batt_unknown = false;1114 else1115 di->events.batt_unknown = true;1116 1117 break;1118 default:1119 break;1120 }1121 break;1122 1123 case POWER_SUPPLY_PROP_TEMP:1124 di->batt_data.temp = ret.intval / 10;1125 break;1126 1127 case POWER_SUPPLY_PROP_CURRENT_NOW:1128 switch (ext->desc->type) {1129 case POWER_SUPPLY_TYPE_MAINS:1130 di->chg_info.ac_curr_ua = ret.intval;1131 break;1132 case POWER_SUPPLY_TYPE_USB:1133 di->chg_info.usb_curr_ua = ret.intval;1134 break;1135 case POWER_SUPPLY_TYPE_BATTERY:1136 di->batt_data.inst_curr_ua = ret.intval;1137 break;1138 default:1139 break;1140 }1141 break;1142 1143 case POWER_SUPPLY_PROP_CURRENT_AVG:1144 switch (ext->desc->type) {1145 case POWER_SUPPLY_TYPE_BATTERY:1146 di->batt_data.avg_curr_ua = ret.intval;1147 break;1148 case POWER_SUPPLY_TYPE_USB:1149 if (ret.intval)1150 di->events.vbus_collapsed = true;1151 else1152 di->events.vbus_collapsed = false;1153 break;1154 default:1155 break;1156 }1157 break;1158 case POWER_SUPPLY_PROP_CAPACITY:1159 if (!capacity_updated)1160 di->batt_data.percent = ret.intval;1161 break;1162 default:1163 break;1164 }1165 }1166 return 0;1167}1168 1169/**1170 * ab8500_chargalg_external_power_changed() - callback for power supply changes1171 * @psy: pointer to the structure power_supply1172 *1173 * This function is the entry point of the pointer external_power_changed1174 * of the structure power_supply.1175 * This function gets executed when there is a change in any external power1176 * supply that this driver needs to be notified of.1177 */1178static void ab8500_chargalg_external_power_changed(struct power_supply *psy)1179{1180 struct ab8500_chargalg *di = power_supply_get_drvdata(psy);1181 1182 /*1183 * Trigger execution of the algorithm instantly and read1184 * all power_supply properties there instead1185 */1186 if (di->chargalg_wq)1187 queue_work(di->chargalg_wq, &di->chargalg_work);1188}1189 1190/**1191 * ab8500_chargalg_time_to_restart() - time to restart CC/CV charging?1192 * @di: charging algorithm state1193 *1194 * This checks if the voltage or capacity of the battery has fallen so1195 * low that we need to restart the CC/CV charge cycle.1196 */1197static bool ab8500_chargalg_time_to_restart(struct ab8500_chargalg *di)1198{1199 struct power_supply_battery_info *bi = di->bm->bi;1200 1201 /* Sanity check - these need to have some reasonable values */1202 if (!di->batt_data.volt_uv || !di->batt_data.percent)1203 return false;1204 1205 /* Some batteries tell us at which voltage we should restart charging */1206 if (bi->charge_restart_voltage_uv > 0) {1207 if (di->batt_data.volt_uv <= bi->charge_restart_voltage_uv)1208 return true;1209 /* Else we restart as we reach a certain capacity */1210 } else {1211 if (di->batt_data.percent <= AB8500_RECHARGE_CAP)1212 return true;1213 }1214 1215 return false;1216}1217 1218/**1219 * ab8500_chargalg_algorithm() - Main function for the algorithm1220 * @di: pointer to the ab8500_chargalg structure1221 *1222 * This is the main control function for the charging algorithm.1223 * It is called periodically or when something happens that will1224 * trigger a state change1225 */1226static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)1227{1228 const struct power_supply_maintenance_charge_table *mt;1229 struct power_supply_battery_info *bi = di->bm->bi;1230 int charger_status;1231 int ret;1232 1233 /* Collect data from all power_supply class devices */1234 power_supply_for_each_device(di->chargalg_psy, ab8500_chargalg_get_ext_psy_data);1235 1236 ab8500_chargalg_end_of_charge(di);1237 ab8500_chargalg_check_temp(di);1238 ab8500_chargalg_check_charger_voltage(di);1239 1240 charger_status = ab8500_chargalg_check_charger_connection(di);1241 1242 if (is_ab8500(di->parent)) {1243 ret = ab8500_chargalg_check_charger_enable(di);1244 if (ret < 0)1245 dev_err(di->dev, "Checking charger is enabled error"1246 ": Returned Value %d\n", ret);1247 }1248 1249 /*1250 * First check if we have a charger connected.1251 * Also we don't allow charging of unknown batteries if configured1252 * this way1253 */1254 if (!charger_status ||1255 (di->events.batt_unknown && !di->bm->chg_unknown_bat)) {1256 if (di->charge_state != STATE_HANDHELD) {1257 di->events.safety_timer_expired = false;1258 ab8500_chargalg_state_to(di, STATE_HANDHELD_INIT);1259 }1260 }1261 1262 /* Safety timer expiration */1263 else if (di->events.safety_timer_expired) {1264 if (di->charge_state != STATE_SAFETY_TIMER_EXPIRED)1265 ab8500_chargalg_state_to(di,1266 STATE_SAFETY_TIMER_EXPIRED_INIT);1267 }1268 /*1269 * Check if any interrupts has occurred1270 * that will prevent us from charging1271 */1272 1273 /* Battery removed */1274 else if (di->events.batt_rem) {1275 if (di->charge_state != STATE_BATT_REMOVED)1276 ab8500_chargalg_state_to(di, STATE_BATT_REMOVED_INIT);1277 }1278 /* Main or USB charger not ok. */1279 else if (di->events.mainextchnotok || di->events.usbchargernotok) {1280 /*1281 * If vbus_collapsed is set, we have to lower the charger1282 * current, which is done in the normal state below1283 */1284 if (di->charge_state != STATE_CHG_NOT_OK &&1285 !di->events.vbus_collapsed)1286 ab8500_chargalg_state_to(di, STATE_CHG_NOT_OK_INIT);1287 }1288 /* VBUS, Main or VBAT OVV. */1289 else if (di->events.vbus_ovv ||1290 di->events.main_ovv ||1291 di->events.batt_ovv ||1292 !di->chg_info.usb_chg_ok ||1293 !di->chg_info.ac_chg_ok) {1294 if (di->charge_state != STATE_OVV_PROTECT)1295 ab8500_chargalg_state_to(di, STATE_OVV_PROTECT_INIT);1296 }1297 /* USB Thermal, stop charging */1298 else if (di->events.main_thermal_prot ||1299 di->events.usb_thermal_prot) {1300 if (di->charge_state != STATE_HW_TEMP_PROTECT)1301 ab8500_chargalg_state_to(di,1302 STATE_HW_TEMP_PROTECT_INIT);1303 }1304 /* Battery temp over/under */1305 else if (di->events.btemp_underover) {1306 if (di->charge_state != STATE_TEMP_UNDEROVER)1307 ab8500_chargalg_state_to(di,1308 STATE_TEMP_UNDEROVER_INIT);1309 }1310 /* Watchdog expired */1311 else if (di->events.ac_wd_expired ||1312 di->events.usb_wd_expired) {1313 if (di->charge_state != STATE_WD_EXPIRED)1314 ab8500_chargalg_state_to(di, STATE_WD_EXPIRED_INIT);1315 }1316 /* Battery temp high/low */1317 else if (di->events.btemp_low || di->events.btemp_high) {1318 if (di->charge_state != STATE_TEMP_LOWHIGH)1319 ab8500_chargalg_state_to(di, STATE_TEMP_LOWHIGH_INIT);1320 }1321 1322 dev_dbg(di->dev,1323 "[CHARGALG] Vb %d Ib_avg %d Ib_inst %d Tb %d Cap %d Maint %d "1324 "State %s Active_chg %d Chg_status %d AC %d USB %d "1325 "AC_online %d USB_online %d AC_CV %d USB_CV %d AC_I %d "1326 "USB_I %d AC_Vset %d AC_Iset %d USB_Vset %d USB_Iset %d\n",1327 di->batt_data.volt_uv,1328 di->batt_data.avg_curr_ua,1329 di->batt_data.inst_curr_ua,1330 di->batt_data.temp,1331 di->batt_data.percent,1332 di->maintenance_chg,1333 states[di->charge_state],1334 di->chg_info.charger_type,1335 di->charge_status,1336 di->chg_info.conn_chg & AC_CHG,1337 di->chg_info.conn_chg & USB_CHG,1338 di->chg_info.online_chg & AC_CHG,1339 di->chg_info.online_chg & USB_CHG,1340 di->events.ac_cv_active,1341 di->events.usb_cv_active,1342 di->chg_info.ac_curr_ua,1343 di->chg_info.usb_curr_ua,1344 di->chg_info.ac_vset_uv,1345 di->chg_info.ac_iset_ua,1346 di->chg_info.usb_vset_uv,1347 di->chg_info.usb_iset_ua);1348 1349 switch (di->charge_state) {1350 case STATE_HANDHELD_INIT:1351 ab8500_chargalg_stop_charging(di);1352 di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;1353 ab8500_chargalg_state_to(di, STATE_HANDHELD);1354 fallthrough;1355 1356 case STATE_HANDHELD:1357 break;1358 1359 case STATE_BATT_REMOVED_INIT:1360 ab8500_chargalg_stop_charging(di);1361 ab8500_chargalg_state_to(di, STATE_BATT_REMOVED);1362 fallthrough;1363 1364 case STATE_BATT_REMOVED:1365 if (!di->events.batt_rem)1366 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1367 break;1368 1369 case STATE_HW_TEMP_PROTECT_INIT:1370 ab8500_chargalg_stop_charging(di);1371 ab8500_chargalg_state_to(di, STATE_HW_TEMP_PROTECT);1372 fallthrough;1373 1374 case STATE_HW_TEMP_PROTECT:1375 if (!di->events.main_thermal_prot &&1376 !di->events.usb_thermal_prot)1377 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1378 break;1379 1380 case STATE_OVV_PROTECT_INIT:1381 ab8500_chargalg_stop_charging(di);1382 ab8500_chargalg_state_to(di, STATE_OVV_PROTECT);1383 fallthrough;1384 1385 case STATE_OVV_PROTECT:1386 if (!di->events.vbus_ovv &&1387 !di->events.main_ovv &&1388 !di->events.batt_ovv &&1389 di->chg_info.usb_chg_ok &&1390 di->chg_info.ac_chg_ok)1391 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1392 break;1393 1394 case STATE_CHG_NOT_OK_INIT:1395 ab8500_chargalg_stop_charging(di);1396 ab8500_chargalg_state_to(di, STATE_CHG_NOT_OK);1397 fallthrough;1398 1399 case STATE_CHG_NOT_OK:1400 if (!di->events.mainextchnotok &&1401 !di->events.usbchargernotok)1402 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1403 break;1404 1405 case STATE_SAFETY_TIMER_EXPIRED_INIT:1406 ab8500_chargalg_stop_charging(di);1407 ab8500_chargalg_state_to(di, STATE_SAFETY_TIMER_EXPIRED);1408 fallthrough;1409 1410 case STATE_SAFETY_TIMER_EXPIRED:1411 /* We exit this state when charger is removed */1412 break;1413 1414 case STATE_NORMAL_INIT:1415 if (bi->constant_charge_current_max_ua == 0)1416 /* "charging" with 0 uA */1417 ab8500_chargalg_stop_charging(di);1418 else {1419 ab8500_chargalg_start_charging(di,1420 bi->constant_charge_voltage_max_uv,1421 bi->constant_charge_current_max_ua);1422 }1423 1424 ab8500_chargalg_state_to(di, STATE_NORMAL);1425 ab8500_chargalg_start_safety_timer(di);1426 ab8500_chargalg_stop_maintenance_timer(di);1427 init_maxim_chg_curr(di);1428 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;1429 di->eoc_cnt = 0;1430 di->maintenance_chg = false;1431 power_supply_changed(di->chargalg_psy);1432 1433 break;1434 1435 case STATE_NORMAL:1436 handle_maxim_chg_curr(di);1437 if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&1438 di->maintenance_chg) {1439 /*1440 * The battery is fully charged, check if we support1441 * maintenance charging else go back to waiting for1442 * the recharge voltage limit.1443 */1444 if (!power_supply_supports_maintenance_charging(bi))1445 ab8500_chargalg_state_to(di,1446 STATE_WAIT_FOR_RECHARGE_INIT);1447 else1448 ab8500_chargalg_state_to(di,1449 STATE_MAINTENANCE_A_INIT);1450 }1451 break;1452 1453 /* This state will be used when the maintenance state is disabled */1454 case STATE_WAIT_FOR_RECHARGE_INIT:1455 ab8500_chargalg_hold_charging(di);1456 ab8500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE);1457 fallthrough;1458 1459 case STATE_WAIT_FOR_RECHARGE:1460 if (ab8500_chargalg_time_to_restart(di))1461 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1462 break;1463 1464 case STATE_MAINTENANCE_A_INIT:1465 mt = power_supply_get_maintenance_charging_setting(bi, 0);1466 if (!mt) {1467 /* No maintenance A state, go back to normal */1468 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1469 power_supply_changed(di->chargalg_psy);1470 break;1471 }1472 ab8500_chargalg_stop_safety_timer(di);1473 ab8500_chargalg_start_maintenance_timer(di,1474 mt->charge_safety_timer_minutes);1475 ab8500_chargalg_start_charging(di,1476 mt->charge_voltage_max_uv,1477 mt->charge_current_max_ua);1478 ab8500_chargalg_state_to(di, STATE_MAINTENANCE_A);1479 power_supply_changed(di->chargalg_psy);1480 fallthrough;1481 1482 case STATE_MAINTENANCE_A:1483 if (di->events.maintenance_timer_expired) {1484 ab8500_chargalg_stop_maintenance_timer(di);1485 ab8500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT);1486 }1487 /*1488 * This happens if the voltage drops too quickly during1489 * maintenance charging, especially in older batteries.1490 */1491 if (ab8500_chargalg_time_to_restart(di)) {1492 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1493 dev_info(di->dev, "restarted charging from maintenance state A - battery getting old?\n");1494 }1495 break;1496 1497 case STATE_MAINTENANCE_B_INIT:1498 mt = power_supply_get_maintenance_charging_setting(bi, 1);1499 if (!mt) {1500 /* No maintenance B state, go back to normal */1501 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1502 power_supply_changed(di->chargalg_psy);1503 break;1504 }1505 ab8500_chargalg_start_maintenance_timer(di,1506 mt->charge_safety_timer_minutes);1507 ab8500_chargalg_start_charging(di,1508 mt->charge_voltage_max_uv,1509 mt->charge_current_max_ua);1510 ab8500_chargalg_state_to(di, STATE_MAINTENANCE_B);1511 power_supply_changed(di->chargalg_psy);1512 fallthrough;1513 1514 case STATE_MAINTENANCE_B:1515 if (di->events.maintenance_timer_expired) {1516 ab8500_chargalg_stop_maintenance_timer(di);1517 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1518 }1519 /*1520 * This happens if the voltage drops too quickly during1521 * maintenance charging, especially in older batteries.1522 */1523 if (ab8500_chargalg_time_to_restart(di)) {1524 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1525 dev_info(di->dev, "restarted charging from maintenance state B - battery getting old?\n");1526 }1527 break;1528 1529 case STATE_TEMP_LOWHIGH_INIT:1530 if (di->events.btemp_low) {1531 ab8500_chargalg_start_charging(di,1532 bi->alert_low_temp_charge_voltage_uv,1533 bi->alert_low_temp_charge_current_ua);1534 } else if (di->events.btemp_high) {1535 ab8500_chargalg_start_charging(di,1536 bi->alert_high_temp_charge_voltage_uv,1537 bi->alert_high_temp_charge_current_ua);1538 } else {1539 dev_err(di->dev, "neither low or high temp event occurred\n");1540 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1541 break;1542 }1543 ab8500_chargalg_stop_maintenance_timer(di);1544 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;1545 ab8500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);1546 power_supply_changed(di->chargalg_psy);1547 fallthrough;1548 1549 case STATE_TEMP_LOWHIGH:1550 if (!di->events.btemp_low && !di->events.btemp_high)1551 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1552 break;1553 1554 case STATE_WD_EXPIRED_INIT:1555 ab8500_chargalg_stop_charging(di);1556 ab8500_chargalg_state_to(di, STATE_WD_EXPIRED);1557 fallthrough;1558 1559 case STATE_WD_EXPIRED:1560 if (!di->events.ac_wd_expired &&1561 !di->events.usb_wd_expired)1562 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1563 break;1564 1565 case STATE_TEMP_UNDEROVER_INIT:1566 ab8500_chargalg_stop_charging(di);1567 ab8500_chargalg_state_to(di, STATE_TEMP_UNDEROVER);1568 fallthrough;1569 1570 case STATE_TEMP_UNDEROVER:1571 if (!di->events.btemp_underover)1572 ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);1573 break;1574 }1575 1576 /* Start charging directly if the new state is a charge state */1577 if (di->charge_state == STATE_NORMAL_INIT ||1578 di->charge_state == STATE_MAINTENANCE_A_INIT ||1579 di->charge_state == STATE_MAINTENANCE_B_INIT)1580 queue_work(di->chargalg_wq, &di->chargalg_work);1581}1582 1583/**1584 * ab8500_chargalg_periodic_work() - Periodic work for the algorithm1585 * @work: pointer to the work_struct structure1586 *1587 * Work queue function for the charging algorithm1588 */1589static void ab8500_chargalg_periodic_work(struct work_struct *work)1590{1591 struct ab8500_chargalg *di = container_of(work,1592 struct ab8500_chargalg, chargalg_periodic_work.work);1593 1594 ab8500_chargalg_algorithm(di);1595 1596 /*1597 * If a charger is connected then the battery has to be monitored1598 * frequently, else the work can be delayed.1599 */1600 if (di->chg_info.conn_chg)1601 queue_delayed_work(di->chargalg_wq,1602 &di->chargalg_periodic_work,1603 di->bm->interval_charging * HZ);1604 else1605 queue_delayed_work(di->chargalg_wq,1606 &di->chargalg_periodic_work,1607 di->bm->interval_not_charging * HZ);1608}1609 1610/**1611 * ab8500_chargalg_wd_work() - periodic work to kick the charger watchdog1612 * @work: pointer to the work_struct structure1613 *1614 * Work queue function for kicking the charger watchdog1615 */1616static void ab8500_chargalg_wd_work(struct work_struct *work)1617{1618 int ret;1619 struct ab8500_chargalg *di = container_of(work,1620 struct ab8500_chargalg, chargalg_wd_work.work);1621 1622 ret = ab8500_chargalg_kick_watchdog(di);1623 if (ret < 0)1624 dev_err(di->dev, "failed to kick watchdog\n");1625 1626 queue_delayed_work(di->chargalg_wq,1627 &di->chargalg_wd_work, CHG_WD_INTERVAL);1628}1629 1630/**1631 * ab8500_chargalg_work() - Work to run the charging algorithm instantly1632 * @work: pointer to the work_struct structure1633 *1634 * Work queue function for calling the charging algorithm1635 */1636static void ab8500_chargalg_work(struct work_struct *work)1637{1638 struct ab8500_chargalg *di = container_of(work,1639 struct ab8500_chargalg, chargalg_work);1640 1641 ab8500_chargalg_algorithm(di);1642}1643 1644/**1645 * ab8500_chargalg_get_property() - get the chargalg properties1646 * @psy: pointer to the power_supply structure1647 * @psp: pointer to the power_supply_property structure1648 * @val: pointer to the power_supply_propval union1649 *1650 * This function gets called when an application tries to get the1651 * chargalg properties by reading the sysfs files.1652 * status: charging/discharging/full/unknown1653 * health: health of the battery1654 * Returns error code in case of failure else 0 on success1655 */1656static int ab8500_chargalg_get_property(struct power_supply *psy,1657 enum power_supply_property psp,1658 union power_supply_propval *val)1659{1660 struct ab8500_chargalg *di = power_supply_get_drvdata(psy);1661 1662 switch (psp) {1663 case POWER_SUPPLY_PROP_STATUS:1664 val->intval = di->charge_status;1665 break;1666 case POWER_SUPPLY_PROP_HEALTH:1667 if (di->events.batt_ovv) {1668 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;1669 } else if (di->events.btemp_underover) {1670 if (di->batt_data.temp <= di->bm->bi->temp_min)1671 val->intval = POWER_SUPPLY_HEALTH_COLD;1672 else1673 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;1674 } else if (di->charge_state == STATE_SAFETY_TIMER_EXPIRED ||1675 di->charge_state == STATE_SAFETY_TIMER_EXPIRED_INIT) {1676 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;1677 } else {1678 val->intval = POWER_SUPPLY_HEALTH_GOOD;1679 }1680 break;1681 default:1682 return -EINVAL;1683 }1684 return 0;1685}1686 1687static int __maybe_unused ab8500_chargalg_resume(struct device *dev)1688{1689 struct ab8500_chargalg *di = dev_get_drvdata(dev);1690 1691 /* Kick charger watchdog if charging (any charger online) */1692 if (di->chg_info.online_chg)1693 queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0);1694 1695 /*1696 * Run the charging algorithm directly to be sure we don't1697 * do it too seldom1698 */1699 queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);1700 1701 return 0;1702}1703 1704static int __maybe_unused ab8500_chargalg_suspend(struct device *dev)1705{1706 struct ab8500_chargalg *di = dev_get_drvdata(dev);1707 1708 if (di->chg_info.online_chg)1709 cancel_delayed_work_sync(&di->chargalg_wd_work);1710 1711 cancel_delayed_work_sync(&di->chargalg_periodic_work);1712 1713 return 0;1714}1715 1716static char *supply_interface[] = {1717 "ab8500_fg",1718};1719 1720static const struct power_supply_desc ab8500_chargalg_desc = {1721 .name = "ab8500_chargalg",1722 .type = POWER_SUPPLY_TYPE_UNKNOWN,1723 .properties = ab8500_chargalg_props,1724 .num_properties = ARRAY_SIZE(ab8500_chargalg_props),1725 .get_property = ab8500_chargalg_get_property,1726 .external_power_changed = ab8500_chargalg_external_power_changed,1727};1728 1729static int ab8500_chargalg_bind(struct device *dev, struct device *master,1730 void *data)1731{1732 struct ab8500_chargalg *di = dev_get_drvdata(dev);1733 1734 /* Create a work queue for the chargalg */1735 di->chargalg_wq = alloc_ordered_workqueue("ab8500_chargalg_wq",1736 WQ_MEM_RECLAIM);1737 if (di->chargalg_wq == NULL) {1738 dev_err(di->dev, "failed to create work queue\n");1739 return -ENOMEM;1740 }1741 1742 /* Run the charging algorithm */1743 queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);1744 1745 return 0;1746}1747 1748static void ab8500_chargalg_unbind(struct device *dev, struct device *master,1749 void *data)1750{1751 struct ab8500_chargalg *di = dev_get_drvdata(dev);1752 1753 /* Stop all timers and work */1754 hrtimer_cancel(&di->safety_timer);1755 hrtimer_cancel(&di->maintenance_timer);1756 1757 cancel_delayed_work_sync(&di->chargalg_periodic_work);1758 cancel_delayed_work_sync(&di->chargalg_wd_work);1759 cancel_work_sync(&di->chargalg_work);1760 1761 /* Delete the work queue */1762 destroy_workqueue(di->chargalg_wq);1763}1764 1765static const struct component_ops ab8500_chargalg_component_ops = {1766 .bind = ab8500_chargalg_bind,1767 .unbind = ab8500_chargalg_unbind,1768};1769 1770static int ab8500_chargalg_probe(struct platform_device *pdev)1771{1772 struct device *dev = &pdev->dev;1773 struct power_supply_config psy_cfg = {};1774 struct ab8500_chargalg *di;1775 1776 di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);1777 if (!di)1778 return -ENOMEM;1779 1780 di->bm = &ab8500_bm_data;1781 1782 /* get device struct and parent */1783 di->dev = dev;1784 di->parent = dev_get_drvdata(pdev->dev.parent);1785 1786 psy_cfg.supplied_to = supply_interface;1787 psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);1788 psy_cfg.drv_data = di;1789 1790 /* Initilialize safety timer */1791 hrtimer_init(&di->safety_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);1792 di->safety_timer.function = ab8500_chargalg_safety_timer_expired;1793 1794 /* Initilialize maintenance timer */1795 hrtimer_init(&di->maintenance_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);1796 di->maintenance_timer.function =1797 ab8500_chargalg_maintenance_timer_expired;1798 1799 /* Init work for chargalg */1800 INIT_DEFERRABLE_WORK(&di->chargalg_periodic_work,1801 ab8500_chargalg_periodic_work);1802 INIT_DEFERRABLE_WORK(&di->chargalg_wd_work,1803 ab8500_chargalg_wd_work);1804 1805 /* Init work for chargalg */1806 INIT_WORK(&di->chargalg_work, ab8500_chargalg_work);1807 1808 /* To detect charger at startup */1809 di->chg_info.prev_conn_chg = -1;1810 1811 /* Register chargalg power supply class */1812 di->chargalg_psy = devm_power_supply_register(di->dev,1813 &ab8500_chargalg_desc,1814 &psy_cfg);1815 if (IS_ERR(di->chargalg_psy)) {1816 dev_err(di->dev, "failed to register chargalg psy\n");1817 return PTR_ERR(di->chargalg_psy);1818 }1819 1820 platform_set_drvdata(pdev, di);1821 1822 dev_info(di->dev, "probe success\n");1823 return component_add(dev, &ab8500_chargalg_component_ops);1824}1825 1826static void ab8500_chargalg_remove(struct platform_device *pdev)1827{1828 component_del(&pdev->dev, &ab8500_chargalg_component_ops);1829}1830 1831static SIMPLE_DEV_PM_OPS(ab8500_chargalg_pm_ops, ab8500_chargalg_suspend, ab8500_chargalg_resume);1832 1833static const struct of_device_id ab8500_chargalg_match[] = {1834 { .compatible = "stericsson,ab8500-chargalg", },1835 { },1836};1837 1838struct platform_driver ab8500_chargalg_driver = {1839 .probe = ab8500_chargalg_probe,1840 .remove_new = ab8500_chargalg_remove,1841 .driver = {1842 .name = "ab8500_chargalg",1843 .of_match_table = ab8500_chargalg_match,1844 .pm = &ab8500_chargalg_pm_ops,1845 },1846};1847MODULE_LICENSE("GPL v2");1848MODULE_AUTHOR("Johan Palsson, Karl Komierowski");1849MODULE_ALIAS("platform:ab8500-chargalg");1850MODULE_DESCRIPTION("ab8500 battery charging algorithm");1851