in supply/88pm860x_charger.c [283:394]
static int set_charging_fsm(struct pm860x_charger_info *info)
{
struct power_supply *psy;
union power_supply_propval data;
unsigned char fsm_state[][16] = { "init", "discharge", "precharge",
"fastcharge",
};
int ret;
int vbatt;
psy = power_supply_get_by_name(pm860x_supplied_to[0]);
if (!psy)
return -EINVAL;
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,
&data);
if (ret) {
power_supply_put(psy);
return ret;
}
vbatt = data.intval / 1000;
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &data);
if (ret) {
power_supply_put(psy);
return ret;
}
power_supply_put(psy);
mutex_lock(&info->lock);
info->present = data.intval;
dev_dbg(info->dev, "Entering FSM:%s, Charger:%s, Battery:%s, "
"Allowed:%d\n",
&fsm_state[info->state][0],
(info->online) ? "online" : "N/A",
(info->present) ? "present" : "N/A", info->allowed);
dev_dbg(info->dev, "set_charging_fsm:vbatt:%d(mV)\n", vbatt);
switch (info->state) {
case FSM_INIT:
if (info->online && info->present && info->allowed) {
if (vbatt < PRECHARGE_THRESHOLD) {
info->state = FSM_PRECHARGE;
start_precharge(info);
} else if (vbatt > DISCHARGE_THRESHOLD) {
info->state = FSM_DISCHARGE;
stop_charge(info, vbatt);
} else if (vbatt < DISCHARGE_THRESHOLD) {
info->state = FSM_FASTCHARGE;
start_fastcharge(info);
}
} else {
if (vbatt < POWEROFF_THRESHOLD) {
power_off_notification(info);
} else {
info->state = FSM_DISCHARGE;
stop_charge(info, vbatt);
}
}
break;
case FSM_PRECHARGE:
if (info->online && info->present && info->allowed) {
if (vbatt > PRECHARGE_THRESHOLD) {
info->state = FSM_FASTCHARGE;
start_fastcharge(info);
}
} else {
info->state = FSM_DISCHARGE;
stop_charge(info, vbatt);
}
break;
case FSM_FASTCHARGE:
if (info->online && info->present && info->allowed) {
if (vbatt < PRECHARGE_THRESHOLD) {
info->state = FSM_PRECHARGE;
start_precharge(info);
}
} else {
info->state = FSM_DISCHARGE;
stop_charge(info, vbatt);
}
break;
case FSM_DISCHARGE:
if (info->online && info->present && info->allowed) {
if (vbatt < PRECHARGE_THRESHOLD) {
info->state = FSM_PRECHARGE;
start_precharge(info);
} else if (vbatt < DISCHARGE_THRESHOLD) {
info->state = FSM_FASTCHARGE;
start_fastcharge(info);
}
} else {
if (vbatt < POWEROFF_THRESHOLD)
power_off_notification(info);
else if (vbatt > CHARGE_THRESHOLD && info->online)
set_vbatt_threshold(info, CHARGE_THRESHOLD, 0);
}
break;
default:
dev_warn(info->dev, "FSM meets wrong state:%d\n",
info->state);
break;
}
dev_dbg(info->dev,
"Out FSM:%s, Charger:%s, Battery:%s, Allowed:%d\n",
&fsm_state[info->state][0],
(info->online) ? "online" : "N/A",
(info->present) ? "present" : "N/A", info->allowed);
mutex_unlock(&info->lock);
return 0;
}