brintos

brintos / linux-shallow public Read only

0
0
Text · 52.7 KiB · 854491a Raw
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