diff options
Diffstat (limited to 'drivers/power/abx500_chargalg.c')
-rw-r--r-- | drivers/power/abx500_chargalg.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 78b623572b52..f043c0851a76 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -445,8 +445,18 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di) { /* Check if charger exists and kick watchdog if charging */ if (di->ac_chg && di->ac_chg->ops.kick_wd && - di->chg_info.online_chg & AC_CHG) + di->chg_info.online_chg & AC_CHG) { + /* + * If AB charger watchdog expired, pm2xxx charging + * gets disabled. To be safe, kick both AB charger watchdog + * and pm2xxx watchdog. + */ + if (di->ac_chg->external && + di->usb_chg && di->usb_chg->ops.kick_wd) + di->usb_chg->ops.kick_wd(di->usb_chg); + return di->ac_chg->ops.kick_wd(di->ac_chg); + } else if (di->usb_chg && di->usb_chg->ops.kick_wd && di->chg_info.online_chg & USB_CHG) return di->usb_chg->ops.kick_wd(di->usb_chg); @@ -603,6 +613,8 @@ static void abx500_chargalg_hold_charging(struct abx500_chargalg *di) static void abx500_chargalg_start_charging(struct abx500_chargalg *di, int vset, int iset) { + bool start_chargalg_wd = true; + switch (di->chg_info.charger_type) { case AC_CHG: dev_dbg(di->dev, @@ -620,8 +632,12 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di, default: dev_err(di->dev, "Unknown charger to charge from\n"); + start_chargalg_wd = false; break; } + + if (start_chargalg_wd && !delayed_work_pending(&di->chargalg_wd_work)) + queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0); } /** @@ -1622,6 +1638,9 @@ static int abx500_chargalg_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_HEALTH_COLD; else val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; + } else if (di->charge_state == STATE_SAFETY_TIMER_EXPIRED || + di->charge_state == STATE_SAFETY_TIMER_EXPIRED_INIT) { + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; } else { val->intval = POWER_SUPPLY_HEALTH_GOOD; } @@ -1635,6 +1654,25 @@ static int abx500_chargalg_get_property(struct power_supply *psy, /* Exposure to the sysfs interface */ /** + * abx500_chargalg_sysfs_show() - sysfs show operations + * @kobj: pointer to the struct kobject + * @attr: pointer to the struct attribute + * @buf: buffer that holds the parameter to send to userspace + * + * Returns a buffer to be displayed in user space + */ +static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct abx500_chargalg *di = container_of(kobj, + struct abx500_chargalg, chargalg_kobject); + + return sprintf(buf, "%d\n", + di->susp_status.ac_suspended && + di->susp_status.usb_suspended); +} + +/** * abx500_chargalg_sysfs_charger() - sysfs store operations * @kobj: pointer to the struct kobject * @attr: pointer to the struct attribute @@ -1702,7 +1740,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, static struct attribute abx500_chargalg_en_charger = \ { .name = "chargalg", - .mode = S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }; static struct attribute *abx500_chargalg_chg[] = { @@ -1711,6 +1749,7 @@ static struct attribute *abx500_chargalg_chg[] = { }; static const struct sysfs_ops abx500_chargalg_sysfs_ops = { + .show = abx500_chargalg_sysfs_show, .store = abx500_chargalg_sysfs_charger, }; |