From fcb71d7b1c186993ccfe1256d07e3c6c94ac8839 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Thu, 23 Feb 2017 16:01:05 +0900 Subject: [PATCH] power: battery: sec-battery: Add support for disabling battery charge The new attribute "disable_charge" will be added. If this attribute is set to 1, battery charging completely stops within "discharging" state, and it cannot resume until restoring the attribute as 0 or rebooting the target. Change-Id: I0638bf73ba89d72c34d1c338a411e6d4978060db Signed-off-by: Dongwoo Lee --- drivers/battery/sec_battery.c | 45 +++++++++++++++++++++++++++++ include/linux/battery/sec_battery.h | 2 ++ 2 files changed, 47 insertions(+) diff --git a/drivers/battery/sec_battery.c b/drivers/battery/sec_battery.c index e40f1071d86..7238a5650c6 100644 --- a/drivers/battery/sec_battery.c +++ b/drivers/battery/sec_battery.c @@ -111,6 +111,7 @@ static struct device_attribute sec_battery_attrs[] = { SEC_BATTERY_ATTR(chg_extreme_onoff), SEC_BATTERY_ATTR(chg_extreme_mode), SEC_BATTERY_ATTR(chg_on), + SEC_BATTERY_ATTR(disable_charge), }; static enum power_supply_property sec_battery_props[] = { @@ -219,6 +220,11 @@ static int sec_bat_set_charge( return 0; } + if (battery->disable_charge && enable) { + dev_warn(battery->dev, "charging is disabled explicitly.\n"); + return 0; + } + val.intval = battery->status; psy_do_property(battery->pdata->charger_name, set, POWER_SUPPLY_PROP_STATUS, val); @@ -678,6 +684,10 @@ static bool sec_bat_get_cable_type( static void sec_bat_set_charging_status(struct sec_battery_info *battery, int status) { union power_supply_propval value; + + if (battery->disable_charge && status == POWER_SUPPLY_STATUS_CHARGING) + return; + switch (status) { case POWER_SUPPLY_STATUS_NOT_CHARGING: case POWER_SUPPLY_STATUS_DISCHARGING: @@ -3952,6 +3962,10 @@ ssize_t sec_bat_show_attrs(struct device *dev, i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", (battery->charging_block == false) ? 1 : 0); break; + case BATT_DISABLE_CHARGE: + i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", + (battery->disable_charge) ? 1 : 0); + break; default: i = -EINVAL; } @@ -4604,6 +4618,37 @@ ssize_t sec_bat_store_attrs( ret = count; } break; + case BATT_DISABLE_CHARGE: + if (sscanf(buf, "%d\n", &x) != 1) + break; + if (!!x) { + /* force disabling battery charge */ + battery->disable_charge = 1; + sec_bat_set_charging_status(battery, + POWER_SUPPLY_STATUS_DISCHARGING); + sec_bat_set_charge(battery, false); + power_supply_changed(&battery->psy_bat); + } else { + union power_supply_propval value; + + battery->disable_charge = 0; + sec_bat_get_cable_type(battery, + battery->pdata->cable_source_type); + + /* enable charger if connected */ + if (battery->cable_type != POWER_SUPPLY_TYPE_BATTERY && + battery->cable_type != POWER_SUPPLY_TYPE_OTG) { + sec_bat_set_charge(battery, true); + psy_do_property(battery->pdata->charger_name, + get, POWER_SUPPLY_PROP_STATUS, + value); + sec_bat_set_charging_status(battery, + value.intval); + power_supply_changed(&battery->psy_bat); + } + } + ret = count; + break; default: ret = -EINVAL; } diff --git a/include/linux/battery/sec_battery.h b/include/linux/battery/sec_battery.h index 53642cbc889..c256259ccee 100644 --- a/include/linux/battery/sec_battery.h +++ b/include/linux/battery/sec_battery.h @@ -226,6 +226,7 @@ struct sec_battery_info { #if defined(CONFIG_AFC_CHARGER_MODE) char *hv_chg_name; #endif + int disable_charge; }; ssize_t sec_bat_show_attrs(struct device *dev, @@ -348,6 +349,7 @@ enum { CHG_EXTREME_ONOFF, CHG_EXTREME_MODE, CHG_ON, + BATT_DISABLE_CHARGE, }; #ifdef CONFIG_OF -- 2.34.1