power: battery: sec-battery: Support force disabling battery charge 67/113967/11
authorDongwoo Lee <dwoo08.lee@samsung.com>
Thu, 9 Feb 2017 10:53:03 +0000 (19:53 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 14 Feb 2017 06:43:51 +0000 (15:43 +0900)
The new attribute "disable_charge" will be added. If this attribute is
set to 1, battery charging is completely stopped within "discharging"
state.

Until setting the attribute to 0 or reboot the target, charging cannot
be resumed.

Change-Id: Ib57d3dbcc1e0925940d818c9bc5eced94b7bfddc
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
drivers/battery/sec_battery.c
include/linux/battery/sec_battery.h

index 98e0d81..1546556 100644 (file)
@@ -85,6 +85,7 @@ static struct device_attribute sec_battery_attrs[] = {
        SEC_BATTERY_ATTR(test_charge_current),
        SEC_BATTERY_ATTR(set_stability_test),
 #endif
+       SEC_BATTERY_ATTR(disable_charge),
 };
 
 static enum power_supply_property sec_battery_props[] = {
@@ -158,6 +159,11 @@ static int sec_bat_set_charge(
        struct timespec ts;
        ktime_t current_time;
 
+       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);
@@ -536,9 +542,10 @@ static bool sec_bat_battery_cable_check(struct sec_battery_info *battery)
        if (battery->health == POWER_SUPPLY_HEALTH_UNSPEC_FAILURE) {
                battery->health = POWER_SUPPLY_HEALTH_GOOD;
 
-               if (battery->status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
+               if (battery->disable_charge) {
+                       ;
+               } else if (battery->status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
                        battery->status = POWER_SUPPLY_STATUS_CHARGING;
-
                        sec_bat_set_charge(battery, true);
                }
        }
@@ -594,12 +601,16 @@ static bool sec_bat_ovp_uvlo_result(
                case POWER_SUPPLY_HEALTH_GOOD:
                        dev_info(battery->dev, "%s: Safe voltage\n", __func__);
                        dev_info(battery->dev, "%s: is_recharging : %d\n", __func__, battery->is_recharging);
-                       if (battery->is_recharging)
-                               battery->status =
-                                       POWER_SUPPLY_STATUS_FULL;
-                       else    /* Normal Charging */
-                               battery->status =
-                                       POWER_SUPPLY_STATUS_CHARGING;
+                       if (battery->disable_charge) {
+                               ;
+                       } else {
+                               if (battery->is_recharging)
+                                       battery->status =
+                                               POWER_SUPPLY_STATUS_FULL;
+                               else    /* Normal Charging */
+                                       battery->status =
+                                               POWER_SUPPLY_STATUS_CHARGING;
+                       }
                        break;
                case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
                case POWER_SUPPLY_HEALTH_UNDERVOLTAGE:
@@ -1221,9 +1232,10 @@ static bool sec_bat_temperature_check(
                        dev_info(battery->dev,
                                "%s: Safe Temperature\n", __func__);
                        /* if recovered from not charging */
-                       if ((battery->health == POWER_SUPPLY_HEALTH_GOOD) &&
-                               (battery->status ==
-                                POWER_SUPPLY_STATUS_NOT_CHARGING)) {
+                       if (battery->disable_charge) {
+                               ;
+                       } else if ((battery->health == POWER_SUPPLY_HEALTH_GOOD) &&
+                           (battery->status == POWER_SUPPLY_STATUS_NOT_CHARGING)) {
                                if (battery->is_recharging)
                                        battery->status =
                                                POWER_SUPPLY_STATUS_FULL;
@@ -2278,7 +2290,9 @@ static void sec_bat_cable_work(struct work_struct *work)
                        goto end_of_cable_work;
        } else {
                /* Do NOT display the charging icon when OTG is enabled */
-               if (battery->cable_type == POWER_SUPPLY_TYPE_OTG) {
+               if  (battery->disable_charge) {
+                       ;
+               } else if (battery->cable_type == POWER_SUPPLY_TYPE_OTG) {
                        battery->charging_mode = SEC_BATTERY_CHARGING_NONE;
                        battery->status = POWER_SUPPLY_STATUS_DISCHARGING;
                } else {
@@ -2603,6 +2617,10 @@ ssize_t sec_bat_show_attrs(struct device *dev,
                        battery->stability_test);
                break;
 #endif
+       case BATT_DISABLE_CHARGE:
+               i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+                               battery->disable_charge);
+               break;
        default:
                i = -EINVAL;
        }
@@ -2919,6 +2937,33 @@ ssize_t sec_bat_store_attrs(
                }
                break;
 #endif
+       case BATT_DISABLE_CHARGE:
+               sscanf(buf, "%d\n", &x);
+               if (!!x) {
+                       /* force disabling battery charge */
+                       battery->disable_charge = 1;
+                       battery->status = 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);
+
+                       /* set charging on if the proper charger is 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);
+                               battery->status = value.intval;
+                               power_supply_changed(&battery->psy_bat);
+                       }
+               }
+               ret = count;
+               break;
        default:
                ret = -EINVAL;
        }
index f17a2e9..f91e488 100644 (file)
@@ -195,6 +195,7 @@ struct sec_battery_info {
 #if defined(CONFIG_BATTERY_DISCHG_IC)
        int dischg_test;
 #endif
+       bool disable_charge;
 };
 
 ssize_t sec_bat_show_attrs(struct device *dev,
@@ -309,6 +310,7 @@ enum {
        BATT_2713_BATTERY_VOLTAGE,
        BATT_2713_BATTERY_ADC,
 #endif
+       BATT_DISABLE_CHARGE,
 };
 
 #ifdef CONFIG_OF