diff options
-rw-r--r-- | drivers/power/charger-manager.c | 59 | ||||
-rw-r--r-- | include/linux/power/charger-manager.h | 1 |
2 files changed, 58 insertions, 2 deletions
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 01a673cabd18..89ecc032d774 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -190,6 +190,8 @@ static bool is_charging(struct charger_manager *cm) continue; if (!cm->charger_enabled) continue; + if (cm->disable_charge) + continue; psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); if (!psy) { @@ -346,8 +348,11 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) int err = 0, i; struct charger_desc *desc = cm->desc; - /* Ignore if it's redundent command */ - if (enable == cm->charger_enabled) + /* + * Ignore redundant command and prevent enabling charger + * if it is disabled. + */ + if (enable == cm->charger_enabled || (enable && cm->disable_charge)) return 0; if (enable) { @@ -510,6 +515,9 @@ static int cm_check_thermal_status(struct charger_manager *cm) */ static int cm_get_target_status(struct charger_manager *cm) { + if (cm->disable_charge) + return POWER_SUPPLY_STATUS_DISCHARGING; + if (!is_ext_pwr_online(cm)) return POWER_SUPPLY_STATUS_DISCHARGING; @@ -1167,10 +1175,57 @@ static ssize_t store_polling_ms(struct device *dev, return count; } +static ssize_t show_disable_charge(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct charger_manager *cm; + + list_for_each_entry(cm, &cm_list, entry) + if (&cm->charger_psy->dev == dev) + break; + + if (&cm->charger_psy->dev != dev) + return -ENODEV; + + return sprintf(buf, "%d\n", cm->disable_charge); +} + +static ssize_t store_disable_charge(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct charger_manager *cm; + unsigned long disable_charge; + + if (kstrtoul(buf, 0, &disable_charge)) + return -EINVAL; + + list_for_each_entry(cm, &cm_list, entry) + if (&cm->charger_psy->dev == dev) + break; + + if (&cm->charger_psy->dev != dev) + return -ENODEV; + + disable_charge = !!disable_charge; + + if (disable_charge == cm->disable_charge) + return count; + + cm->disable_charge = disable_charge; + + _cm_monitor(cm); + + return count; +} + static DEVICE_ATTR(polling_ms, 0644, show_polling_ms, store_polling_ms); +static DEVICE_ATTR(disable_charge, 0644, + show_disable_charge, store_disable_charge); static struct attribute *charger_manager_attrs[] = { &dev_attr_polling_ms.attr, + &dev_attr_disable_charge.attr, NULL, }; diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h index 835d9337a3f3..1afe5e2be366 100644 --- a/include/linux/power/charger-manager.h +++ b/include/linux/power/charger-manager.h @@ -233,6 +233,7 @@ struct charger_manager { struct thermal_zone_device *tzd_batt; bool charger_enabled; + bool disable_charge; int emergency_stop; |