[RAMEN9610-12039][9610] drivers, dts: add battery driver. DT for ERD.
authorKeunho Hwang <keunho.hwang@samsung.com>
Mon, 11 Feb 2019 12:47:00 +0000 (21:47 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:23:15 +0000 (20:23 +0300)
Add new battery data DT, battery driver for S2MU004
base ERD

Change-Id: I3c03e6f47b57bf0761ebf374a6fb80cc463b06de
Signed-off-by: Keunho Hwang <keunho.hwang@samsung.com>
arch/arm64/boot/dts/exynos/exynos9610-erd9610_common.dtsi
arch/arm64/boot/dts/exynos/exynos9610_battery_data.dtsi
arch/arm64/boot/dts/exynos/exynos9610_erd_battery_data.dtsi [new file with mode: 0644]
arch/arm64/configs/erd9610_defconfig
drivers/mfd/s2mu004_core.c
drivers/power/supply/Kconfig
drivers/power/supply/Makefile
drivers/power/supply/s2mu00x_battery.c
drivers/power/supply/s2mu00x_erd_battery.c [new file with mode: 0644]
include/linux/power/s2mu00x_battery.h
include/linux/power/s2mu00x_erd_battery.h [new file with mode: 0644]

index abb74e61e511ce4d0d91ef5c95474b0d4c60d2f7..a3371717567926c0ebc17c8c8b44bd712947bf1b 100644 (file)
@@ -9,7 +9,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "exynos9610_battery_data.dtsi"
+#include "exynos9610_erd_battery_data.dtsi"
 #include <dt-bindings/clock/exynos9610.h>
 #include "modem-ss360ap-sit-pdata.dtsi"
 #include "exynos9610-display-lcd.dtsi"
index 941fcda1d70328418655daa72e2277a9b4ca36a7..8b0d44ac2a27cc7846ffaeac3eb1614714495339 100644 (file)
                                pinctrl-names = "default";
 
                                battery,vendor = "SDI SDI";
-                               battery,charger_name = "s2mu004-charger";
-                               battery,fuelgauge_name = "s2mu004-fuelgauge";
+                               battery,charger_name = "s2mu106-charger";
+                               battery,smallcharger_name = "s2mcs02-charger";
+                               battery,fuelgauge_name = "s2mu106-fuelgauge";
                                battery,technology = <2>; /* POWER_SUPPLY_TECHNOLOGY_LION */
 
                                battery,temp_high = <500>;
                                battery,temp_high_recovery = <450>;
                                battery,temp_low = <100>;
                                battery,temp_low_recovery = <150>;
+                               battery,low_temp_limit = <100>;
 
+                               battery,chg_float_voltage = <4400>;
                                battery,full_check_count = <3>;
-                               battery,chg_full_vcell = <4310>;
-                               battery,chg_recharge_vcell = <4250>;
+                               battery,chg_full_vcell = <4360>;
+                               battery,chg_recharge_vcell = <4300>;
 
                                battery,max_rawsoc = <100>;
 
                                battery,default_charging_current = <1000>;
                                battery,default_full_check_current = <300>;
 
-                               battery,max_input_current = <1200>;
-                               battery,max_charging_current = <1200>;
+                               battery,max_input_current = <3000>;
+                               battery,max_charging_current = <3000>;
+
+                               battery,pdo_max_input_vol = <5000>; /* mV */
+                               battery,pdo_max_chg_power = <15000>; /* mW */
+
+                               battery,small_input_current = <1000>;
+                               battery,small_charging_current = <1000>;
 
                                /* Order of current setting must be same with
                                 * POWER_SUPPLY_TYPE_ of power_supply.h
                                 */
                                battery,input_current_limit =
-                                       <500 450 500 1200 500 1200 1200 1000 1000 1000
-                                       1000 500 500 1200 1000 500 450>;
+                                       <500 450 500 3000 500 1200 1200 1000 1000 2000
+                                       1000 500 500 1500 2000 500 450>;
                                battery,fast_charging_current =
-                                       <500 450 500 1200 500 1200 1200 1000 1000 1000
-                                       1000 500 500 1200 1000 500 450>;
+                                       <500 450 500 3000 500 1200 1200 1000 1000 2000
+                                       1000 500 500 1500 2000 500 450>;
                                battery,full_check_current =
                                        <300 0 300 300 300 300 300 300 300 300
                                        300 300 300 300 300 300 0>;
 
-                               battery,battery_table3 =
-                                       <204 11 61 11 175 10 34 10 169 9
-                                       55 9 206 8 107 8 230 7 166 7
-                                       77 7 234 6 174 6 130 6 95 6
-                                       67 6 36 6 253 5 197 5 147 5
-                                       42 5 168 1 247 8 136 8 24 8
-                                       169 7 58 7 202 6 91 6 236 5
-                                       124 5 13 5 158 4 47 4 191 3
-                                       80 3 225 2 113 2 2 2 147 1
-                                       36 1 180 0 69 0 214 15>;
-
-                               battery,battery_table4 =
-                                       <62 62 61 60 61 60 59 60 60 58
-                                       58 58 58 58 58 58 59 60 62 64
-                                       76 154>;
-
-                               battery,batcap = <0xD0 0x20 0x34 0x08>; /* [0x0E] [0x0F] [0x10] [0x11] */
-                               battery,accum = <0x8 0x00>; /* [0x45] [0x44] */
-
-                               battery,soc_arr_val =
-                                       <11205 10662 10119 9575 9032 8488 7945 7402 6858 6315
-                                       5771 5228 4685 4141 3598 3054 2511 1968 1424 881
-                                       337 (-206)>;
-                               battery,ocv_arr_val =
-                                       <44747 44050 43353 42664 42077 41520 41006 40522 39872 39562
-                                       39127 38645 38349 38135 37966 37828 37676 37485 37211 36970
-                                       36454 32069>;
+                               /* Battery parameter for cell 1 */
+                               battery,battery_table3_cell1 =
+                                       <156 10 120 10 84 10 218 9 100 9
+                                       243 8 140 8 34 8 205 7 123 7
+                                       8 7 198 6 151 6 113 6 84 6
+                                       57 6 15 6 234 5 175 5 133 5
+                                       253 4 178 1 105 8 0 8 150 7
+                                       45 7 196 6 90 6 241 5 135 5
+                                       30 5 180 4 75 4 225 3 120 3
+                                       14 3 165 2 59 2 210 1 104 1
+                                       255 0 149 0 44 0 217 15>;
+
+                               battery,battery_table4_cell1 =
+                                       <27 27 27 27 27 27 27 28 27 27
+                                       27 27 28 28 28 28 28 28 28 30
+                                       32 103>;
+
+                               battery,batcap_cell1 = <0xB0 0x36 0xAC 0x0D>; /* [0x0E] [0x0F] [0x10] [0x11] */
+                               battery,accum_cell1 = <0x8 0x00>; /* [0x45] [0x44] */
+
+                               battery,soc_arr_val_cell1 =
+                                       <10515 10000 9484 8969 8454 7939 7424 6909 6394 5879
+                                       5364 4849 4334 3819 3304 2789 2274 1759 1244 729
+                                       214 (-191)>;
+                               battery,ocv_arr_val_cell1 =
+                                       <43259 43084 42910 42315 41740 41188 40683 40167 39749 39351
+                                       38791 38469 38237 38054 37911 37778 37574 37390 37106 36900
+                                       36236 32120>;
+
+                               battery,battery_param_ver_cell1 = <0x02>;
+
+                               /* Battery parameter for cell 2 */
+                               battery,battery_table3_cell2 =
+                                       <90 11 208 10 71 10 204 9 87 9
+                                       231 8 130 8 11 8 196 7 115 7
+                                       14 7 191 6 143 6 106 6 78 6
+                                       54 6 27 6 241 5 189 5 136 5
+                                       239 4 93 1 104 8 0 8 152 7
+                                       48 7 199 6 95 6 247 5 143 5
+                                       39 5 191 4 86 4 238 3 134 3
+                                       30 3 182 2 78 2 229 1 125 1
+                                       21 1 173 0 69 0 221 15>;
+
+                               battery,battery_table4_cell2 =
+                                       <51 51 97 97 97 97 96 97 96 96
+                                       96 96 97 98 100 101 104 107 113 124
+                                       138 206>;
+
+                               battery,batcap_cell2 = <0xB0 0x36 0xAC 0x0D>; /* [0x0E] [0x0F] [0x10] [0x11] */
+                               battery,accum_cell2 = <0x8 0x00>; /* [0x45] [0x44] */
+
+                               battery,soc_arr_val_cell2 =
+                                       <10508 10000 9491 8982 8474 7965 7456 6948 6439 5931
+                                       5422 4913 4405 3896 3387 2879 2370 1862 1353 844
+                                       336 (-172)>;
+                               battery,ocv_arr_val_cell2 =
+                                       <44189 43517 42845 42245 41672 41128 40635 40053 39708 39313
+                                       38816 38431 38198 38019 37880 37765 37631 37428 37172 36914
+                                       36167 31703>;
+
+                               battery,battery_param_ver_cell2 = <0x00>;
                        };
                };
        };
diff --git a/arch/arm64/boot/dts/exynos/exynos9610_erd_battery_data.dtsi b/arch/arm64/boot/dts/exynos/exynos9610_erd_battery_data.dtsi
new file mode 100644 (file)
index 0000000..229b1da
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SAMSUNG EXYNOS9610 ERD board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+       fragment@battery {
+               target-path = "/";
+               __overlay__ {
+                       battery {
+                               status = "okay";
+
+                               pinctrl-names = "default";
+
+                               battery,vendor = "SDI SDI";
+                               battery,charger_name = "s2mu004-charger";
+                               battery,fuelgauge_name = "s2mu004-fuelgauge";
+                               battery,technology = <2>; /* POWER_SUPPLY_TECHNOLOGY_LION */
+
+                               battery,temp_high = <500>;
+                               battery,temp_high_recovery = <450>;
+                               battery,temp_low = <100>;
+                               battery,temp_low_recovery = <150>;
+
+                               battery,full_check_count = <3>;
+                               battery,chg_full_vcell = <4310>;
+                               battery,chg_recharge_vcell = <4250>;
+
+                               battery,max_rawsoc = <100>;
+
+                               battery,default_input_current = <1000>;
+                               battery,default_charging_current = <1000>;
+                               battery,default_full_check_current = <300>;
+
+                               battery,max_input_current = <1200>;
+                               battery,max_charging_current = <1200>;
+
+                               /* Order of current setting must be same with
+                                * POWER_SUPPLY_TYPE_ of power_supply.h
+                                */
+                               battery,input_current_limit =
+                                       <500 450 500 1200 500 1200 1200 1000 1000 1000
+                                       1000 500 500 1200 1000 500 450>;
+                               battery,fast_charging_current =
+                                       <500 450 500 1200 500 1200 1200 1000 1000 1000
+                                       1000 500 500 1200 1000 500 450>;
+                               battery,full_check_current =
+                                       <300 0 300 300 300 300 300 300 300 300
+                                       300 300 300 300 300 300 0>;
+
+                               battery,battery_table3 =
+                                       <204 11 61 11 175 10 34 10 169 9
+                                       55 9 206 8 107 8 230 7 166 7
+                                       77 7 234 6 174 6 130 6 95 6
+                                       67 6 36 6 253 5 197 5 147 5
+                                       42 5 168 1 247 8 136 8 24 8
+                                       169 7 58 7 202 6 91 6 236 5
+                                       124 5 13 5 158 4 47 4 191 3
+                                       80 3 225 2 113 2 2 2 147 1
+                                       36 1 180 0 69 0 214 15>;
+
+                               battery,battery_table4 =
+                                       <62 62 61 60 61 60 59 60 60 58
+                                       58 58 58 58 58 58 59 60 62 64
+                                       76 154>;
+
+                               battery,batcap = <0xD0 0x20 0x34 0x08>; /* [0x0E] [0x0F] [0x10] [0x11] */
+                               battery,accum = <0x8 0x00>; /* [0x45] [0x44] */
+
+                               battery,soc_arr_val =
+                                       <11205 10662 10119 9575 9032 8488 7945 7402 6858 6315
+                                       5771 5228 4685 4141 3598 3054 2511 1968 1424 881
+                                       337 (-206)>;
+                               battery,ocv_arr_val =
+                                       <44747 44050 43353 42664 42077 41520 41006 40522 39872 39562
+                                       39127 38645 38349 38135 37966 37828 37676 37485 37211 36970
+                                       36454 32069>;
+                       };
+               };
+       };
+};
index 531fed7bcedf6a9f238cf46232b8944dac17b81e..926ad16e711116750f9e07844739edf344b53886 100755 (executable)
@@ -299,7 +299,7 @@ CONFIG_SPI_S3C64XX=y
 CONFIG_GPIOLIB=y
 CONFIG_FUELGAUGE_S2MU004=y
 CONFIG_CHARGER_S2MU004=y
