diff --git a/drivers/power/stc3117_battery.c b/drivers/power/stc3117_battery.c
index df67169d4e104f4dca900f0fa17417112831eb3d..4e4169132922358c75ff0690ed4cba53775c8a37 100755
--- a/drivers/power/stc3117_battery.c
+++ b/drivers/power/stc3117_battery.c
@@ -182,8 +182,6 @@
 #define CC_MODE 0
 
 #define SMB231_REG0_DEFAULT 			0x54
-#define SOC_CHANGE_COUNT_NORMAL			3
-#define SOC_CHANGE_COUNT_LOW_BATTERY	2
 /* gas gauge structure definition ------------------------------------*/
 
 /* Private constants -------------------------------------------------------*/
@@ -193,8 +191,8 @@
 static const int TempTable[NTEMP] = {60, 40, 25, 10, 0, -10, -20};
 static const int DefVMTempTable[NTEMP] = VMTEMPTABLE;
 static const char *charger_name = "battery";
-static bool g_debug, g_standby_mode;
-static int g_new_soc, g_last_status, g_ocv;
+static bool g_debug, g_standby_mode, g_boot_phase;
+static int g_ui_soc, g_last_status, g_ocv, g_reg_soc;
 static const char * const charge_status[] = {
 	"unknown",
 	"charging",
@@ -303,7 +301,7 @@ static union {
 	unsigned char db[RAM_SIZE];  /* last byte holds the CRC */
 	struct {
 		short int TstWord;     /* 0-1 */
-		short int HRSOC;       /* 2-3 SOC backup */
+		unsigned short int HRSOC;       /* 2-3 SOC backup */
 		short int CC_cnf;      /* 4-5 current CC_cnf */
 		short int VM_cnf;      /* 6-7 current VM_cnf */
 		char SOC;              /* 8 SOC for trace (in %) */
@@ -323,9 +321,12 @@ int Capacity_Adjust;
 /* ------------------------------------------------------------------------ */
 
 #define STC311x_BATTERY_FULL 100
+#define STC311x_DELAY_BOOTUP	 12000 //120 sec
 #define STC311x_DELAY	 3000 //30 sec
-#define STC311x_DELAY_LOW_BATT 500 //5 sec
-#define STC311x_SOC_THRESHOLD 5
+#define STC311x_DELAY_LOW_BATT 2000 //20 sec
+#define STC311x_DELAY_CRITICAL_BATT 500 //5 sec
+#define STC311x_SOC_LOW_THRESHOLD 7
+#define STC311x_SOC_CRITICAL_THRESHOLD 3
 
 /* ************************************************************************ */
 
@@ -334,6 +335,7 @@ static struct i2c_client *sav_client;
 struct stc311x_chip {
 	struct i2c_client		*client;
 	struct delayed_work		work;
+	struct delayed_work		boot_up_work;
 	struct power_supply		battery;
 	struct stc311x_platform_data	*pdata;
 	struct wake_lock wlock;
@@ -483,7 +485,7 @@ static int stc311x_get_property(struct power_supply *psy,
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
 		//val->intval = chip->batt_soc;
-		val->intval = g_new_soc;
+		val->intval = g_ui_soc;
 		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = chip->Temperature;
@@ -991,6 +993,7 @@ static int STC311x_ReadBatteryData(struct STC311x_BattDataTypeDef *BattData)
 	value = (value<<8) + data[2];
 
 	BattData->HRSOC = value;     /* result in 1/512% */
+	g_reg_soc = (int)(value/512);
 
 	/* conversion counter */
 	value = data[5];
@@ -1361,8 +1364,8 @@ static void Reset_FSM_GG(void)
 
 /* -------------------- Algo functions ------------------------------------- */
 
-
-#define OG2
+//Temporarily skip soc_correction() to fix soc jumps problem
+//#define OG2
 
 #define CURRENT_TH  (GG->Cnom/10)
 #define GAIN 10
@@ -1390,6 +1393,10 @@ void SOC_correction(struct GasGauge_DataTypeDef *GG)
 	else
 		Var3 = 400;
 
+	if (g_debug) {
+		pr_err("before SOC_correction: BattData.SOC = %d (0.1) \n", BattData.SOC);	
+		pr_err("Var3 = %d, BattData.AvgCurrent = %d \n", Var3, BattData.AvgCurrent);
+	}
 	Var1 = 256*BattData.AvgCurrent*A_Var3/Var3/CURRENT_TH;
 	Var1 = 32768 * GAIN / (256+Var1*Var1/256) / 10;
 	Var1 = (Var1+1)/2;
@@ -1400,10 +1407,15 @@ void SOC_correction(struct GasGauge_DataTypeDef *GG)
 	GG->Var1 = Var1;
 
 	Var4 = BattData.CC_adj-BattData.VM_adj;
-	if (BattData.GG_Mode == CC_MODE)
+	if (BattData.GG_Mode == CC_MODE) {
 		SOCopt = BattData.HRSOC + Var1 * Var4 / 64;
-	else
+		if (g_debug)
+			pr_err("CC mode:  Raw SOC (%d) = BattData.HRSOC (%d) + Var1 (%d) * Var4 (%d) / 64 \n", SOCopt, BattData.HRSOC, Var1, Var4);
+	} else {
 		SOCopt = BattData.HRSOC - BattData.CC_adj + Var1 * Var4 / 64;
+		if (g_debug)
+			pr_err("VM mode:  Raw SOC (%d) = BattData.HRSOC (%d) - BattData.CC_adj (%d) + Var1 (%d) * Var4 (%d) / 64 \n", SOCopt, BattData.HRSOC, BattData.CC_adj, Var1, Var4);
+	}
 
 	Var2 = BattData.Nropt;
 	if ((BattData.AvgCurrent < (-CURRENT_TH)) ||
@@ -1432,9 +1444,12 @@ void SOC_correction(struct GasGauge_DataTypeDef *GG)
 	BattData.SOC = (SOCopt*10+256)/512;
 	if ((Var4 < (-VAR4MAX)) || (Var4 >= VAR4MAX)) {
 		/*rewrite SOCopt into STC311x and clear acc registers*/
-		pr_err("SOC_correction() set new SOC: %d\n", SOCopt);
+		pr_err("SOC_correction() set new raw SOC: %d (1/512) \n", SOCopt);
 		STC311x_SetSOC(SOCopt);
 	}
+
+	if (g_debug)
+		pr_err("after SOC_correction: BattData.SOC = %d (0.1) \n", BattData.SOC);	
 #endif
 
 }
@@ -1610,9 +1625,9 @@ void stc311x_debug_info(void)
 
 	// read ram data from 32-47
 	value = STC31xx_Read(16, 32, ram);
-	pr_info("Ram data: [0-1] TstWord = 0x%x, [2-3] HRSOC = %d \n", (ram[1]<<8)+ram[0], ( (ram[3]<<8)+ram[2])/512);
-	pr_info("Ram data: [4-5] CC_cnf = %d, [6-7] VM_cnf = %d \n", (ram[5]<<8)+ram[4], (ram[7]<<8)+ram[6]);
-	pr_info("Ram data: [8] SOC = %d, [9] GG_Status = %d \n", ram[8], ram[9]);
+	pr_err("Ram data: [0-1] TstWord = 0x%x, [2-3] HRSOC = %d (1/512)\n", (ram[1]<<8)+ram[0], ( (ram[3]<<8)+ram[2]));
+	pr_err("Ram data: [4-5] CC_cnf = %d, [6-7] VM_cnf = %d \n", (ram[5]<<8)+ram[4], (ram[7]<<8)+ram[6]);
+	pr_err("Ram data: [8] SOC = %d (1/1),  [9] GG_Status = %d \n", ram[8], ram[9]);
 
 	/* MODE */
 	pr_err("REG[00] MODE = 0x%x \n", data[0]);
@@ -1673,7 +1688,7 @@ void stc311x_debug_info(void)
 	} else {
 		value = conv(value, (36*400)); //BattData->CRateFactor
 	}
-	pr_err("REG[11-12] AVG Current = %d degC \n", value);
+	pr_err("REG[11-12] AVG Current = %d mA \n", value);
 	
 	/* OCV */
 	value = data[14];
@@ -1723,7 +1738,7 @@ void stc311x_debug_info(void)
 	if (value >= 0x8000)
 		value -= 0x10000;  /* convert to signed value */
 	//BattData->CC_adj = value; /* in 1/512% */
-	pr_err("REG[[27-28] CC_ADJ = %d \n", (int)(value/512));
+	pr_err("REG[[27-28] CC_ADJ = %d \n", value);
 
 
 	value = data[30];
@@ -1732,7 +1747,7 @@ void stc311x_debug_info(void)
 	if (value >= 0x8000)
 		value -= 0x10000;  /* convert to signed value */
 	//BattData->VM_adj = value; /* in 1/512% */
-	pr_err("REG[29-30] VM_ADJ = %d \n", (int)(value/512));
+	pr_err("REG[29-30] VM_ADJ = %d \n", value);
 
 
 	// read OCVTAB registers from 48 to 79
@@ -1827,7 +1842,7 @@ static void STC311x_Rewrite_OCV(void)
  *****************************************************************************/
 int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 {
-	int res, value, ret, soc;
+	int res, value, ret;
 
 	BattData.Cnom = GG->Cnom;
 	BattData.Rsense = GG->Rsense;
@@ -1893,12 +1908,13 @@ int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 
 		//update SOC
 		mdelay(500);
-		soc = STC31xx_ReadWord(STC311x_REG_SOC);
-		pr_info("update new SOC = %d \n", soc);
-		BattData.HRSOC = soc;
+		BattData.HRSOC = STC31xx_ReadWord(STC311x_REG_SOC);
+		pr_info("update new SOC = %d \n", BattData.HRSOC);
 	}
 
 	BattData.SOC = (BattData.HRSOC*10+256)/512;  /* in 0.1% unit  */
+	if (g_debug)
+		pr_err(" 1st BattData.SOC = %d (0.1)\n", BattData.SOC);
 
 	/*Force an external temperature*/
 	if (GG->ForceExternalTemperature == 1)
@@ -1906,6 +1922,8 @@ int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 
 	/* check INIT state */
 	if (GG_Ram.reg.GG_Status == GG_INIT) {
+		if (g_debug)	
+			pr_err("GG_INIT \n");
 		/* INIT state, wait for current & temperature value available:
 		 * */
 		if (BattData.ConvCounter > VCOUNT) {
@@ -1931,13 +1949,22 @@ int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 	}
 
 	if (GG_Ram.reg.GG_Status != GG_RUNNING) {
+		if (g_debug) {
+			pr_err("not GG_RUNNING \n");
+			pr_err("before CompensateSOC: GG->SOC = %d (0.1),  BattData.SOC = %d (0.1), temp = 25 degC \n", GG->SOC, BattData.SOC);
+		}
 		GG->SOC = CompensateSOC(BattData.SOC, 250);
+		if (g_debug)
+			pr_err("after CompensateSOC: GG->SOC = %d (0.1),  BattData.SOC (0.1) = %d \n", GG->SOC, BattData.SOC);
+
 		GG->Voltage = BattData.Voltage;
 		GG->OCV = BattData.OCV;
 		GG->Current = 0;
 		GG->RemTime = -1;   /* means no estimated time available */
 		GG->Temperature = 250;
 	} else {
+		if (g_debug)
+			pr_err("GG_RUNNING \n");
 		/*Check battery presence*/
 		if ((BattData.STC_Status & M_BATFAIL) == 0)
 			BattData.BattOnline = 1;
@@ -1946,18 +1973,23 @@ int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 		/* SOC derating with temperature */
 		BattData.SOC = CompensateSOC(BattData.SOC,
 					     BattData.Temperature);
+		if (g_debug)
+			pr_err("temperature compensate SOC: BattData.SOC = %d (0.1), temp = %d degC \n", BattData.SOC, BattData.Temperature);
 
 		/*early empty compensation*/
 		value = BattData.AvgVoltage;
 		if (BattData.Voltage < value)
 			value = BattData.Voltage;
-		if (value < (APP_MIN_VOLTAGE+200) &&
+		//In the boot up phase, skip early empty compensation to avoid soc drop
+		if ((g_boot_phase == 0) && value < (APP_MIN_VOLTAGE+200) &&
 		    value > (APP_MIN_VOLTAGE-500)) {
-			if (value < APP_MIN_VOLTAGE)
+			if ((value < APP_MIN_VOLTAGE) && ((BattData.AvgCurrent > -100) && (BattData.AvgCurrent < 0)))
 				BattData.SOC = 0;
 			else
 				BattData.SOC = BattData.SOC *
 					(value - APP_MIN_VOLTAGE) / 200;
+			if (g_debug)
+				pr_err("early empty compensation:  AvgVoltage = %d, BattData.Voltage = %d, BattData.SOC = %d (0.1)\n", BattData.AvgVoltage, BattData.Voltage, BattData.SOC);
 		}
 
 		BattData.AccVoltage += (BattData.Voltage - BattData.AvgVoltage);
@@ -1998,6 +2030,11 @@ int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 			}
 		}
 
+		//Set max SOC to fix SOC > 100
+		if (BattData.HRSOC > (MAX_HRSOC+512)) {
+			BattData.SOC = MAX_SOC;
+			STC311x_SetSOC(MAX_HRSOC+512);
+		}
 
 		/* -------- APPLICATION RESULTS ------------ */
 
@@ -2047,6 +2084,8 @@ int GasGauge_Task(struct GasGauge_DataTypeDef *GG)
 	GG_Ram.reg.SOC = (GG->SOC+5)/10;    /* trace SOC in % */
 	UpdateRamCrc();
 	STC311x_WriteRamData(GG_Ram.db);
+	if (g_debug)
+		pr_err("Save to memory:  GG_Ram.reg.HRSOC = %d (1/512), GG_Ram.reg.SOC = %d (1/1) \n", GG_Ram.reg.HRSOC, GG_Ram.reg.SOC);
 
 	if (GG_Ram.reg.GG_Status == GG_RUNNING)
 		return 1;
@@ -2268,40 +2307,6 @@ int STC31xx_ForceCC(void)
 	return OK;
 }
 
-/*
-static int stc311x_read_pmic_adc_temperature(struct stc311x_chip *chip)
-{
-	struct qpnp_vadc_result result;
-	int res;
-	
-	// get pm8916 mpp3 adc
-	if(NULL == chip->vadc_dev) {
-		chip->vadc_dev = qpnp_get_vadc(chip->dev, "pm8916");
-			if (IS_ERR(chip->vadc_dev)) {
-				res = PTR_ERR(chip->vadc_dev);
-				if (res == -EPROBE_DEFER)
-					pr_err("stc311x - pm8916 vadc not found - defer rc \n");
-				else
-					pr_err("stc311x - fail to get the pm8916 vadc \n");
-				chip->vadc_dev = NULL;
-
-				return -1; 
-	          }
-	}
-	
-	res=qpnp_vadc_read(chip->vadc_dev, P_MUX3_1_1, &result);//get channel 0x12
-	if (res < 0) {
-		pr_err("stc311x - Error reading VADC chennal_12: %d\n", res);
-		return res;
-	}
-	else {
-		// update the tempetature from pmic adc
-		pr_debug("stc311x - read pmic mpp3,  temperature = %lld \n", result.physical);
-		chip->Temperature = (result.physical * 10);
-	}
-	return 0;
-}
-*/
 	
 /* -------------------------------------------------------------- */
 
@@ -2360,37 +2365,58 @@ void stc311x_check_charger_state(struct stc311x_chip *chip)
 }
 
 /*
-* 1. If charge is fulled and charger exists, keep soc = 100% 
-* 2. The moment when charger is removed, if soc = 100% and drops, keep 100%. Else, update soc
-* 3. When discharging, soc can only decrease
+* 1. If charge is fulled and charger exists, keep soc = 100%
+* 2. If SOC = 0% and in charging, show SOC = 1%
+* 3. The moment when charger is removed, if soc = 100% and drops, keep 100%. Else, update soc
+* 4. When discharging, soc can only decrease
 */
 void UI_soc_adjustment(struct stc311x_chip *chip)
 {
-	pr_err("enter: status = %d, original soc = %d,  ST soc = %d \n", chip->status,  g_new_soc, chip->batt_soc);
-	if ((g_new_soc == STC311x_BATTERY_FULL) && (chip->status != POWER_SUPPLY_STATUS_DISCHARGING))
+	if (g_debug)
+		pr_err("charging status = %d, UI soc = %d,  ST soc = %d \n", chip->status,  g_ui_soc, chip->batt_soc);
+	if ((g_ui_soc == STC311x_BATTERY_FULL) && (chip->status != POWER_SUPPLY_STATUS_DISCHARGING))
 		return;
 
+	if ((chip->batt_soc == 0) && (chip->status == POWER_SUPPLY_STATUS_CHARGING) && (chip->batt_current > 0)) {
+		g_ui_soc = 1;
+		return;
+	}
+
 	if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
 		//charger is plugged out
-		if (g_last_status != POWER_SUPPLY_STATUS_DISCHARGING) {
-			if (g_new_soc == STC311x_BATTERY_FULL)
-				return;
-			else {
-				g_new_soc = chip->batt_soc;
-				pr_info("charger plugged out, update SOC = %d \n", g_new_soc);
-				return;
-			}
-		}
-		
-		//when discharging, the new SOC can only decrease
-		if (chip->batt_soc > g_new_soc) {
-			pr_err("Discharging, new soc = %d > original soc = %d, abort \n", chip->batt_soc, g_new_soc);
+		if ((g_last_status != POWER_SUPPLY_STATUS_DISCHARGING) && (g_ui_soc == STC311x_BATTERY_FULL))
 			return;
-		} else
-			g_new_soc = chip->batt_soc;
-	} else
-		g_new_soc = chip->batt_soc;
-	
+
+		//when discharging, the new SOC can only decrease
+		if (chip->batt_soc > g_ui_soc)
+			pr_err("Discharging, new soc = %d > original soc = %d, abort \n", chip->batt_soc, g_ui_soc);	
+	}
+
+	//normal SOC calculate
+	switch (chip->status) {
+	case POWER_SUPPLY_STATUS_CHARGING:
+	case POWER_SUPPLY_STATUS_FULL:
+		if (chip->batt_soc > g_ui_soc)
+			g_ui_soc++;
+		//charger exist but current not enough
+		else if (chip->batt_current <= 0) {
+			if ((g_ui_soc - chip->batt_soc > 5 ) || (chip->batt_voltage < APP_MIN_VOLTAGE))
+				g_ui_soc--;
+		}
+		break;
+	case POWER_SUPPLY_STATUS_DISCHARGING:
+	case POWER_SUPPLY_STATUS_NOT_CHARGING:
+		if ((chip->batt_soc < g_ui_soc ) || (chip->batt_voltage < APP_MIN_VOLTAGE))
+			g_ui_soc--;
+		break;
+	case POWER_SUPPLY_STATUS_UNKNOWN:
+	default:
+		if (chip->batt_soc > g_ui_soc)
+			g_ui_soc++;
+		else
+			g_ui_soc--;
+		break;
+	}
 }
 
 static void stc311x_work(struct work_struct *work)
@@ -2482,17 +2508,25 @@ static void stc311x_work(struct work_struct *work)
 
 	stc311x_check_charger_state(chip);
 
-	if ((res > 0) && (chip->batt_soc ^ g_new_soc))
+	if ((chip->batt_soc ^ g_ui_soc) || (chip->batt_soc == 0))
 		UI_soc_adjustment(chip);
 
+	//Control SOC between  0 - 100%
+	if (g_ui_soc >= 100) 
+		g_ui_soc = 100;
+	if (g_ui_soc <= 0)
+		g_ui_soc = 0;
+
 	stc311x_updata();
 	if (g_debug)
-		pr_err("*** ST_SOC = %d, UI_SOC = %d, voltage = %d mv, OCV = %d mv, current = %d mA, Temperature = %d, charging_status = %d *** \n", chip->batt_soc, g_new_soc, chip->batt_voltage, g_ocv, chip->batt_current, chip->Temperature, chip->status);
+		pr_err("*** ST_SOC = %d, UI_SOC = %d, reg_soc = %d, voltage = %d mv, OCV = %d mv, current = %d mA, Temperature = %d, charging_status = %d *** \n", chip->batt_soc, g_ui_soc, g_reg_soc, chip->batt_voltage, g_ocv, chip->batt_current, chip->Temperature, chip->status);
 
-	if (chip->batt_soc > STC311x_SOC_THRESHOLD)
+	if (chip->batt_soc > STC311x_SOC_LOW_THRESHOLD)
 		schedule_delayed_work(&chip->work, STC311x_DELAY);
-	else
+	else if ((STC311x_SOC_CRITICAL_THRESHOLD <= chip->batt_soc) && (chip->batt_soc <= STC311x_SOC_LOW_THRESHOLD))
 		schedule_delayed_work(&chip->work, STC311x_DELAY_LOW_BATT);
+	else
+		schedule_delayed_work(&chip->work, STC311x_DELAY_CRITICAL_BATT);
 
 	if (wake_lock_active(&chip->wlock)) {
 		wake_unlock(&chip->wlock);
@@ -2501,6 +2535,10 @@ static void stc311x_work(struct work_struct *work)
 
 }
 
+static void stc311x_boot_up_work(struct work_struct *work)
+{
+	g_boot_phase = 0;
+}
 
 static enum power_supply_property stc311x_battery_props[] = {
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
@@ -2536,6 +2574,7 @@ static int stc311x_probe(struct i2c_client *client,
 
 	pr_err("\n\nstc311x probe started\n\n");
 	g_debug = 0;
+	g_boot_phase = 1;
 
 	/* The common I2C client data is placed right specific data. */
 	chip->client = client;
@@ -2624,6 +2663,7 @@ static int stc311x_probe(struct i2c_client *client,
 	reg_mode = 0;
 	reg_ctrl = 0;
 	g_standby_mode = 0;
+	g_reg_soc = 0;
 	reg_mode = STC31xx_ReadByte(STC311x_REG_MODE);
 	reg_ctrl = STC31xx_ReadByte(STC311x_REG_CTRL);
 	pr_info("mode = 0x%x, (reg_mode & GG_RUN_BIT) = %d  \n", reg_mode, (int)(reg_mode & GG_RUN_BIT));
@@ -2661,7 +2701,7 @@ static int stc311x_probe(struct i2c_client *client,
 		chip->Temperature = 250;
 		pr_err("GasGauge_Task return (-1) \n");
 	}
-	g_new_soc = chip->batt_soc;
+	g_ui_soc = chip->batt_soc;
 	chip->status = POWER_SUPPLY_STATUS_UNKNOWN;
 	g_last_status = POWER_SUPPLY_STATUS_UNKNOWN;
 	wake_lock_init(&chip->wlock, WAKE_LOCK_SUSPEND, "stc311x");
@@ -2683,8 +2723,12 @@ static int stc311x_probe(struct i2c_client *client,
 	/*a delay of about 5 seconds is correct but 30 seconds is enough compare
 	 * to the battery SOC evolution speed*/
 
+	//Init a 120 seconds timer for device boot up
+	INIT_DEFERRABLE_WORK(&chip->boot_up_work, stc311x_boot_up_work);
+	schedule_delayed_work(&chip->boot_up_work, STC311x_DELAY_BOOTUP);
+
 	if (g_debug)
-		pr_err("SOC = %d, voltage = %d, OCV = %d, temp = %d \n", chip->batt_soc, chip->batt_voltage, g_ocv, chip->Temperature);
+		pr_err("SOC = %d, reg_soc = %d, voltage = %d, OCV = %d, temp = %d \n", chip->batt_soc, g_reg_soc, chip->batt_voltage, g_ocv, chip->Temperature);
 	pr_info("stc311x FG successfully probed\n");
 	return 0;
 }