-CONFIG_BATTERY_S2MU00X=y
+CONFIG_BATTERY_S2MU00X_ERD=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
index 0fc8cd9b481eb97609a2e6aca0095f503cf09d2c..b2578cb2afe3b9a1976c38b126ba7181596f8574 100644 (file)
@@ -50,7 +50,7 @@ static struct mfd_cell s2mu004_devs[] = {
 #if defined(CONFIG_CHARGER_S2MU004)
        { .name = "s2mu004-charger", },
 #endif
-#if defined(CONFIG_BATTERY_S2MU00X)
+#if defined(CONFIG_BATTERY_S2MU00X_ERD)
        { .name = "s2mu00x-battery", },
 #endif
 #if defined(CONFIG_LEDS_S2MU004_RGB)
index 4e2ffa4a3ffc3c05f28771ca4ada44988d992eb1..c6fdbc12845cacad46b9ac2fc6bf86ab3c0f2079 100644 (file)
@@ -629,10 +629,18 @@ config CHARGER_S2MU004
 
 config BATTERY_S2MU00X
     tristate "S2MU00x battery driver"
-       depends on (MFD_S2MU004) && I2C
+       depends on I2C
        help
          Say Y here to enable support for S2MU00x battery driver.
 
+config BATTERY_S2MU00X_ERD
+    tristate "S2MU00x ERD battery driver"
+       depends on I2C
+       help
+         Say Y here to enable support for S2MU00x ERD battery driver.
+         This battery driver supports only the basic functions for
+         ERD board.
+
 config FUELGAUGE_S2MU106
     tristate "S2MU106 fuelgauge driver"
     default n
index 78b70489714cde7a9e80088c2a0f2326ac1cef8b..de4e49b81101a85c62e9a351d70767c74e842b4b 100644 (file)
@@ -87,4 +87,5 @@ obj-$(CONFIG_CHARGER_S2MU004)   += s2mu004_charger.o
 obj-$(CONFIG_FUELGAUGE_S2MU106) += s2mu106_fuelgauge.o
 obj-$(CONFIG_CHARGER_S2MU106)   += s2mu106_charger.o s2mu106_pmeter.o
 obj-$(CONFIG_BATTERY_S2MU00X)   += s2mu00x_battery.o
+obj-$(CONFIG_BATTERY_S2MU00X_ERD)   += s2mu00x_erd_battery.o
 obj-$(CONFIG_CHARGER_S2MCS02)   += s2mcs02_charger.o
index 9d033b8980e278cf34bea50824ef4feb5a3a675d..8ecc694106a0fcd9e08f2ea976a4f622483fd165 100644 (file)
 #include <linux/module.h>
 #include <linux/of_gpio.h>
 #include <linux/wakelock.h>
-
 #include <linux/workqueue.h>
 #include <linux/power_supply.h>
 #include <linux/power/s2mu00x_battery.h>
+#include <linux/power/s2mu106_pmeter.h>
 #include <linux/alarmtimer.h>
 
-#if defined(CONFIG_MUIC_S2MU004)
-#if defined(CONFIG_MUIC_NOTIFIER)
-#include <linux/muic_mu004/s2mu004-muic-notifier.h>
-#include <linux/muic_mu004/muic.h>
-#endif /* CONFIG_MUIC_NOTIFIER */
-
-#if defined(CONFIG_IFCONN_NOTIFIER)
-#include <linux/ifconn/ifconn_notifier.h>
-#include <linux/ifconn/ifconn_manager.h>
-#include <linux/muic_mu004/s2mu004-muic-notifier.h>
-#include <linux/muic_mu004/muic.h>
-#endif
-#else /* CONFIG_MUIC_S2MU004 */
 #if defined(CONFIG_MUIC_NOTIFIER)
 #include <linux/muic/s2mu004-muic-notifier.h>
 #include <linux/muic/muic.h>
 #if defined(CONFIG_IFCONN_NOTIFIER)
 #include <linux/ifconn/ifconn_notifier.h>
 #include <linux/ifconn/ifconn_manager.h>
-#include <linux/muic/s2mu004-muic-notifier.h>
 #include <linux/muic/muic.h>
 #endif
-#endif /* CONFIG_MUIC_S2MU004 */
 
 #define FAKE_BAT_LEVEL 50
 #define DEFAULT_ALARM_INTERVAL 10
@@ -93,6 +78,10 @@ static enum power_supply_property s2mu00x_battery_props[] = {
        POWER_SUPPLY_PROP_CURRENT_AVG,
        POWER_SUPPLY_PROP_CHARGE_COUNTER,
        POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CHARGE_TEMP,
+       POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
+       POWER_SUPPLY_PROP_CALIBRATE,
+       POWER_SUPPLY_PROP_SOH,
 };
 
 static enum power_supply_property s2mu00x_power_props[] = {
@@ -102,16 +91,31 @@ static enum power_supply_property s2mu00x_power_props[] = {
 typedef struct s2mu00x_battery_platform_data {
        s2mu00x_charging_current_t *charging_current;
        char *charger_name;
+#if defined(CONFIG_SMALL_CHARGER)
+       char *smallcharger_name;
+#endif
        char *fuelgauge_name;
 
        int max_input_current;
        int max_charging_current;
 
+#if defined(CONFIG_SMALL_CHARGER)
+       int small_input_current;
+       int small_charging_current;
+#endif
+
+#if defined(CONFIG_USE_CCIC)
+       int pdo_max_input_vol;
+       int pdo_max_chg_power;
+#endif
+
        int temp_high;
        int temp_high_recovery;
        int temp_low;
        int temp_low_recovery;
 
+       int chg_float_voltage;
+
        /* full check */
        unsigned int full_check_count;
        unsigned int chg_recharge_vcell;
@@ -143,6 +147,7 @@ struct s2mu00x_battery_info {
        struct wake_lock monitor_wake_lock;
        struct workqueue_struct *monitor_wqueue;
        struct delayed_work monitor_work;
+       struct delayed_work soc_control;
        struct wake_lock vbus_wake_lock;
 
        struct alarm monitor_alarm;
@@ -152,6 +157,16 @@ struct s2mu00x_battery_info {
        int max_input_current;
        int charging_current;
        int max_charging_current;
+
+#if defined(CONFIG_USE_CCIC)
+       int pdo_max_input_vol;
+       int pdo_max_chg_power;
+
+       int pdo_sel_num;
+       int pdo_sel_vol;
+       int pdo_sel_cur;
+#endif
+
        int topoff_current;
        int cable_type;
        unsigned int charging_mode;
@@ -167,6 +182,8 @@ struct s2mu00x_battery_info {
        /* charging */
        bool is_recharging;
 
+       bool is_factory;        /* factory image support mode */
+
        bool battery_valid;
        int status;
        int health;
@@ -178,9 +195,17 @@ struct s2mu00x_battery_info {
        unsigned int capacity;
        unsigned int max_rawsoc;
 
-       int current_now;        /* current (mA) */
-       int current_avg;        /* average current (mA) */
-       int current_max;        /* input current limit (mA) */
+       int soh;        /* State of Health (%) */
+
+       int current_now;        /* current (mA) */
+       int current_avg;        /* average current (mA) */
+       int current_max;        /* input current limit (mA) */
+       int current_chg;        /* charge current limit (mA) */
+
+#if defined(CONFIG_SMALL_CHARGER)
+       int small_input;        /* input current limit (mA) */
+       int small_chg;  /* charge current limit (mA) */
+#endif
 
 #if defined(CONFIG_MUIC_NOTIFIER)
        struct notifier_block cable_check;
@@ -192,12 +217,18 @@ struct s2mu00x_battery_info {
        int temp_high_recovery;
        int temp_low;
        int temp_low_recovery;
+       int vchg_voltage;
+       int vchg_current;
+       int charge_temp;
 };
 
+static int is_charging_mode = S2MU00X_NOR_MODE;
+
+
 static char *s2mu00x_supplied_to[] = {
        "s2mu00x-battery",
 };
-
+#if defined(CONFIG_CHARGER_S2MU106)
 static void get_charging_current(struct s2mu00x_battery_info *battery,
                int *input_current, int *charging_current)
 {
@@ -231,7 +262,7 @@ static int set_charging_current(struct s2mu00x_battery_info *battery)
        mutex_lock(&battery->iolock);
 
        /*Limit input & charging current according to the max current*/
-       get_charging_current(battery, &input_current, &charging_current);
+       get_charging_current(battery, &input_current, &charging_current);\
 
        /* set input current limit */
        if (battery->input_current != input_current) {
@@ -272,7 +303,26 @@ static int set_charging_current(struct s2mu00x_battery_info *battery)
 
                battery->topoff_current = topoff_current;
        }
+#if defined(CONFIG_SMALL_CHARGER)
+       if (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA ||
+               battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) {
+               value.intval = battery->pdata->small_input_current;
+               psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
 
+               value.intval = battery->pdata->small_charging_current;
+               psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+       }
+#endif
        mutex_unlock(&battery->iolock);
        return 0;
 }
@@ -311,20 +361,45 @@ static int set_charger_mode(
        if (ret < 0)
                pr_err("%s: Fail to execute property\n", __func__);
 
+#if defined(CONFIG_SMALL_CHARGER)
+       if (charger_mode == S2MU00X_BAT_CHG_MODE_CHARGING &&
+                       (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA ||
+                        battery->cable_type == POWER_SUPPLY_TYPE_USB_PD)) {
+               psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGING_ENABLED, &val);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+       } else if (charger_mode != S2MU00X_BAT_CHG_MODE_CHARGING) {
+               psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGING_ENABLED, &val);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+       }
+#endif
+
        return 0;
 }
 
+#endif
 static int set_battery_status(struct s2mu00x_battery_info *battery,
                int status)
 {
        union power_supply_propval value;
+#if defined(CONFIG_CHARGER_S2MU106)
        struct power_supply *psy;
-               int ret;
-
+       int ret;
+#endif
        pr_info("%s: current status = %d, new status = %d\n", __func__, battery->status, status);
+#if 0
        if (battery->status == status)
                return 0;
+#endif
 
+#if defined(CONFIG_CHARGER_S2MU106)
        switch (status) {
        case POWER_SUPPLY_STATUS_CHARGING:
                /* notify charger cable type */
@@ -337,6 +412,19 @@ static int set_battery_status(struct s2mu00x_battery_info *battery,
                if (ret < 0)
                        pr_err("%s: Fail to execute property\n", __func__);
 
+#if defined(CONFIG_SMALL_CHARGER)
+               if (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA ||
+                       battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) {
+                       psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+                       if (!psy)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+               }
+#endif
+
+               /* charger on */
                set_charger_mode(battery, S2MU00X_BAT_CHG_MODE_CHARGING);
                set_charging_current(battery);
                break;
@@ -347,6 +435,18 @@ static int set_battery_status(struct s2mu00x_battery_info *battery,
                /* notify charger cable type */
                value.intval = battery->cable_type;
 
+#if defined(CONFIG_SMALL_CHARGER)
+               if (battery->cable_type == POWER_SUPPLY_TYPE_PREPARE_TA ||
+                       battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) {
+                       psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+                       if (!psy)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+               }
+#endif
+
                psy = power_supply_get_by_name(battery->pdata->charger_name);
                if (!psy)
                        return -EINVAL;
@@ -370,27 +470,38 @@ static int set_battery_status(struct s2mu00x_battery_info *battery,
                set_charger_mode(battery, S2MU00X_BAT_CHG_MODE_CHARGING_OFF);
                break;
        }
-
+#endif
        /* battery status update */
        battery->status = status;
        value.intval = battery->status;
-
+#if defined(CONFIG_CHARGER_S2MU106)
        psy = power_supply_get_by_name(battery->pdata->charger_name);
        if (!psy)
                return -EINVAL;
        ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_STATUS, &value);
        if (ret < 0)
                pr_err("%s: Fail to execute property\n", __func__);
-
+#endif
        return 0;
 }
 
 static void set_bat_status_by_cable(struct s2mu00x_battery_info *battery)
 {
+       if (battery->is_factory) {
+               pr_info("%s: factory image support mode. Skip!\n", __func__);
+               return;
+       }
+
+#if defined(CONFIG_CHARGER_S2MU106)
        if (battery->cable_type == POWER_SUPPLY_TYPE_BATTERY ||
                battery->cable_type == POWER_SUPPLY_TYPE_UNKNOWN ||
                battery->cable_type == POWER_SUPPLY_TYPE_OTG) {
                battery->is_recharging = false;
+#if defined(CONFIG_USE_CCIC)
+               battery->pdo_sel_num = 0;
+               battery->pdo_sel_vol = 0;
+               battery->pdo_sel_cur = 0;
+#endif
                set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
                return;
        }
@@ -400,6 +511,7 @@ static void set_bat_status_by_cable(struct s2mu00x_battery_info *battery)
        }
 
        dev_info(battery->dev, "%s: abnormal cable_type or status", __func__);
+#endif
 }
 
 static int s2mu00x_battery_get_property(struct power_supply *psy,
@@ -436,6 +548,9 @@ static int s2mu00x_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_TEMP:
                val->intval = battery->temperature;
                break;
+       case POWER_SUPPLY_PROP_CHARGE_TEMP:
+               val->intval = battery->charge_temp;
+               break;
        case POWER_SUPPLY_PROP_CHARGE_NOW:
                val->intval = battery->charging_mode;
                break;
@@ -469,6 +584,15 @@ static int s2mu00x_battery_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_CHARGE_FULL:
                val->intval = 100;
                break;
+       case POWER_SUPPLY_PROP_CALIBRATE:
+               val->intval = battery->is_factory;
+               break;
+       case POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION:
+               val->intval = battery->vchg_voltage;
+               break;
+       case POWER_SUPPLY_PROP_SOH:
+               val->intval = battery->soh;
+               break;
        default:
                ret = -ENODATA;
        }
@@ -481,6 +605,9 @@ static int s2mu00x_battery_set_property(struct power_supply *psy,
 {
        struct s2mu00x_battery_info *battery = power_supply_get_drvdata(psy);
        int ret = 0;
+       union power_supply_propval value;
+       struct power_supply *psy_dest;
+
 
        dev_dbg(battery->dev, "prop: %d\n", psp);
        switch (psp) {
@@ -493,6 +620,41 @@ static int s2mu00x_battery_set_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_ONLINE:
                battery->cable_type = val->intval;
                break;
+       case POWER_SUPPLY_PROP_CALIBRATE:
+               if (val->intval == S2MU00X_BAT_FAC_MODE_VBAT) {
+                       battery->is_factory = true;
+                       pr_info("%s: VBat factory image support mode\n", __func__);
+
+                       value.intval = S2MU00X_BAT_FAC_MODE_VBAT;
+                       psy_dest = power_supply_get_by_name(battery->pdata->charger_name);
+                       if (!psy_dest)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy_dest, POWER_SUPPLY_PROP_CALIBRATE, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+               } else if (val->intval == S2MU00X_BAT_FAC_MODE_VBUS) {
+                       battery->is_factory = true;
+                       pr_info("%s: VBUS charging factory image support mode\n", __func__);
+
+                       value.intval = S2MU00X_BAT_FAC_MODE_VBUS;
+                       psy_dest = power_supply_get_by_name(battery->pdata->charger_name);
+                       if (!psy_dest)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy_dest, POWER_SUPPLY_PROP_CALIBRATE, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+               } else {
+                       battery->is_factory = false;
+                       pr_info("%s: disable factory image support mode\n", __func__);
+
+                       /* Reset current setting for recovering */
+                       battery->input_current = 0;
+                       battery->charging_current = 0;
+                       battery->topoff_current = 0;
+
+                       set_bat_status_by_cable(battery);
+               }
+               break;
        default:
                ret = -EINVAL;
        }
@@ -500,6 +662,21 @@ static int s2mu00x_battery_set_property(struct power_supply *psy,
        return ret;
 }
 
+static int s2mu00x_battery_property_is_writeable(struct power_supply *psy,
+               enum power_supply_property psp)
+{
+       int ret;
+       switch (psp) {
+               case POWER_SUPPLY_PROP_CALIBRATE:
+                       ret = 1;
+                       break;
+               default:
+                       ret = 0;
+       }
+
+       return ret;
+}
+
 static int s2mu00x_usb_get_property(struct power_supply *psy,
                enum power_supply_property psp,
                union power_supply_propval *val)
@@ -543,6 +720,7 @@ static int s2mu00x_ac_get_property(struct power_supply *psy,
        case POWER_SUPPLY_TYPE_UNKNOWN:
        case POWER_SUPPLY_TYPE_PREPARE_TA:
        case POWER_SUPPLY_TYPE_HV_MAINS:
+       case POWER_SUPPLY_TYPE_USB_PD:
                val->intval = 1;
                break;
        default:
@@ -593,9 +771,6 @@ static int s2mu00x_bat_cable_check(struct s2mu00x_battery_info *battery,
                break;
        case ATTACHED_DEV_AFC_CHARGER_9V_MUIC:
        case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
-#if defined(CONFIG_HV_MUIC_S2MU004_PE)
-       case ATTACHED_DEV_PE_CHARGER_9V_MUIC:
-#endif
                current_cable_type = POWER_SUPPLY_TYPE_HV_MAINS;
                break;
        case ATTACHED_DEV_UNDEFINED_CHARGING_MUIC:
@@ -619,6 +794,13 @@ static int s2mu00x_bat_cable_check(struct s2mu00x_battery_info *battery,
                current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
                break;
 #endif
+#if defined(CONFIG_HV_MUIC_TURBO_CHARGER)
+       case ATTACHED_DEV_TURBO_CHARGER:
+               current_cable_type = POWER_SUPPLY_TYPE_HV_MAINS;
+               pr_info("[%s]Turbo charger ATTACHED\n", __func__);
+               break;
+#endif
+
        default:
                current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
                pr_err("%s: invalid type for charger:%d\n",
@@ -672,7 +854,7 @@ static int s2mu00x_battery_handle_notification(struct notifier_block *nb,
        pr_info("%s: CMD=%s, attached_dev=%d battery_cable=%d\n",
                        __func__, cmd, attached_dev, battery->cable_type);
 
-
+#if defined(CONFIG_CHARGER_S2MU106)
        if (attached_dev == ATTACHED_DEV_OTG_MUIC) {
                if (!strcmp(cmd, "ATTACH")) {
                        value.intval = true;
@@ -711,7 +893,7 @@ static int s2mu00x_battery_handle_notification(struct notifier_block *nb,
                                set_battery_status(battery, POWER_SUPPLY_STATUS_CHARGING);
                }
        }
-
+#endif
        pr_info(
                        "%s: Status(%s), Health(%s), Cable(%d), Recharging(%d))"
                        "\n", __func__,
@@ -729,6 +911,95 @@ static int s2mu00x_battery_handle_notification(struct notifier_block *nb,
 }
 #endif
 #if defined(CONFIG_IFCONN_NOTIFIER)
+#if defined(CONFIG_USE_CCIC)
+static int s2mu00x_bat_set_pdo(struct s2mu00x_battery_info *battery,
+               ifconn_pd_sink_status_t *pdo_data)
+{
+       int ret = -1;
+       int pdo_num = battery->pdo_sel_num;
+
+       if (pdo_num > pdo_data->available_pdo_num + 1 || pdo_num < 1) {
+               dev_info(battery->dev, "%s: wrong pdo number. Stop pdo select.\n",
+                               __func__);
+               return ret;
+       }
+
+       ret = ifconn_notifier_notify(IFCONN_NOTIFY_BATTERY,
+                       IFCONN_NOTIFY_MANAGER,
+                       IFCONN_NOTIFY_ID_SELECT_PDO,
+                       pdo_num,
+                       IFCONN_NOTIFY_PARAM_DATA,
+                       NULL);
+       if (ret < 0) {
+               pr_err("%s: Fail to send noti\n", __func__);
+               return ret;
+       }
+
+       ret = POWER_SUPPLY_TYPE_PREPARE_TA;
+
+       return ret;
+}
+
+static int s2mu00x_bat_pdo_check(struct s2mu00x_battery_info *battery,
+               struct ifconn_notifier_template *pdo_info)
+{
+       int current_cable = -1;
+       int i;
+       int pd_input_current_limit =
+               battery->pdata->charging_current[POWER_SUPPLY_TYPE_USB_PD].input_current_limit;
+       ifconn_pd_sink_status_t *pdo_data = pdo_info->data;
+
+       dev_info(battery->dev, "%s: available_pdo_num:%d, selected_pdo_num:%d,"
+               "current_pdo_num:%d\n",
+               __func__, pdo_data->available_pdo_num, pdo_data->selected_pdo_num,
+               pdo_data->current_pdo_num);
+
+       dev_info(battery->dev, "%s: pdo_max_input_vol:%d, pdo_max_chg_power:%d, "
+                       "pdo_sel_num:%d\n",
+                       __func__, battery->pdo_max_input_vol, battery->pdo_max_chg_power,
+                       battery->pdo_sel_num);
+
+       if (pdo_data->available_pdo_num < 0)
+               return current_cable;
+
+       if (battery->pdo_sel_num == pdo_data->selected_pdo_num) {
+               dev_info(battery->dev, "%s: Already done. Finish pdo check.\n",
+                               __func__);
+               current_cable = POWER_SUPPLY_TYPE_USB_PD;
+               goto end_pdo_check;
+       }
+
+       for (i = 1; i <= pdo_data->available_pdo_num + 1; i++) {
+               dev_info(battery->dev, "%s: pdo_num:%d, max_voltage:%d, max_current:%d\n",
+                               __func__, i, pdo_data->power_list[i].max_voltage,
+                               pdo_data->power_list[i].max_current);
+
+               if (pdo_data->power_list[i].max_voltage > battery->pdo_max_input_vol)
+                       continue;
+
+               pd_input_current_limit = (pd_input_current_limit > pdo_data->power_list[i].max_current)?
+                       pdo_data->power_list[i].max_current:pd_input_current_limit;
+
+               if (((pdo_data->power_list[i].max_voltage/1000) * pd_input_current_limit) <=
+                               battery->pdo_max_chg_power) {
+                               battery->pdo_sel_num = i;
+                               battery->pdo_sel_vol = pdo_data->power_list[i].max_voltage;
+                               battery->pdo_sel_cur = pdo_data->power_list[i].max_current;
+                               dev_info(battery->dev, "%s: new pdo_sel_num:%d\n",
+                                               __func__, battery->pdo_sel_num);
+               }
+       }
+
+       if (battery->pdo_sel_num == 0) {
+               dev_info(battery->dev, "%s: There is no proper pdo. Do normal TA setting\n", __func__);
+               current_cable = POWER_SUPPLY_TYPE_MAINS;
+       } else
+               current_cable = s2mu00x_bat_set_pdo(battery, pdo_data);
+
+end_pdo_check:
+       return current_cable;
+}
+#endif
 static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb,
                unsigned long action, void *data)
 {
@@ -758,9 +1029,35 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb,
                cable_type = POWER_SUPPLY_TYPE_BATTERY;
                break;
        case IFCONN_NOTIFY_ID_ATTACH:
+#if defined(CONFIG_USE_CCIC)
+               if (battery->cable_type == POWER_SUPPLY_TYPE_USB_PD) {
+                       pr_info("%s: PD TA is attached. Skip cable check\n", __func__);
+                       cable_type =  POWER_SUPPLY_TYPE_USB_PD;
+                       cmd = "PD ATTACH";
+                       break;
+               }
+#endif
                cmd = "ATTACH";
                cable_type = s2mu00x_bat_cable_check(battery, attached_dev);
                break;
+#if defined(CONFIG_USE_CCIC)
+       case IFCONN_NOTIFY_ID_POWER_STATUS:
+               cable_type = s2mu00x_bat_pdo_check(battery, ifconn_info);
+               switch (cable_type) {
+                       case POWER_SUPPLY_TYPE_USB_PD:
+                               cmd = "PD ATTACH";
+                               attached_dev = ATTACHED_DEV_TYPE3_CHARGER_MUIC;
+                               break;
+                       case POWER_SUPPLY_TYPE_PREPARE_TA:
+                               cmd = "PD PREPARE";
+                               attached_dev = ATTACHED_DEV_TYPE3_CHARGER_MUIC;
+                               break;
+                       default:
+                               cmd = "PD FAIL";
+                               break;
+               }
+               break;
+#endif
        default:
                cmd = "ERROR";
                cable_type = -1;
@@ -776,6 +1073,11 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb,
 
        battery->cable_type = cable_type;
 
+#if 0 // defined(CONFIG_USE_CCIC)
+       if (cable_type == POWER_SUPPLY_TYPE_PREPARE_TA)
+               goto end_ifconn_handle;
+#endif
+
        if (attached_dev == ATTACHED_DEV_OTG_MUIC) {
                if (!strcmp(cmd, "ATTACH")) {
                        value.intval = true;
@@ -803,6 +1105,9 @@ static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb,
        }
        set_bat_status_by_cable(battery);
 
+#if 0 //defined(CONFIG_USE_CCIC)
+end_ifconn_handle:
+#endif
        pr_info("%s: Status(%s), Health(%s), Cable(%d), Recharging(%d)\n",
                        __func__, bat_status_str[battery->status], health_str[battery->health],
                        battery->cable_type, battery->is_recharging);
@@ -822,6 +1127,7 @@ static void get_battery_capacity(struct s2mu00x_battery_info *battery)
        struct power_supply *psy;
        int ret;
        unsigned int raw_soc = 0;
+       int new_capacity = 0;
 
        psy = power_supply_get_by_name(battery->pdata->fuelgauge_name);
        ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &value);
@@ -832,9 +1138,21 @@ static void get_battery_capacity(struct s2mu00x_battery_info *battery)
        if (battery->status == POWER_SUPPLY_STATUS_FULL)
                battery->max_rawsoc = raw_soc;
 
-       battery->capacity = (raw_soc*100)/battery->max_rawsoc;
-       if (battery->capacity > 100)
-               battery->capacity = 100;
+       new_capacity = (raw_soc * 100) / battery->max_rawsoc;
+       if (new_capacity > 100)
+               new_capacity = 100;
+
+       if (new_capacity > battery->capacity)
+               new_capacity = battery->capacity + 1;
+       else if (new_capacity < battery->capacity)
+               new_capacity = battery->capacity - 1;
+
+       if (new_capacity > 100)
+               new_capacity = 100;
+       else if (new_capacity < 0)
+               new_capacity = 0;
+
+       battery->capacity = new_capacity;
 
        dev_info(battery->dev, "%s: SOC(%u), rawsoc(%d), max_rawsoc(%u).\n",
                __func__, battery->capacity, raw_soc, battery->max_rawsoc);
@@ -880,9 +1198,20 @@ static int get_battery_info(struct s2mu00x_battery_info *battery)
        if (ret < 0)
                pr_err("%s: Fail to execute property\n", __func__);
        battery->temperature = value.intval;
+       /* Get charge temperature info */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CHARGE_TEMP, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->charge_temp = value.intval;
 
        get_battery_capacity(battery);
 
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_SOH, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->soh = value.intval;
+
+#if defined(CONFIG_CHARGER_S2MU106)
        /*Get charger psy*/
        psy = power_supply_get_by_name(battery->pdata->charger_name);
        if (!psy)
@@ -894,6 +1223,12 @@ static int get_battery_info(struct s2mu00x_battery_info *battery)
                pr_err("%s: Fail to execute property\n", __func__);
        battery->current_max = value.intval;
 
+       /* Get charge current limit */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->current_chg = value.intval;
+
        /* Get charger status*/
        ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &value);
        if (ret < 0)
@@ -902,29 +1237,57 @@ static int get_battery_info(struct s2mu00x_battery_info *battery)
        if (battery->status != value.intval)
                pr_err("%s: battery status = %d, charger status = %d\n",
                                __func__, battery->status, value.intval);
+#endif
+
+       /* Get input voltage & current from powermeter */
+       battery->vchg_voltage = s2mu106_powermeter_get_vchg_voltage();
+       battery->vchg_current = s2mu106_powermeter_get_vchg_current();
 
        dev_info(battery->dev,
-                       "%s:Vnow(%dmV),Inow(%dmA),Imax(%dmA),SOC(%d%%),Tbat(%d)"
+                       "%s:Vnow(%dmV),Inow(%dmA),Imax(%dmA),Ichg(%dmA),SOC(%d%%),Tbat(%d),SOH(%d%%)"
+                       ",Vbus(%dmV),Ibus(%dmA)"
                        "\n", __func__,
                        battery->voltage_now, battery->current_now,
-                       battery->current_max, battery->capacity,
-                       battery->temperature
+                       battery->current_max, battery->current_chg, battery->capacity,
+                       battery->temperature, battery->soh,
+                       battery->vchg_voltage, battery->vchg_current
                        );
        dev_dbg(battery->dev,
                        "%s,Vavg(%dmV),Vocv(%dmV),Iavg(%dmA)\n",
                        battery->battery_valid ? "Connected" : "Disconnected",
                        battery->voltage_avg, battery->voltage_ocv, battery->current_avg);
 
+#if defined(CONFIG_SMALL_CHARGER)
+       psy = power_supply_get_by_name(battery->pdata->smallcharger_name);
+       if (!psy)
+               return -EINVAL;
+
+       /* Get input current limit */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->small_input = value.intval;
+
+       /* Get charge current limit */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->small_chg = value.intval;
+
+       dev_info(battery->dev,
+                       "%s: small Imax(%dmA), Ichg(%dmA)\n", __func__,
+                       battery->small_input, battery->small_chg);
+#endif
        return 0;
 }
 
 static int get_battery_health(struct s2mu00x_battery_info *battery)
 {
-       union power_supply_propval value;
        int health = POWER_SUPPLY_HEALTH_UNKNOWN;
+#if defined(CONFIG_CHARGER_S2MU106)
        struct power_supply *psy;
+       union power_supply_propval value;
        int ret;
-
        /* Get health status from charger */
        psy = power_supply_get_by_name(battery->pdata->charger_name);
        if (!psy)
@@ -934,6 +1297,9 @@ static int get_battery_health(struct s2mu00x_battery_info *battery)
                pr_err("%s: Fail to execute property\n", __func__);
 
        health = value.intval;
+#else
+       health = POWER_SUPPLY_HEALTH_GOOD;
+#endif
 
        return health;
 }
@@ -1073,12 +1439,13 @@ static void bat_monitor_work(struct work_struct *work)
 {
        struct s2mu00x_battery_info *battery =
                container_of(work, struct s2mu00x_battery_info, monitor_work.work);
+#if defined(CONFIG_CHARGER_S2MU106)
        union power_supply_propval value;
        struct power_supply *psy;
        int ret;
-
+#endif
        pr_info("%s: start monitoring\n", __func__);
-
+#if defined(CONFIG_CHARGER_S2MU106)
        psy = power_supply_get_by_name(battery->pdata->charger_name);
        if (!psy)
                return;
@@ -1092,16 +1459,24 @@ static void bat_monitor_work(struct work_struct *work)
                goto continue_monitor;
        } else
                battery->battery_valid = true;
-
+#else
+       battery->battery_valid = true;
+#endif
        get_battery_info(battery);
 
        check_health(battery);
 
        check_charging_full(battery);
 
-       power_supply_changed(battery->psy_battery);
+       if (is_charging_mode == S2MU00X_FAC_MODE) {
+               pr_info("%s: Factory boot mode and reinsert adapter, stop charging\n", __func__);
+               set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
+       }
 
+       power_supply_changed(battery->psy_battery);
+#if defined(CONFIG_CHARGER_S2MU106)
 continue_monitor:
+#endif
        pr_err(
                 "%s: Status(%s), Health(%s), Cable(%d), Recharging(%d))"
                 "\n", __func__,
@@ -1142,6 +1517,13 @@ static int s2mu00x_battery_parse_dt(struct device *dev,
        if (ret)
                pr_info("%s: Charger name is empty\n", __func__);
 
+#if defined(CONFIG_SMALL_CHARGER)
+       ret = of_property_read_string(np,
+                       "battery,smallcharger_name", (char const **)&pdata->smallcharger_name);
+       if (ret)
+               pr_info("%s: Small charger name is empty\n", __func__);
+#endif
+
        ret = of_property_read_string(np,
                        "battery,fuelgauge_name", (char const **)&pdata->fuelgauge_name);
        if (ret)
@@ -1218,6 +1600,34 @@ static int s2mu00x_battery_parse_dt(struct device *dev,
        if (ret)
                pr_info("%s : max_charging_current is empty\n", __func__);
 
+#if defined(CONFIG_SMALL_CHARGER)
+       ret = of_property_read_u32(np, "battery,small_input_current",
+                       &pdata->small_input_current);
+       if (ret) {
+               pr_info("%s : small_input_current is empty\n", __func__);
+               pdata->small_input_current = 500;
+       }
+
+       ret = of_property_read_u32(np, "battery,small_charging_current",
+                       &pdata->small_charging_current);
+       if (ret) {
+               pr_info("%s : small_charging_current is empty\n", __func__);
+               pdata->small_charging_current = 800;
+       }
+#endif
+
+#if defined(CONFIG_USE_CCIC)
+       ret = of_property_read_u32(np, "battery,pdo_max_chg_power",
+                       &pdata->pdo_max_chg_power);
+       if (ret)
+               pr_info("%s : pdo_max_chg_power is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,pdo_max_input_vol",
+                       &pdata->pdo_max_input_vol);
+       if (ret)
+               pr_info("%s : pdo_max_input_vol is empty\n", __func__);
+#endif
+
        ret = of_property_read_u32(np, "battery,temp_high", &temp);
        if (ret) {
                pr_info("%s : temp_high is empty\n", __func__);
@@ -1251,6 +1661,13 @@ static int s2mu00x_battery_parse_dt(struct device *dev,
                        pdata->temp_high, pdata->temp_high_recovery,
                        pdata->temp_low, pdata->temp_low_recovery);
 
+       ret = of_property_read_u32(np, "battery,chg_float_voltage",
+                       &pdata->chg_float_voltage);
+       if (ret) {
+               pr_info("%s : chg_float_voltage is empty\n", __func__);
+               pdata->chg_float_voltage = 4200;
+       }
+
        ret = of_property_read_u32(np, "battery,full_check_count",
                        &pdata->full_check_count);
        if (ret)
@@ -1300,6 +1717,22 @@ static enum alarmtimer_restart bat_monitor_alarm(
        return ALARMTIMER_NORESTART;
 }
 
+static void soc_control_worker(struct work_struct *work)
+{
+       struct s2mu00x_battery_info *battery =
+               container_of(work, struct s2mu00x_battery_info, soc_control.work);
+
+       pr_info("%s: S2MU00x battery capacity = %d, status = %d\n",
+               __func__, battery->capacity, battery->status);
+
+       if ((battery->capacity >= 75) && (battery->status == POWER_SUPPLY_STATUS_CHARGING)) {
+               pr_info("%s: Capacity is more than 75, stop charging\n", __func__);
+               set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
+       }
+
+       queue_delayed_work(battery->monitor_wqueue, &battery->soc_control, 10*HZ);
+}
+
 static int s2mu00x_battery_probe(struct platform_device *pdev)
 {
        struct s2mu00x_battery_info *battery;
@@ -1361,7 +1794,10 @@ static int s2mu00x_battery_probe(struct platform_device *pdev)
 
        battery->max_input_current = battery->pdata->max_input_current;
        battery->max_charging_current = battery->pdata->max_charging_current;
-
+#if defined(CONFIG_USE_CCIC)
+       battery->pdo_max_input_vol = battery->pdata->pdo_max_input_vol;
+       battery->pdo_max_chg_power = battery->pdata->pdo_max_chg_power;
+#endif
        battery->temp_high = battery->pdata->temp_high;
        battery->temp_high_recovery = battery->pdata->temp_high_recovery;
        battery->temp_low = battery->pdata->temp_low;
@@ -1369,9 +1805,11 @@ static int s2mu00x_battery_probe(struct platform_device *pdev)
 
        battery->max_rawsoc = battery->pdata->max_rawsoc;
 
+       battery->is_factory = false;
+
        battery->is_recharging = false;
        battery->cable_type = POWER_SUPPLY_TYPE_BATTERY;
-
+#if defined(CONFIG_CHARGER_S2MU106)
        psy = power_supply_get_by_name(battery->pdata->charger_name);
        if (!psy)
                return -EINVAL;
@@ -1383,12 +1821,15 @@ static int s2mu00x_battery_probe(struct platform_device *pdev)
                battery->battery_valid = false;
        else
                battery->battery_valid = true;
-
+#else
+       battery->battery_valid = true;
+#endif
        /* Register battery as "POWER_SUPPLY_TYPE_BATTERY" */
        battery->psy_battery_desc.name = "battery";
        battery->psy_battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
        battery->psy_battery_desc.get_property =  s2mu00x_battery_get_property;
        battery->psy_battery_desc.set_property =  s2mu00x_battery_set_property;
+       battery->psy_battery_desc.property_is_writeable =  s2mu00x_battery_property_is_writeable;
        battery->psy_battery_desc.properties = s2mu00x_battery_props;
        battery->psy_battery_desc.num_properties =  ARRAY_SIZE(s2mu00x_battery_props);
 
@@ -1459,11 +1900,21 @@ static int s2mu00x_battery_probe(struct platform_device *pdev)
 
        battery->capacity = value.intval;
 
+       /* Set float voltage for charger */
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return -EINVAL;
+       value.intval = battery->pdata->chg_float_voltage;
+       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_VOLTAGE_MAX, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+
 #if defined(CONFIG_IFCONN_NOTIFIER)
        ifconn_notifier_register(&battery->ifconn_nb,
                        s2mu00x_ifconn_handle_notification,
                        IFCONN_NOTIFY_BATTERY,
-                       IFCONN_NOTIFY_MUIC);
+                       IFCONN_NOTIFY_MANAGER);
 #elif defined(CONFIG_MUIC_NOTIFIER)
        pr_info("%s: Register MUIC notifier\n", __func__);
        muic_notifier_register(&battery->batt_nb, s2mu00x_battery_handle_notification,
@@ -1474,6 +1925,18 @@ static int s2mu00x_battery_probe(struct platform_device *pdev)
        pr_info("%s: start battery monitoring work\n", __func__);
        queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 5*HZ);
 
+       if ((is_charging_mode == S2MU00X_POWEROFF_CHG_MODE) ||
+               (is_charging_mode == S2MU00X_NOR_MODE)) {
+               pr_info("%s: Poweroff charger mode, enable charging\n", __func__);
+               INIT_DELAYED_WORK(&battery->soc_control, soc_control_worker);
+               queue_delayed_work(battery->monitor_wqueue, &battery->soc_control, 5*HZ);
+       } else if (is_charging_mode == S2MU00X_FAC_MODE) {
+               pr_info("%s: Factory boot mode, stop charging\n", __func__);
+               set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
+       } else {
+
+       }
+
        dev_info(battery->dev, "%s: Battery driver is loaded\n", __func__);
        return 0;
 
@@ -1506,6 +1969,7 @@ static int s2mu00x_battery_prepare(struct device *dev)
        struct s2mu00x_battery_info *battery = dev_get_drvdata(dev);
 
        alarm_cancel(&battery->monitor_alarm);
+       cancel_delayed_work_sync(&battery->monitor_work);
        wake_unlock(&battery->monitor_wake_lock);
        /* If charger is connected, monitoring is required*/
        if (battery->cable_type != POWER_SUPPLY_TYPE_BATTERY) {
@@ -1582,6 +2046,19 @@ static void __exit s2mu00x_battery_exit(void)
 }
 module_exit(s2mu00x_battery_exit);
 
+static int __init is_poweroff_charging_mode(char *str)
+{
+       if (strncmp("charger", str, 7) == 0)
+               is_charging_mode = S2MU00X_POWEROFF_CHG_MODE;
+       else if (strncmp("factory", str, 7) == 0)
+               is_charging_mode = S2MU00X_FAC_MODE;
+       else {
+               is_charging_mode = S2MU00X_NOR_MODE;
+       }
+
+       return 0;
+} early_param("androidboot.mode", is_poweroff_charging_mode);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Samsung Electronics");
 MODULE_DESCRIPTION("Battery driver for S2MU00x");
diff --git a/drivers/power/supply/s2mu00x_erd_battery.c b/drivers/power/supply/s2mu00x_erd_battery.c
new file mode 100644 (file)
index 0000000..7f80eda
--- /dev/null
@@ -0,0 +1,1586 @@
+/*
+ * s2mu00x_erd_battery.c - Example battery driver for Exynos9610 ERD board
+ *
+ * Copyright (C) 2017 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/printk.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/wakelock.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+#include <linux/power/s2mu00x_erd_battery.h>
+#include <linux/alarmtimer.h>
+
+#if defined(CONFIG_MUIC_S2MU004)
+#if defined(CONFIG_MUIC_NOTIFIER)
+#include <linux/muic_mu004/s2mu004-muic-notifier.h>
+#include <linux/muic_mu004/muic.h>
+#endif /* CONFIG_MUIC_NOTIFIER */
+
+#if defined(CONFIG_IFCONN_NOTIFIER)
+#include <linux/ifconn/ifconn_notifier.h>
+#include <linux/ifconn/ifconn_manager.h>
+#include <linux/muic_mu004/s2mu004-muic-notifier.h>
+#include <linux/muic_mu004/muic.h>
+#endif
+#else /* CONFIG_MUIC_S2MU004 */
+#if defined(CONFIG_MUIC_NOTIFIER)
+#include <linux/muic/s2mu004-muic-notifier.h>
+#include <linux/muic/muic.h>
+#endif /* CONFIG_MUIC_NOTIFIER */
+
+#if defined(CONFIG_IFCONN_NOTIFIER)
+#include <linux/ifconn/ifconn_notifier.h>
+#include <linux/ifconn/ifconn_manager.h>
+#include <linux/muic/s2mu004-muic-notifier.h>
+#include <linux/muic/muic.h>
+#endif
+#endif /* CONFIG_MUIC_S2MU004 */
+
+#define FAKE_BAT_LEVEL 50
+#define DEFAULT_ALARM_INTERVAL 10
+#define SLEEP_ALARM_INTERVAL   30
+
+static char *bat_status_str[] = {
+       "Unknown",
+       "Charging",
+       "Discharging",
+       "Not-charging",
+       "Full"
+};
+
+static char *health_str[] = {
+       "Unknown",
+       "Good",
+       "Overheat",
+       "Dead",
+       "OverVoltage",
+       "UnspecFailure",
+       "Cold",
+       "WatchdogTimerExpire",
+       "SafetyTimerExpire",
+       "UnderVoltage",
+};
+
+static enum power_supply_property s2mu00x_battery_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_VOLTAGE_AVG,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CURRENT_AVG,
+       POWER_SUPPLY_PROP_CHARGE_COUNTER,
+       POWER_SUPPLY_PROP_CHARGE_FULL,
+};
+
+static enum power_supply_property s2mu00x_power_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
+typedef struct s2mu00x_battery_platform_data {
+       s2mu00x_charging_current_t *charging_current;
+       char *charger_name;
+       char *fuelgauge_name;
+
+       int max_input_current;
+       int max_charging_current;
+
+       int temp_high;
+       int temp_high_recovery;
+       int temp_low;
+       int temp_low_recovery;
+
+       /* full check */
+       unsigned int full_check_count;
+       unsigned int chg_recharge_vcell;
+       unsigned int chg_full_vcell;
+
+       /* Initial maximum raw SOC */
+       unsigned int max_rawsoc;
+
+       /* battery */
+       char *vendor;
+       int technology;
+       int battery_type;
+       void *battery_data;
+} s2mu00x_battery_platform_data_t;
+
+struct s2mu00x_battery_info {
+       struct device *dev;
+       s2mu00x_battery_platform_data_t *pdata;
+
+       struct power_supply *psy_battery;
+       struct power_supply_desc psy_battery_desc;
+       struct power_supply *psy_usb;
+       struct power_supply_desc psy_usb_desc;
+       struct power_supply *psy_ac;
+       struct power_supply_desc psy_ac_desc;
+
+       struct mutex iolock;
+
+       struct wake_lock monitor_wake_lock;
+       struct workqueue_struct *monitor_wqueue;
+       struct delayed_work monitor_work;
+       struct wake_lock vbus_wake_lock;
+
+       struct alarm monitor_alarm;
+       unsigned int monitor_alarm_interval;
+
+       int input_current;
+       int max_input_current;
+       int charging_current;
+       int max_charging_current;
+       int topoff_current;
+       int cable_type;
+       unsigned int charging_mode;
+
+#if defined(CONFIG_IFCONN_NOTIFIER)
+       struct notifier_block ifconn_nb;
+#elif defined(CONFIG_MUIC_NOTIFIER)
+       struct notifier_block batt_nb;
+#endif
+
+       int full_check_cnt;
+
+       /* charging */
+       bool is_recharging;
+
+       bool battery_valid;
+       int status;
+       int health;
+
+       int voltage_now;
+       int voltage_avg;
+       int voltage_ocv;
+
+       unsigned int capacity;
+       unsigned int max_rawsoc;
+
+       int current_now;        /* current (mA) */
+       int current_avg;        /* average current (mA) */
+       int current_max;        /* input current limit (mA) */
+
+#if defined(CONFIG_MUIC_NOTIFIER)
+       struct notifier_block cable_check;
+#endif
+
+       /* temperature check */
+       int temperature;    /* battery temperature(0.1 Celsius)*/
+       int temp_high;
+       int temp_high_recovery;
+       int temp_low;
+       int temp_low_recovery;
+};
+
+static char *s2mu00x_supplied_to[] = {
+       "s2mu00x-battery",
+};
+
+static void get_charging_current(struct s2mu00x_battery_info *battery,
+               int *input_current, int *charging_current)
+{
+       int max_input_current = battery->max_input_current;
+       int max_charging_current = battery->max_charging_current;
+
+       if (*input_current > max_input_current) {
+               *input_current = max_input_current;
+               pr_info("%s: limit input current. (%d)\n", __func__, *input_current);
+       }
+       if (*charging_current > max_charging_current) {
+               *charging_current = max_charging_current;
+               pr_info("%s: limit charging current. (%d)\n", __func__, *charging_current);
+       }
+}
+
+static int set_charging_current(struct s2mu00x_battery_info *battery)
+{
+       union power_supply_propval value;
+       int input_current =
+                       battery->pdata->charging_current[battery->cable_type].input_current_limit,
+               charging_current =
+                       battery->pdata->charging_current[battery->cable_type].fast_charging_current,
+               topoff_current =
+                       battery->pdata->charging_current[battery->cable_type].full_check_current;
+       struct power_supply *psy;
+       int ret;
+
+       pr_info("%s: cable_type(%d), current(%d, %d, %d)\n", __func__,
+                       battery->cable_type, input_current, charging_current, topoff_current);
+       mutex_lock(&battery->iolock);
+
+       /*Limit input & charging current according to the max current*/
+       get_charging_current(battery, &input_current, &charging_current);
+
+       /* set input current limit */
+       if (battery->input_current != input_current) {
+               value.intval = input_current;
+
+               psy = power_supply_get_by_name(battery->pdata->charger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+
+               battery->input_current = input_current;
+       }
+       /* set fast charging current */
+       if (battery->charging_current != charging_current) {
+               value.intval = charging_current;
+
+               psy = power_supply_get_by_name(battery->pdata->charger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+
+               battery->charging_current = charging_current;
+       }
+       /* set topoff current */
+       if (battery->topoff_current != topoff_current) {
+               value.intval = topoff_current;
+
+               psy = power_supply_get_by_name(battery->pdata->charger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CURRENT_FULL, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+
+               battery->topoff_current = topoff_current;
+       }
+
+       mutex_unlock(&battery->iolock);
+       return 0;
+}
+
+
+/*
+ * set_charger_mode(): charger_mode must have one of following values.
+ * 1. S2MU00X_BAT_CHG_MODE_CHARGING
+ *     Charger on.
+ *     Supply power to system & battery both.
+ * 2. S2MU00X_BAT_CHG_MODE_CHARGING_OFF
+ *     Buck mode. Stop battery charging.
+ *     But charger supplies system power.
+ * 3. S2MU00X_BAT_CHG_MODE_BUCK_OFF
+ *     All off. Charger is completely off.
+ *     Do not supply power to battery & system both.
+ */
+
+static int set_charger_mode(
+               struct s2mu00x_battery_info *battery,
+               int charger_mode)
+{
+       union power_supply_propval val;
+       struct power_supply *psy;
+               int ret;
+
+       if (charger_mode != S2MU00X_BAT_CHG_MODE_CHARGING)
+               battery->full_check_cnt = 0;
+
+       val.intval = charger_mode;
+
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return -EINVAL;
+       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGING_ENABLED, &val);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       return 0;
+}
+
+static int set_battery_status(struct s2mu00x_battery_info *battery,
+               int status)
+{
+       union power_supply_propval value;
+       struct power_supply *psy;
+               int ret;
+
+       pr_info("%s: current status = %d, new status = %d\n", __func__, battery->status, status);
+       if (battery->status == status)
+               return 0;
+
+       switch (status) {
+       case POWER_SUPPLY_STATUS_CHARGING:
+               /* notify charger cable type */
+               value.intval = battery->cable_type;
+
+               psy = power_supply_get_by_name(battery->pdata->charger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+
+               set_charger_mode(battery, S2MU00X_BAT_CHG_MODE_CHARGING);
+               set_charging_current(battery);
+               break;
+
+       case POWER_SUPPLY_STATUS_DISCHARGING:
+               set_charging_current(battery);
+
+               /* notify charger cable type */
+               value.intval = battery->cable_type;
+
+               psy = power_supply_get_by_name(battery->pdata->charger_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+
+               set_charger_mode(battery, S2MU00X_BAT_CHG_MODE_CHARGING_OFF);
+               break;
+
+       case POWER_SUPPLY_STATUS_NOT_CHARGING:
+               set_charger_mode(battery, S2MU00X_BAT_CHG_MODE_BUCK_OFF);
+
+               /* to recover charger configuration when heath is recovered */
+               battery->input_current = 0;
+               battery->charging_current = 0;
+               battery->topoff_current = 0;
+               break;
+
+       case POWER_SUPPLY_STATUS_FULL:
+               set_charger_mode(battery, S2MU00X_BAT_CHG_MODE_CHARGING_OFF);
+               break;
+       }
+
+       /* battery status update */
+       battery->status = status;
+       value.intval = battery->status;
+
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return -EINVAL;
+       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_STATUS, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       return 0;
+}
+
+static void set_bat_status_by_cable(struct s2mu00x_battery_info *battery)
+{
+       if (battery->cable_type == POWER_SUPPLY_TYPE_BATTERY ||
+               battery->cable_type == POWER_SUPPLY_TYPE_UNKNOWN ||
+               battery->cable_type == POWER_SUPPLY_TYPE_OTG) {
+               battery->is_recharging = false;
+               set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
+               return;
+       }
+       if (battery->status != POWER_SUPPLY_STATUS_FULL) {
+               set_battery_status(battery, POWER_SUPPLY_STATUS_CHARGING);
+               return;
+       }
+
+       dev_info(battery->dev, "%s: abnormal cable_type or status", __func__);
+}
+
+static int s2mu00x_battery_get_property(struct power_supply *psy,
+               enum power_supply_property psp, union power_supply_propval *val)
+{
+       struct s2mu00x_battery_info *battery =  power_supply_get_drvdata(psy);
+       int ret = 0;
+       union power_supply_propval value;
+
+       dev_dbg(battery->dev, "prop: %d\n", psp);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               val->intval = battery->status;
+               break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               val->intval = battery->health;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = battery->cable_type;
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = battery->battery_valid;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               if (!battery->battery_valid)
+                       val->intval = FAKE_BAT_LEVEL;
+               else
+                       val->intval = battery->voltage_now * 1000;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+               val->intval = battery->voltage_avg * 1000;
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = battery->temperature;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               val->intval = battery->charging_mode;
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY:
+               if (!battery->battery_valid)
+                       val->intval = FAKE_BAT_LEVEL;
+               else {
+                       if (battery->status == POWER_SUPPLY_STATUS_FULL)
+                               val->intval = 100;
+                       else
+                               val->intval = battery->capacity;
+               }
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               val->intval = battery->current_now;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               val->intval = battery->current_avg;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+               /*Get fuelgauge psy*/
+               psy = power_supply_get_by_name(battery->pdata->fuelgauge_name);
+               if (!psy)
+                       return -EINVAL;
+               ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CHARGE_COUNTER, &value);
+               if (ret < 0)
+                       pr_err("%s: Fail to execute property\n", __func__);
+
+               val->intval = value.intval;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL:
+               val->intval = 100;
+               break;
+       default:
+               ret = -ENODATA;
+       }
+       return ret;
+}
+
+static int s2mu00x_battery_set_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               const union power_supply_propval *val)
+{
+       struct s2mu00x_battery_info *battery = power_supply_get_drvdata(psy);
+       int ret = 0;
+
+       dev_dbg(battery->dev, "prop: %d\n", psp);
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               set_battery_status(battery, val->intval);
+               break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               battery->health = val->intval;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               battery->cable_type = val->intval;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int s2mu00x_usb_get_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               union power_supply_propval *val)
+{
+       struct s2mu00x_battery_info *battery =  power_supply_get_drvdata(psy);
+
+       if (psp != POWER_SUPPLY_PROP_ONLINE)
+               return -EINVAL;
+
+       /* Set enable=1 only if the USB charger is connected */
+       switch (battery->cable_type) {
+       case POWER_SUPPLY_TYPE_USB:
+       case POWER_SUPPLY_TYPE_USB_DCP:
+       case POWER_SUPPLY_TYPE_USB_CDP:
+       case POWER_SUPPLY_TYPE_USB_ACA:
+               val->intval = 1;
+               break;
+       default:
+               val->intval = 0;
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * AC charger operations
+ */
+static int s2mu00x_ac_get_property(struct power_supply *psy,
+               enum power_supply_property psp,
+               union power_supply_propval *val)
+{
+       struct s2mu00x_battery_info *battery =  power_supply_get_drvdata(psy);
+
+       if (psp != POWER_SUPPLY_PROP_ONLINE)
+               return -EINVAL;
+
+       /* Set enable=1 only if the AC charger is connected */
+       switch (battery->cable_type) {
+       case POWER_SUPPLY_TYPE_MAINS:
+       case POWER_SUPPLY_TYPE_UNKNOWN:
+       case POWER_SUPPLY_TYPE_PREPARE_TA:
+       case POWER_SUPPLY_TYPE_HV_MAINS:
+               val->intval = 1;
+               break;
+       default:
+               val->intval = 0;
+               break;
+       }
+
+       return 0;
+}
+
+#if defined(CONFIG_MUIC_NOTIFIER) || defined(CONFIG_IFCONN_NOTIFIER)
+static int s2mu00x_bat_cable_check(struct s2mu00x_battery_info *battery,
+               muic_attached_dev_t attached_dev)
+{
+       int current_cable_type = -1;
+
+       pr_info("[%s]ATTACHED(%d)\n", __func__, attached_dev);
+
+       switch (attached_dev) {
+       case ATTACHED_DEV_SMARTDOCK_MUIC:
+       case ATTACHED_DEV_DESKDOCK_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+               break;
+       case ATTACHED_DEV_OTG_MUIC:
+       case ATTACHED_DEV_HMT_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_OTG;
+               break;
+       case ATTACHED_DEV_USB_MUIC:
+       case ATTACHED_DEV_SMARTDOCK_USB_MUIC:
+       case ATTACHED_DEV_UNOFFICIAL_ID_USB_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_USB;
+               break;
+       case ATTACHED_DEV_TA_MUIC:
+       case ATTACHED_DEV_CARDOCK_MUIC:
+       case ATTACHED_DEV_DESKDOCK_VB_MUIC:
+       case ATTACHED_DEV_SMARTDOCK_TA_MUIC:
+       case ATTACHED_DEV_AFC_CHARGER_5V_MUIC:
+       case ATTACHED_DEV_UNOFFICIAL_TA_MUIC:
+       case ATTACHED_DEV_UNOFFICIAL_ID_TA_MUIC:
+       case ATTACHED_DEV_UNOFFICIAL_ID_ANY_MUIC:
+       case ATTACHED_DEV_QC_CHARGER_5V_MUIC:
+       case ATTACHED_DEV_UNSUPPORTED_ID_VB_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_MAINS;
+               break;
+       case ATTACHED_DEV_CDP_MUIC:
+       case ATTACHED_DEV_UNOFFICIAL_ID_CDP_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_USB_CDP;
+               break;
+       case ATTACHED_DEV_AFC_CHARGER_9V_MUIC:
+       case ATTACHED_DEV_QC_CHARGER_9V_MUIC:
+#if defined(CONFIG_HV_MUIC_S2MU004_PE)
+       case ATTACHED_DEV_PE_CHARGER_9V_MUIC:
+#endif
+               current_cable_type = POWER_SUPPLY_TYPE_HV_MAINS;
+               break;
+       case ATTACHED_DEV_UNDEFINED_CHARGING_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
+               break;
+#if defined(CONFIG_IFCONN_NOTIFIER)
+       case ATTACHED_DEV_UNDEFINED_RANGE_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+               break;
+       case ATTACHED_DEV_TIMEOUT_OPEN_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_USB;
+               break;
+       case ATTACHED_DEV_AFC_CHARGER_PREPARE_MUIC:
+       case ATTACHED_DEV_QC_CHARGER_PREPARE_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_PREPARE_TA;
+               break;
+       case ATTACHED_DEV_AFC_CHARGER_9V_DUPLI_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_HV_MAINS;
+               break;
+       case ATTACHED_DEV_VZW_INCOMPATIBLE_MUIC:
+               current_cable_type = POWER_SUPPLY_TYPE_UNKNOWN;
+               break;
+#endif
+       default:
+               current_cable_type = POWER_SUPPLY_TYPE_BATTERY;
+               pr_err("%s: invalid type for charger:%d\n",
+                               __func__, attached_dev);
+       }
+
+       return current_cable_type;
+}
+#endif
+
+#if defined(CONFIG_MUIC_NOTIFIER)
+static int s2mu00x_battery_handle_notification(struct notifier_block *nb,
+               unsigned long action, void *data)
+{
+       muic_attached_dev_t attached_dev = *(muic_attached_dev_t *)data;
+       const char *cmd;
+       int cable_type;
+       union power_supply_propval value;
+       struct s2mu00x_battery_info *battery =
+               container_of(nb, struct s2mu00x_battery_info, batt_nb);
+       struct power_supply *psy;
+       int ret;
+
+       if (attached_dev == ATTACHED_DEV_MHL_MUIC)
+               return 0;
+
+       switch (action) {
+       case MUIC_NOTIFY_CMD_DETACH:
+       case MUIC_NOTIFY_CMD_LOGICALLY_DETACH:
+               cmd = "DETACH";
+               cable_type = POWER_SUPPLY_TYPE_BATTERY;
+               break;
+       case MUIC_NOTIFY_CMD_ATTACH:
+       case MUIC_NOTIFY_CMD_LOGICALLY_ATTACH:
+               cmd = "ATTACH";
+               cable_type = s2mu00x_bat_cable_check(battery, attached_dev);
+               break;
+       default:
+               cmd = "ERROR";
+               cable_type = -1;
+               break;
+       }
+
+       pr_info("%s: current_cable(%d) former cable_type(%d) battery_valid(%d)\n",
+                       __func__, cable_type, battery->cable_type,
+                       battery->battery_valid);
+       if (battery->battery_valid == false)
+               pr_info("%s: Battery is disconnected\n", __func__);
+
+       battery->cable_type = cable_type;
+       pr_info("%s: CMD=%s, attached_dev=%d battery_cable=%d\n",
+                       __func__, cmd, attached_dev, battery->cable_type);
+
+
+       if (attached_dev == ATTACHED_DEV_OTG_MUIC) {
+               if (!strcmp(cmd, "ATTACH")) {
+                       value.intval = true;
+
+                       psy = power_supply_get_by_name(battery->pdata->charger_name);
+                       if (!psy)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+
+                       pr_info("%s: OTG cable attached\n", __func__);
+               } else {
+                       value.intval = false;
+
+                       psy = power_supply_get_by_name(battery->pdata->charger_name);
+                       if (!psy)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+
+                       pr_info("%s: OTG cable detached\n", __func__);
+               }
+       }
+
+       if (battery->cable_type == POWER_SUPPLY_TYPE_BATTERY ||
+                       battery->cable_type == POWER_SUPPLY_TYPE_UNKNOWN) {
+               battery->is_recharging = false;
+               set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
+       } else {
+               if (battery->cable_type == POWER_SUPPLY_TYPE_OTG) {
+                       set_battery_status(battery, POWER_SUPPLY_STATUS_DISCHARGING);
+               } else {
+                       if (battery->status != POWER_SUPPLY_STATUS_FULL)
+                               set_battery_status(battery, POWER_SUPPLY_STATUS_CHARGING);
+               }
+       }
+
+       pr_info(
+                       "%s: Status(%s), Health(%s), Cable(%d), Recharging(%d))"
+                       "\n", __func__,
+                       bat_status_str[battery->status],
+                       health_str[battery->health],
+                       battery->cable_type,
+                       battery->is_recharging
+                 );
+
+       power_supply_changed(battery->psy_battery);
+       alarm_cancel(&battery->monitor_alarm);
+       wake_lock(&battery->monitor_wake_lock);
+       queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 0);
+       return 0;
+}
+#endif
+#if defined(CONFIG_IFCONN_NOTIFIER)
+static int s2mu00x_ifconn_handle_notification(struct notifier_block *nb,
+               unsigned long action, void *data)
+{
+       struct s2mu00x_battery_info *battery =
+                       container_of(nb, struct s2mu00x_battery_info, ifconn_nb);
+       struct ifconn_notifier_template *ifconn_info = (struct ifconn_notifier_template *)data;
+       muic_attached_dev_t attached_dev = (muic_attached_dev_t)ifconn_info->event;
+       const char *cmd;
+       int cable_type;
+       union power_supply_propval value;
+       struct power_supply *psy;
+       int ret;
+
+       dev_info(battery->dev, "%s: action (%ld) dump(0x%01x, 0x%01x, 0x%02x, 0x%04x, 0x%04x, 0x%04x, 0x%04x)\n",
+               __func__, action, ifconn_info->src, ifconn_info->dest, ifconn_info->id,
+               ifconn_info->attach, ifconn_info->rprd, ifconn_info->cable_type, ifconn_info->event);
+       ifconn_info->cable_type = (muic_attached_dev_t)ifconn_info->event;
+
+       action = ifconn_info->id;
+
+       if (attached_dev == ATTACHED_DEV_MHL_MUIC)
+               return 0;
+
+       switch (action) {
+       case IFCONN_NOTIFY_ID_DETACH:
+               cmd = "DETACH";
+               cable_type = POWER_SUPPLY_TYPE_BATTERY;
+               break;
+       case IFCONN_NOTIFY_ID_ATTACH:
+               cmd = "ATTACH";
+               cable_type = s2mu00x_bat_cable_check(battery, attached_dev);
+               break;
+       default:
+               cmd = "ERROR";
+               cable_type = -1;
+               break;
+       }
+
+       pr_info("%s: CMD[%s] attached_dev(%d) current_cable(%d) former cable_type(%d) battery_valid(%d)\n",
+                       __func__, cmd,  attached_dev, cable_type,
+                       battery->cable_type, battery->battery_valid);
+
+       if (battery->battery_valid == false)
+               pr_info("%s: Battery is disconnected\n", __func__);
+
+       battery->cable_type = cable_type;
+
+       if (attached_dev == ATTACHED_DEV_OTG_MUIC) {
+               if (!strcmp(cmd, "ATTACH")) {
+                       value.intval = true;
+
+                       psy = power_supply_get_by_name(battery->pdata->charger_name);
+                       if (!psy)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+
+                       pr_info("%s: OTG cable attached\n", __func__);
+               } else {
+                       value.intval = false;
+
+                       psy = power_supply_get_by_name(battery->pdata->charger_name);
+                       if (!psy)
+                               return -EINVAL;
+                       ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_OTG_CONTROL, &value);
+                       if (ret < 0)
+                               pr_err("%s: Fail to execute property\n", __func__);
+
+                       pr_info("%s: OTG cable detached\n", __func__);
+               }
+       }
+       set_bat_status_by_cable(battery);
+
+       pr_info("%s: Status(%s), Health(%s), Cable(%d), Recharging(%d)\n",
+                       __func__, bat_status_str[battery->status], health_str[battery->health],
+                       battery->cable_type, battery->is_recharging);
+
+       power_supply_changed(battery->psy_battery);
+       alarm_cancel(&battery->monitor_alarm);
+       wake_lock(&battery->monitor_wake_lock);
+       queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 0);
+       return 0;
+}
+#endif
+
+static void get_battery_capacity(struct s2mu00x_battery_info *battery)
+{
+
+       union power_supply_propval value;
+       struct power_supply *psy;
+       int ret;
+       unsigned int raw_soc = 0;
+
+       psy = power_supply_get_by_name(battery->pdata->fuelgauge_name);
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       raw_soc = value.intval;
+
+       if (battery->status == POWER_SUPPLY_STATUS_FULL)
+               battery->max_rawsoc = raw_soc;
+
+       battery->capacity = (raw_soc*100)/battery->max_rawsoc;
+       if (battery->capacity > 100)
+               battery->capacity = 100;
+
+       dev_info(battery->dev, "%s: SOC(%u), rawsoc(%d), max_rawsoc(%u).\n",
+               __func__, battery->capacity, raw_soc, battery->max_rawsoc);
+}
+
+static int get_battery_info(struct s2mu00x_battery_info *battery)
+{
+       union power_supply_propval value;
+       struct power_supply *psy;
+       int ret;
+
+       /*Get fuelgauge psy*/
+       psy = power_supply_get_by_name(battery->pdata->fuelgauge_name);
+       if (!psy)
+               return -EINVAL;
+
+       /* Get voltage and current value */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->voltage_now = value.intval;
+
+       value.intval = S2MU00X_BATTERY_VOLTAGE_AVERAGE;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_AVG, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->voltage_avg = value.intval;
+
+       value.intval = S2MU00X_BATTERY_CURRENT_MA;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->current_now = value.intval;
+
+       value.intval = S2MU00X_BATTERY_CURRENT_MA;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_AVG, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->current_avg = value.intval;
+
+       /* Get temperature info */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_TEMP, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->temperature = value.intval;
+
+       get_battery_capacity(battery);
+
+       /*Get charger psy*/
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return -EINVAL;
+
+       /* Get input current limit */
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+       battery->current_max = value.intval;
+
+       /* Get charger status*/
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       if (battery->status != value.intval)
+               pr_err("%s: battery status = %d, charger status = %d\n",
+                               __func__, battery->status, value.intval);
+
+       dev_info(battery->dev,
+                       "%s:Vnow(%dmV),Inow(%dmA),Imax(%dmA),SOC(%d%%),Tbat(%d)"
+                       "\n", __func__,
+                       battery->voltage_now, battery->current_now,
+                       battery->current_max, battery->capacity,
+                       battery->temperature
+                       );
+       dev_dbg(battery->dev,
+                       "%s,Vavg(%dmV),Vocv(%dmV),Iavg(%dmA)\n",
+                       battery->battery_valid ? "Connected" : "Disconnected",
+                       battery->voltage_avg, battery->voltage_ocv, battery->current_avg);
+
+       return 0;
+}
+
+static int get_battery_health(struct s2mu00x_battery_info *battery)
+{
+       union power_supply_propval value;
+       int health = POWER_SUPPLY_HEALTH_UNKNOWN;
+       struct power_supply *psy;
+       int ret;
+
+       /* Get health status from charger */
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return -EINVAL;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_HEALTH, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       health = value.intval;
+
+       return health;
+}
+
+static int get_temperature_health(struct s2mu00x_battery_info *battery)
+{
+       int health = POWER_SUPPLY_HEALTH_UNKNOWN;
+
+       switch (battery->health) {
+       case POWER_SUPPLY_HEALTH_OVERHEAT:
+               if (battery->temperature < battery->temp_high_recovery)
+                       health = POWER_SUPPLY_HEALTH_GOOD;
+               else
+                       health = POWER_SUPPLY_HEALTH_OVERHEAT;
+               break;
+       case POWER_SUPPLY_HEALTH_COLD:
+               if (battery->temperature > battery->temp_low_recovery)
+                       health = POWER_SUPPLY_HEALTH_GOOD;
+               else
+                       health = POWER_SUPPLY_HEALTH_COLD;
+               break;
+       case POWER_SUPPLY_HEALTH_GOOD:
+       default:
+               if (battery->temperature > battery->temp_high)
+                       health = POWER_SUPPLY_HEALTH_OVERHEAT;
+               else if (battery->temperature < battery->temp_low)
+                       health = POWER_SUPPLY_HEALTH_COLD;
+               else
+                       health = POWER_SUPPLY_HEALTH_GOOD;
+               break;
+       }
+
+       /* For test, Temperature health is always good*/
+       health = POWER_SUPPLY_HEALTH_GOOD;
+
+       return health;
+}
+
+static void check_health(struct s2mu00x_battery_info *battery)
+{
+       int battery_health = 0;
+       int temperature_health = 0;
+
+       battery_health = get_battery_health(battery);
+       temperature_health = get_temperature_health(battery);
+
+       pr_info("%s: T = %d, bat_health(%s), T_health(%s), Charging(%s)\n",
+               __func__, battery->temperature, health_str[battery_health],
+               health_str[temperature_health], bat_status_str[battery->status]);
+
+       /* If battery & temperature both are normal,                     *
+        *      set battery->health GOOD and recover battery->status */
+       if (battery_health == POWER_SUPPLY_HEALTH_GOOD &&
+               temperature_health == POWER_SUPPLY_HEALTH_GOOD) {
+               battery->health = POWER_SUPPLY_HEALTH_GOOD;
+               if (battery->status == POWER_SUPPLY_STATUS_NOT_CHARGING)
+                       set_bat_status_by_cable(battery);
+               return;
+       }
+
+       switch (battery_health) {
+       case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
+       case POWER_SUPPLY_HEALTH_UNDERVOLTAGE:
+       case POWER_SUPPLY_HEALTH_UNKNOWN:
+               battery->health = battery_health;
+               goto abnormal_health;
+       default:
+               break;
+       }
+       switch (temperature_health) {
+       case POWER_SUPPLY_HEALTH_OVERHEAT:
+       case POWER_SUPPLY_HEALTH_COLD:
+       case POWER_SUPPLY_HEALTH_UNKNOWN:
+               battery->health = temperature_health;
+               goto abnormal_health;
+       default:
+               break;
+       }
+
+       pr_err("%s: Abnormal case of temperature & battery health.\n", __func__);
+       return;
+
+abnormal_health:
+       if (battery->status != POWER_SUPPLY_STATUS_NOT_CHARGING) {
+               battery->is_recharging = false;
+               /* Take the wakelock during 10 seconds  *
+                * when not_charging status is detected */
+               wake_lock_timeout(&battery->vbus_wake_lock, HZ * 10);
+               set_battery_status(battery, POWER_SUPPLY_STATUS_NOT_CHARGING);
+       }
+}
+
+static void check_charging_full(
+               struct s2mu00x_battery_info *battery)
+{
+       pr_info("%s Start\n", __func__);
+
+       if ((battery->status == POWER_SUPPLY_STATUS_DISCHARGING) ||
+                       (battery->status == POWER_SUPPLY_STATUS_NOT_CHARGING)) {
+               dev_dbg(battery->dev,
+                               "%s: No Need to Check Full-Charged\n", __func__);
+               return;
+       }
+
+       /* 1. Recharging check */
+       if (battery->status == POWER_SUPPLY_STATUS_FULL &&
+                       battery->voltage_now < battery->pdata->chg_recharge_vcell &&
+                       !battery->is_recharging) {
+               pr_info("%s: Recharging start\n", __func__);
+               set_battery_status(battery, POWER_SUPPLY_STATUS_CHARGING);
+               battery->is_recharging = true;
+       }
+
+       /* 2. Full charged check */
+       if ((battery->current_now > 0 && battery->current_now <
+                               battery->pdata->charging_current[
+                               battery->cable_type].full_check_current) &&
+                       (battery->voltage_avg > battery->pdata->chg_full_vcell)) {
+               battery->full_check_cnt++;
+               pr_info("%s: Full Check Cnt (%d)\n", __func__, battery->full_check_cnt);
+       } else if (battery->full_check_cnt != 0) {
+       /* Reset full check cnt when it is out of full condition */
+               battery->full_check_cnt = 0;
+               pr_info("%s: Reset Full Check Cnt\n", __func__);
+       }
+
+       /* 3. If full charged, turn off charging. */
+       if (battery->full_check_cnt >= battery->pdata->full_check_count) {
+               battery->full_check_cnt = 0;
+               battery->is_recharging = false;
+               set_battery_status(battery, POWER_SUPPLY_STATUS_FULL);
+               pr_info("%s: Full charged, charger off\n", __func__);
+       }
+}
+
+static void bat_monitor_work(struct work_struct *work)
+{
+       struct s2mu00x_battery_info *battery =
+               container_of(work, struct s2mu00x_battery_info, monitor_work.work);
+       union power_supply_propval value;
+       struct power_supply *psy;
+       int ret;
+
+       pr_info("%s: start monitoring\n", __func__);
+
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       if (!value.intval) {
+               battery->battery_valid = false;
+               pr_info("%s: There is no battery, skip monitoring.\n", __func__);
+               goto continue_monitor;
+       } else
+               battery->battery_valid = true;
+
+       get_battery_info(battery);
+
+       check_health(battery);
+
+       check_charging_full(battery);
+
+       power_supply_changed(battery->psy_battery);
+
+continue_monitor:
+       pr_err(
+                "%s: Status(%s), Health(%s), Cable(%d), Recharging(%d))"
+                "\n", __func__,
+                bat_status_str[battery->status],
+                health_str[battery->health],
+                battery->cable_type,
+                battery->is_recharging
+                );
+
+       alarm_cancel(&battery->monitor_alarm);
+       alarm_start_relative(&battery->monitor_alarm, ktime_set(battery->monitor_alarm_interval, 0));
+       wake_unlock(&battery->monitor_wake_lock);
+}
+
+#ifdef CONFIG_OF
+static int s2mu00x_battery_parse_dt(struct device *dev,
+               struct s2mu00x_battery_info *battery)
+{
+       struct device_node *np = of_find_node_by_name(NULL, "battery");
+       s2mu00x_battery_platform_data_t *pdata = battery->pdata;
+       int ret = 0, len;
+       unsigned int i;
+       const u32 *p;
+       u32 temp;
+       u32 default_input_current, default_charging_current, default_full_check_current;
+
+       if (!np) {
+               pr_info("%s np NULL(battery)\n", __func__);
+               return -1;
+       }
+       ret = of_property_read_string(np,
+                       "battery,vendor", (char const **)&pdata->vendor);
+       if (ret)
+               pr_info("%s: Vendor is empty\n", __func__);
+
+       ret = of_property_read_string(np,
+                       "battery,charger_name", (char const **)&pdata->charger_name);
+       if (ret)
+               pr_info("%s: Charger name is empty\n", __func__);
+
+       ret = of_property_read_string(np,
+                       "battery,fuelgauge_name", (char const **)&pdata->fuelgauge_name);
+       if (ret)
+               pr_info("%s: Fuelgauge name is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,technology",
+                       &pdata->technology);
+       if (ret)
+               pr_info("%s : technology is empty\n", __func__);
+
+       p = of_get_property(np, "battery,input_current_limit", &len);
+       if (!p)
+               return 1;
+
+       len = len / sizeof(u32);
+
+       if (len < POWER_SUPPLY_TYPE_END)
+               len = POWER_SUPPLY_TYPE_END;
+
+       pdata->charging_current = kzalloc(sizeof(s2mu00x_charging_current_t) * len,
+                       GFP_KERNEL);
+
+       ret = of_property_read_u32(np, "battery,default_input_current",
+                       &default_input_current);
+       if (ret)
+               pr_info("%s : default_input_current is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,default_charging_current",
+                       &default_charging_current);
+       if (ret)
+               pr_info("%s : default_charging_current is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,default_full_check_current",
+                       &default_full_check_current);
+       if (ret)
+               pr_info("%s : default_full_check_current is empty\n", __func__);
+
+       for (i = 0; i < len; i++) {
+               ret = of_property_read_u32_index(np,
+                               "battery,input_current_limit", i,
+                               &pdata->charging_current[i].input_current_limit);
+               if (ret) {
+                       pr_info("%s : Input_current_limit is empty\n",
+                                       __func__);
+                       pdata->charging_current[i].input_current_limit = default_input_current;
+               }
+
+               ret = of_property_read_u32_index(np,
+                               "battery,fast_charging_current", i,
+                               &pdata->charging_current[i].fast_charging_current);
+               if (ret) {
+                       pr_info("%s : Fast charging current is empty\n",
+                                       __func__);
+                       pdata->charging_current[i].fast_charging_current = default_charging_current;
+               }
+
+               ret = of_property_read_u32_index(np,
+                               "battery,full_check_current", i,
+                               &pdata->charging_current[i].full_check_current);
+               if (ret) {
+                       pr_info("%s : Full check current is empty\n",
+                                       __func__);
+                       pdata->charging_current[i].full_check_current = default_full_check_current;
+               }
+       }
+
+       ret = of_property_read_u32(np, "battery,max_input_current",
+                       &pdata->max_input_current);
+       if (ret)
+               pr_info("%s : max_input_current is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,max_charging_current",
+                       &pdata->max_charging_current);
+       if (ret)
+               pr_info("%s : max_charging_current is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,temp_high", &temp);
+       if (ret) {
+               pr_info("%s : temp_high is empty\n", __func__);
+               pdata->temp_high = 500;
+       } else
+               pdata->temp_high = (int)temp;
+
+       ret = of_property_read_u32(np, "battery,temp_high_recovery", &temp);
+       if (ret) {
+               pr_info("%s : temp_high_recovery is empty\n", __func__);
+               pdata->temp_high_recovery = pdata->temp_high - 50;
+       } else
+               pdata->temp_high_recovery = (int)temp;
+
+       ret = of_property_read_u32(np, "battery,temp_low", &temp);
+       if (ret) {
+               pr_info("%s : temp_low is empty\n", __func__);
+               pdata->temp_low = 100;
+       } else
+               pdata->temp_low = (int)temp;
+
+       ret = of_property_read_u32(np, "battery,temp_low_recovery", &temp);
+       if (ret) {
+               pr_info("%s : temp_low_recovery is empty\n", __func__);
+               pdata->temp_low_recovery = pdata->temp_low + 50;
+       } else
+               pdata->temp_low_recovery = (int)temp;
+
+       pr_info("%s : temp_high(%d), temp_high_recovery(%d), temp_low(%d), temp_low_recovery(%d)\n",
+                       __func__,
+                       pdata->temp_high, pdata->temp_high_recovery,
+                       pdata->temp_low, pdata->temp_low_recovery);
+
+       ret = of_property_read_u32(np, "battery,full_check_count",
+                       &pdata->full_check_count);
+       if (ret)
+               pr_info("%s : full_check_count is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,chg_full_vcell",
+                       &pdata->chg_full_vcell);
+       if (ret)
+               pr_info("%s : chg_full_vcell is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,chg_recharge_vcell",
+                       &pdata->chg_recharge_vcell);
+       if (ret)
+               pr_info("%s : chg_recharge_vcell is empty\n", __func__);
+
+       ret = of_property_read_u32(np, "battery,max_rawsoc",
+                       &pdata->max_rawsoc);
+       if (ret)
+               pr_info("%s : max_rawsoc is empty\n", __func__);
+
+       pr_info("%s:DT parsing is done, vendor : %s, technology : %d\n",
+                       __func__, pdata->vendor, pdata->technology);
+       return ret;
+}
+#else
+static int s2mu00x_battery_parse_dt(struct device *dev,
+               struct s2mu00x_battery_platform_data *pdata)
+{
+       return pdev->dev.platform_data;
+}
+#endif
+
+static const struct of_device_id s2mu00x_battery_match_table[] = {
+       { .compatible = "samsung,s2mu00x-battery",},
+       {},
+};
+
+static enum alarmtimer_restart bat_monitor_alarm(
+       struct alarm *alarm, ktime_t now)
+{
+       struct s2mu00x_battery_info *battery = container_of(alarm,
+                               struct s2mu00x_battery_info, monitor_alarm);
+
+       wake_lock(&battery->monitor_wake_lock);
+       queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 0);
+
+       return ALARMTIMER_NORESTART;
+}
+
+static int s2mu00x_battery_probe(struct platform_device *pdev)
+{
+       struct s2mu00x_battery_info *battery;
+       struct power_supply_config psy_cfg = {};
+       union power_supply_propval value;
+       int ret = 0, temp = 0;
+       struct power_supply *psy;
+#ifndef CONFIG_OF
+       int i;
+#endif
+
+       pr_info("%s: S2MU00x ERD battery driver loading\n", __func__);
+
+       /* Allocate necessary device data structures */
+       battery = kzalloc(sizeof(*battery), GFP_KERNEL);
+       if (!battery)
+               return -ENOMEM;
+
+       pr_info("%s: battery is allocated\n", __func__);
+
+       battery->pdata = devm_kzalloc(&pdev->dev, sizeof(*(battery->pdata)),
+                       GFP_KERNEL);
+       if (!battery->pdata) {
+               ret = -ENOMEM;
+               goto err_bat_free;
+       }
+
+       pr_info("%s: pdata is allocated\n", __func__);
+
+       /* Get device/board dependent configuration data from DT */
+       temp = s2mu00x_battery_parse_dt(&pdev->dev, battery);
+       if (temp) {
+               pr_info("%s: s2mu00x_battery_parse_dt(&pdev->dev, battery) == %d\n", __func__, temp);
+               dev_err(&pdev->dev, "%s: Failed to get battery dt\n", __func__);
+               ret = -EINVAL;
+               goto err_parse_dt_nomem;
+       }
+
+       pr_info("%s: DT parsing is done\n", __func__);
+
+       /* Set driver data */
+       platform_set_drvdata(pdev, battery);
+       battery->dev = &pdev->dev;
+
+       mutex_init(&battery->iolock);
+
+       wake_lock_init(&battery->monitor_wake_lock, WAKE_LOCK_SUSPEND,
+                       "sec-battery-monitor");
+       wake_lock_init(&battery->vbus_wake_lock, WAKE_LOCK_SUSPEND,
+                       "sec-battery-vbus");
+
+       /* Inintialization of battery information */
+       battery->status = POWER_SUPPLY_STATUS_DISCHARGING;
+       battery->health = POWER_SUPPLY_HEALTH_GOOD;
+
+       battery->input_current = 0;
+       battery->charging_current = 0;
+       battery->topoff_current = 0;
+
+       battery->max_input_current = battery->pdata->max_input_current;
+       battery->max_charging_current = battery->pdata->max_charging_current;
+
+       battery->temp_high = battery->pdata->temp_high;
+       battery->temp_high_recovery = battery->pdata->temp_high_recovery;
+       battery->temp_low = battery->pdata->temp_low;
+       battery->temp_low_recovery = battery->pdata->temp_low_recovery;
+
+       battery->max_rawsoc = battery->pdata->max_rawsoc;
+
+       battery->is_recharging = false;
+       battery->cable_type = POWER_SUPPLY_TYPE_BATTERY;
+
+       psy = power_supply_get_by_name(battery->pdata->charger_name);
+       if (!psy)
+               return -EINVAL;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       if (!value.intval)
+               battery->battery_valid = false;
+       else
+               battery->battery_valid = true;
+
+       /* Register battery as "POWER_SUPPLY_TYPE_BATTERY" */
+       battery->psy_battery_desc.name = "battery";
+       battery->psy_battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+       battery->psy_battery_desc.get_property =  s2mu00x_battery_get_property;
+       battery->psy_battery_desc.set_property =  s2mu00x_battery_set_property;
+       battery->psy_battery_desc.properties = s2mu00x_battery_props;
+       battery->psy_battery_desc.num_properties =  ARRAY_SIZE(s2mu00x_battery_props);
+
+       battery->psy_usb_desc.name = "usb";
+       battery->psy_usb_desc.type = POWER_SUPPLY_TYPE_USB;
+       battery->psy_usb_desc.get_property = s2mu00x_usb_get_property;
+       battery->psy_usb_desc.properties = s2mu00x_power_props;
+       battery->psy_usb_desc.num_properties = ARRAY_SIZE(s2mu00x_power_props);
+
+       battery->psy_ac_desc.name = "ac";
+       battery->psy_ac_desc.type = POWER_SUPPLY_TYPE_MAINS;
+       battery->psy_ac_desc.properties = s2mu00x_power_props;
+       battery->psy_ac_desc.num_properties = ARRAY_SIZE(s2mu00x_power_props);
+       battery->psy_ac_desc.get_property = s2mu00x_ac_get_property;
+
+       /* Initialize work queue for periodic polling thread */
+       battery->monitor_wqueue =
+               create_singlethread_workqueue(dev_name(&pdev->dev));
+       if (!battery->monitor_wqueue) {
+               dev_err(battery->dev,
+                               "%s: Fail to Create Workqueue\n", __func__);
+               goto err_irr;
+       }
+
+       /* Init work & alarm for monitoring */
+       INIT_DELAYED_WORK(&battery->monitor_work, bat_monitor_work);
+       alarm_init(&battery->monitor_alarm, ALARM_BOOTTIME, bat_monitor_alarm);
+       battery->monitor_alarm_interval = DEFAULT_ALARM_INTERVAL;
+
+       /* Register power supply to framework */
+       psy_cfg.drv_data = battery;
+       psy_cfg.supplied_to = s2mu00x_supplied_to;
+       psy_cfg.num_supplicants = ARRAY_SIZE(s2mu00x_supplied_to);
+
+       battery->psy_battery = power_supply_register(&pdev->dev, &battery->psy_battery_desc, &psy_cfg);
+       if (IS_ERR(battery->psy_battery)) {
+               pr_err("%s: Failed to Register psy_battery\n", __func__);
+               ret = PTR_ERR(battery->psy_battery);
+               goto err_workqueue;
+       }
+       pr_info("%s: Registered battery as power supply\n", __func__);
+
+       battery->psy_usb = power_supply_register(&pdev->dev, &battery->psy_usb_desc, &psy_cfg);
+       if (IS_ERR(battery->psy_usb)) {
+               pr_err("%s: Failed to Register psy_usb\n", __func__);
+               ret = PTR_ERR(battery->psy_usb);
+               goto err_unreg_battery;
+       }
+       pr_info("%s: Registered USB as power supply\n", __func__);
+
+       battery->psy_ac = power_supply_register(&pdev->dev, &battery->psy_ac_desc, &psy_cfg);
+       if (IS_ERR(battery->psy_ac)) {
+               pr_err("%s: Failed to Register psy_ac\n", __func__);
+               ret = PTR_ERR(battery->psy_ac);
+               goto err_unreg_usb;
+       }
+       pr_info("%s: Registered AC as power supply\n", __func__);
+
+       /* Initialize battery level*/
+       value.intval = 0;
+
+       psy = power_supply_get_by_name(battery->pdata->fuelgauge_name);
+       if (!psy)
+               return -EINVAL;
+       ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CAPACITY, &value);
+       if (ret < 0)
+               pr_err("%s: Fail to execute property\n", __func__);
+
+       battery->capacity = value.intval;
+
+#if defined(CONFIG_IFCONN_NOTIFIER)
+       ifconn_notifier_register(&battery->ifconn_nb,
+                       s2mu00x_ifconn_handle_notification,
+                       IFCONN_NOTIFY_BATTERY,
+                       IFCONN_NOTIFY_MUIC);
+#elif defined(CONFIG_MUIC_NOTIFIER)
+       pr_info("%s: Register MUIC notifier\n", __func__);
+       muic_notifier_register(&battery->batt_nb, s2mu00x_battery_handle_notification,
+                       MUIC_NOTIFY_DEV_CHARGER);
+#endif
+
+       /* Kick off monitoring thread */
+       pr_info("%s: start battery monitoring work\n", __func__);
+       queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 5*HZ);
+
+       dev_info(battery->dev, "%s: ERD Battery driver is loaded\n", __func__);
+       return 0;
+
+err_unreg_usb:
+       power_supply_unregister(battery->psy_usb);
+err_unreg_battery:
+       power_supply_unregister(battery->psy_battery);
+err_workqueue:
+       destroy_workqueue(battery->monitor_wqueue);
+err_irr:
+       wake_lock_destroy(&battery->monitor_wake_lock);
+       wake_lock_destroy(&battery->vbus_wake_lock);
+       mutex_destroy(&battery->iolock);
+err_parse_dt_nomem:
+       kfree(battery->pdata);
+err_bat_free:
+       kfree(battery);
+
+       return ret;
+}
+
+static int s2mu00x_battery_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+#if defined CONFIG_PM
+static int s2mu00x_battery_prepare(struct device *dev)
+{
+       struct s2mu00x_battery_info *battery = dev_get_drvdata(dev);
+
+       alarm_cancel(&battery->monitor_alarm);
+       wake_unlock(&battery->monitor_wake_lock);
+       /* If charger is connected, monitoring is required*/
+       if (battery->cable_type != POWER_SUPPLY_TYPE_BATTERY) {
+               battery->monitor_alarm_interval = SLEEP_ALARM_INTERVAL;
+               pr_info("%s: Increase battery monitoring interval -> %d\n",
+                               __func__, battery->monitor_alarm_interval);
+               alarm_start_relative(&battery->monitor_alarm,
+                               ktime_set(battery->monitor_alarm_interval, 0));
+       }
+       return 0;
+}
+
+static int s2mu00x_battery_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int s2mu00x_battery_resume(struct device *dev)
+{
+       return 0;
+}
+
+static void s2mu00x_battery_complete(struct device *dev)
+{
+       struct s2mu00x_battery_info *battery = dev_get_drvdata(dev);
+
+       if (battery->monitor_alarm_interval != DEFAULT_ALARM_INTERVAL) {
+               battery->monitor_alarm_interval = DEFAULT_ALARM_INTERVAL;
+               pr_info("%s: Recover battery monitoring interval -> %d\n",
+                       __func__, battery->monitor_alarm_interval);
+       }
+       alarm_cancel(&battery->monitor_alarm);
+       wake_lock(&battery->monitor_wake_lock);
+       queue_delayed_work(battery->monitor_wqueue, &battery->monitor_work, 0);
+}
+
+#else
+#define s2mu00x_battery_prepare NULL
+#define s2mu00x_battery_suspend NULL
+#define s2mu00x_battery_resume NULL
+#define s2mu00x_battery_complete NULL
+#endif
+
+static const struct dev_pm_ops s2mu00x_battery_pm_ops = {
+       .prepare = s2mu00x_battery_prepare,
+       .suspend = s2mu00x_battery_suspend,
+       .resume = s2mu00x_battery_resume,
+       .complete = s2mu00x_battery_complete,
+};
+
+static struct platform_driver s2mu00x_battery_driver = {
+       .driver         = {
+               .name   = "s2mu00x-battery",
+               .owner  = THIS_MODULE,
+               .pm     = &s2mu00x_battery_pm_ops,
+               .of_match_table = s2mu00x_battery_match_table,
+       },
+       .probe          = s2mu00x_battery_probe,
+       .remove     = s2mu00x_battery_remove,
+};
+
+static int __init s2mu00x_battery_init(void)
+{
+       int ret = 0;
+
+       ret = platform_driver_register(&s2mu00x_battery_driver);
+       return ret;
+}
+late_initcall(s2mu00x_battery_init);
+
+static void __exit s2mu00x_battery_exit(void)
+{
+       platform_driver_unregister(&s2mu00x_battery_driver);
+}
+module_exit(s2mu00x_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Samsung Electronics");
+MODULE_DESCRIPTION("Battery driver for S2MU00x");
index fbe46233c73fe289406c78a5a7403e7b0675f32c..f933e87091f9e609cf2fd13ed496bc8bc71f17d9 100644 (file)
@@ -46,6 +46,17 @@ enum s2mu00x_battery_charger_mode {
        S2MU00X_BAT_CHG_MODE_BUCK_OFF,
 };
 
+enum s2mu00x_battery_factory_mode {
+       S2MU00X_BAT_FAC_MODE_VBAT = 0,
+       S2MU00X_BAT_FAC_MODE_VBUS,
+       S2MU00X_BAT_FAC_MODE_NORMAL,
+};
+
+enum s2mu00x_battery_charge_mode {
+       S2MU00X_POWEROFF_CHG_MODE = 0,
+       S2MU00X_FAC_MODE,
+       S2MU00X_NOR_MODE,
+};
 struct s2mu00x_charging_current {
 #ifdef CONFIG_OF
        unsigned int input_current_limit;
diff --git a/include/linux/power/s2mu00x_erd_battery.h b/include/linux/power/s2mu00x_erd_battery.h
new file mode 100644 (file)
index 0000000..277fa43
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * s2mu00x_erd_battery.h
+ *
+ * Copyright (C) 2017 Samsung Electronics, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __S2MU00X_BATTERY_H
+#define __S2MU00X_BATTERY_H
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/power_supply.h>
+
+enum s2mu00x_battery_voltage_mode {
+       S2MU00X_BATTERY_VOLTAGE_AVERAGE = 0,
+       S2MU00X_BATTERY_VOLTAGE_OCV,
+};
+
+enum s2mu00x_battery_current_mode {
+       S2MU00X_BATTERY_CURRENT_UA = 0,
+       S2MU00X_BATTERY_CURRENT_MA,
+};
+
+enum s2mu00x_battery_charger_mode {
+       S2MU00X_BAT_CHG_MODE_CHARGING = 0,
+       S2MU00X_BAT_CHG_MODE_CHARGING_OFF,
+       S2MU00X_BAT_CHG_MODE_BUCK_OFF,
+};
+
+struct s2mu00x_charging_current {
+#ifdef CONFIG_OF
+       unsigned int input_current_limit;
+       unsigned int fast_charging_current;
+       unsigned int full_check_current;
+#else
+       int input_current_limit;
+       int fast_charging_current;
+       int full_check_current;
+#endif
+};
+
+#define s2mu00x_charging_current_t struct s2mu00x_charging_current
+
+#define S2MU00X_FUELGAUGE_CAPACITY_TYPE_RESET   (-1)
+
+#endif /* __S2MU00X_BATTERY_H */