power: rk81x-battery: support otg device
[firefly-linux-kernel-4.4.55.git] / drivers / power / rt5025-battery.c
old mode 100755 (executable)
new mode 100644 (file)
index 83b458a..6b4314e
@@ -2,12 +2,13 @@
  * I2C Driver for Richtek RT5025 PMIC
  * Multi function device - multi functional baseband PMIC Battery part
  *
- * Copyright (C) 2013
+ *  Copyright (C) 2014 Richtek Technology Corp.
  * Author: Nick Hung <nick_hung@richtek.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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/kernel.h>
 #include <linux/workqueue.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
-#include <linux/android_alarm.h>
+#include <linux/alarmtimer.h>
 #include <linux/mfd/rt5025.h>
 #include <linux/power/rt5025-battery.h>
 
-#define VOLTAGE_ALERT 1
+
+#define VOLTAGE_ALERT 0
 #define TEMPERATURE_ALERT 0
 
 #define RT5025_CSV 0
 #define RT5025_B 1
-#define RT5025_TEST_WAKE_LOCK 1
+#define RT5025_TEST_WAKE_LOCK 0
 
 u8 irq_thres[LAST_TYPE];
 
-void rt5025_gauge_set_status(struct rt5025_battery_info *bi, int status)
-{
-  bi->status = status;
-  if (status == POWER_SUPPLY_STATUS_FULL)
-       bi->tp_flag = true;
-}
-EXPORT_SYMBOL(rt5025_gauge_set_status);
+static unsigned char gauge_init_regval[] = {
+       0xFF, /*REG 0x53*/
+       0x00, /*REG 0x54*/
+       0x00, /*REG 0x55*/
+       0xFF, /*REG 0x56*/
+       0x00, /*REG 0x57*/
+};
 
-void rt5025_gauge_set_online(struct rt5025_battery_info *bi, bool present)
-{
-  bi->online = present;
-}
-EXPORT_SYMBOL(rt5025_gauge_set_online);
+static u16 crctab16[256] = {
+       0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+       0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+       0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+       0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+       0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+       0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+       0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+       0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+       0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+       0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+       0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+       0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+       0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+       0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+       0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+       0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+       0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+       0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+       0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+       0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+       0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+       0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+       0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+       0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+       0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+       0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+       0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+       0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+       0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+       0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+       0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+       0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
+};
+
+static int rt5025_battery_parameter_backup(struct rt5025_battery_info *);
+static void rt5025_get_external_temp(struct rt5025_battery_info *);
+static void rt5025_get_internal_temp(struct rt5025_battery_info *);
+static void rt5025_get_vcell(struct rt5025_battery_info *);
+static void rt5025_get_current(struct rt5025_battery_info *);
+static void rt5025_temp_comp(struct rt5025_battery_info *);
 
+/* 20140415 CY */
 static int rt5025_read_reg(struct i2c_client *client,
                                u8 reg, u8 *data, u8 len)
 {
-       #if 1
        return rt5025_reg_block_read(client, reg, len, data);
-       #else
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msgs[2];
-       int ret;
-       
-       msgs[0].addr = client->addr;
-       msgs[0].flags = client->flags;
-       msgs[0].len = 1;
-       msgs[0].buf = &reg;
-
-       msgs[1].addr = client->addr;
-       msgs[1].flags = client->flags | I2C_M_RD;
-       msgs[1].len = len;
-       msgs[1].buf = data;
-       
-       ret = i2c_transfer(adap, msgs, 2);
-        
-       return (ret == 2)? len : ret;
-       #endif
 }
 
 static int rt5025_write_reg(struct i2c_client *client,
                                u8 reg, u8 *data, u8 len)
 {
-       #if 1
        return rt5025_reg_block_write(client, reg, len, data);
-       #else
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msg;
-       int ret;
-       char *tx_buf = (char *)kmalloc(len + 1, GFP_KERNEL);
-       
-       if(!tx_buf)
-               return -ENOMEM;
-       tx_buf[0] = reg;
-       memcpy(tx_buf+1, data, len);
-       
-       msg.addr = client->addr;
-       msg.flags = client->flags;
-       msg.len = len + 1;
-       msg.buf = (char *)tx_buf;
-
-       ret = i2c_transfer(adap, &msg, 1);
-       kfree(tx_buf);
-       return (ret == 1) ? len : ret;
-       #endif
-}
-
-static void rt5025_gauge_alarm(struct alarm *alarm)
-{
-       struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(alarm, struct rt5025_battery_info, wakeup_alarm);
-
-       wake_lock(&bi->monitor_wake_lock);
-       schedule_delayed_work(&bi->monitor_work, 0);
 }
 
-static void rt5025_program_alarm(struct rt5025_battery_info *bi)
+static void rt5025_set_battery_led(struct rt5025_battery_info *bi, int status)
 {
-       ktime_t low_interval = ktime_set(bi->update_time, 0);
-       ktime_t slack = ktime_set(20, 0);
-       ktime_t next;
-
-       next = ktime_add(bi->last_poll, low_interval);
-       alarm_start_range(&bi->wakeup_alarm, next, ktime_add(next, slack));
+       switch (status) {
+       case POWER_SUPPLY_STATUS_CHARGING:
+               break;
+       case POWER_SUPPLY_STATUS_DISCHARGING:
+               break;
+       case POWER_SUPPLY_STATUS_FULL:
+               break;
+       default:
+               break;
+       }
 }
 
-#if 0
-static void rt5025_run_time(struct rt5025_battery_info *bi)
+static int rt5025_set_property(struct power_supply *psy,
+                              enum power_supply_property psp,
+                              const union power_supply_propval *val)
 {
-       if(bi->curr <= 0)
-       {
-               bi->time_to_empty = bi->rm / (bi->curr*(-1));
+       struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent);
+       int rc = 0;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               if (val->intval == POWER_SUPPLY_STATUS_FULL) {
+                               bi->tp_flag = true;
+                               pr_info("%s: Battery is full \n", __func__);
+               } else {
+                               mutex_lock(&bi->status_change_lock);
+                               bi->status = val->intval;
+                               if (bi->status == POWER_SUPPLY_STATUS_DISCHARGING)
+                                       bi->tp_flag = false;
+                               rt5025_set_battery_led(bi, bi->status);
+                               mutex_unlock(&bi->status_change_lock);
+                               }
+               wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ);
+               schedule_delayed_work(&bi->monitor_work, msecs_to_jiffies(100));
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               bi->batt_present = val->intval;
+               break;
+       default:
+               rc = -EINVAL;
+               break;
        }
-       else
-       {
-               bi->time_to_full = (bi->fcc * 3600 - bi->rm) / bi->curr;
-       }
-       RTINFO("RTTF = %d\n",bi->time_to_full);
-       RTINFO("RTTE = %d\n",bi->time_to_empty);
+       return rc;
 }
-#endif
 
 static int rt5025_get_property(struct power_supply *psy,
                            enum power_supply_property psp,
                            union power_supply_propval *val)
 {
-  struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent);
-
-  switch (psp) {
-    case POWER_SUPPLY_PROP_STATUS:
-      val->intval = bi->status;
-      //val->intval = POWER_SUPPLY_STATUS_CHARGING;
-      break;
-    case POWER_SUPPLY_PROP_HEALTH:
-      val->intval = bi->health;
-      break;
-    case POWER_SUPPLY_PROP_PRESENT:
-      val->intval = bi->present;
-      break;
-    case POWER_SUPPLY_PROP_TEMP:
-      val->intval = bi->ext_temp;
-      break;
-    case POWER_SUPPLY_PROP_ONLINE:
-      val->intval = bi->online;
-      break;
-    case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-      val->intval = bi->vcell * 1000; //uV
-      break;
-    case POWER_SUPPLY_PROP_CURRENT_NOW:
-      val->intval = bi->curr * 1000; //uA
-      break;
-    case POWER_SUPPLY_PROP_CAPACITY:
-      val->intval = bi->soc;
-                       //val->intval = 50;
-      if (val->intval > 100)
-                               val->intval = 100;
-      break;
-    case POWER_SUPPLY_PROP_TECHNOLOGY:
-      val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
-      break;
-    #if 0
-    case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
-                       val->intval = bi->time_to_empty;
-    break;
-    case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
-                       val->intval = bi->time_to_full;
-    #endif
-    break;
-    default:
-      return -EINVAL;
-  }
-  return 0;
+       struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               val->intval = bi->status;
+               /*val->intval = POWER_SUPPLY_STATUS_CHARGING;*/
+               break;
+       case POWER_SUPPLY_PROP_HEALTH:
+               val->intval = bi->health;
+               /*If there's no battery, always show battery health to good.*/
+               if (!bi->present || !bi->batt_present)
+                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = bi->present;
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               if (val->intval == 23) {
+                       rt5025_get_external_temp(bi);
+                       val->intval = bi->ext_temp;
+               } else {
+                       /*If there's no battery, always show battery temperature to 25'c.*/
+                       if (!bi->present || !bi->batt_present)
+                               val->intval = 250;
+                       else
+                               val->intval = bi->ext_temp;
+               }
+               break;
+       case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+               rt5025_get_internal_temp(bi);
+               val->intval = bi->int_temp;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = bi->online;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               rt5025_get_vcell(bi);
+               val->intval = bi->vcell * 1000; /*uv*/
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               rt5025_get_current(bi);
+               val->intval = bi->curr * 1000; /*uA*/
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY:
+               val->intval = bi->soc;
+               if (val->intval > 100)
+                       val->intval = 100;
+               /*If there's no battery, always show capacity to 50*/
+               if (!bi->present || !bi->batt_present)
+                       val->intval = 50;
+               break;
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
 }
 
 static void rt5025_get_vcell(struct rt5025_battery_info *bi)
 {
-  u8 data[2];
-       
-  if (rt5025_read_reg(bi->client, RT5025_REG_VCELL_MSB, data, 2) < 0){
-    printk(KERN_ERR "%s: Failed to read Voltage\n", __func__);
-  }
+       u8 data[2];
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_VBATSH, data, 2) < 0)
+               pr_err("%s: Failed to read Voltage\n", __func__);
 
-  if (bi->avg_flag)
-    bi->vcell = ((data[0] << 8) + data[1]) * 61 / 100;
-  else 
-         bi->vcell = (bi->vcell + ((data[0] << 8) + data[1]) * 61 / 100) / 2;
+       if (bi->avg_flag)
+               bi->vcell = ((data[0] << 8) + data[1]) * 61 / 100;
+       else
+               bi->vcell =
+                   (bi->vcell + ((data[0] << 8) + data[1]) * 61 / 100) / 2;
 #if RT5025_B
-       bi->curr_offset = (15444 * bi->vcell - 27444000) / 10000;
-#else 
-  if (37 * bi->vcell > 92000)
+
+       /*b. Remove current offset compensation; 2013/12/17*/
+       bi->curr_offset = 0;
+       /*bi->curr_offset = (15444 * bi->vcell - 27444000) / 10000;*/
+
+#else
+       if (37 * bi->vcell > 92000)
                bi->curr_offset = (37 * bi->vcell - 92000) / 1000;
        else
                bi->curr_offset = 0;
 #endif
-               
+
 #if RT5025_CSV
- // if (!bi->avg_flag)
-  //  pr_info("%d,%d,", bi->vcell, bi->curr_offset);
-#else  
-  if (bi->avg_flag)
+       /* if (!bi->avg_flag)*/
+       /*  pr_info("%d,%d,", bi->vcell, bi->curr_offset);*/
+#else
+       if (bi->avg_flag)
                RTINFO("vcell_pre: %d, offset: %d\n", bi->vcell, bi->curr_offset);
-  else
+       else
                RTINFO("vcell_avg: %d, offset: %d\n", bi->vcell, bi->curr_offset);
 #endif
 }
 
 static void rt5025_get_current(struct rt5025_battery_info *bi)
 {
-  u8 data[2];
-  s32 temp;
-  int sign = 0;
+       u8 data[2];
+       s32 temp;
+       int sign = 0;
+       u8 curr_region;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_CURRH, data, 2) < 0)
+               pr_err("%s: Failed to read CURRENT\n", __func__);
 
-  if (rt5025_read_reg(bi->client, RT5025_REG_CURRENT_MSB, data, 2) < 0) {
-    printk(KERN_ERR "%s: Failed to read CURRENT\n", __func__);
-  }
 #if RT5025_B
-  temp = (data[0]<<8) | data[1];
-  bi->curr_raw = ((temp & 0x7FFF) * 3125) / 10000;
-    
-  if (data[0] & (1 << 7)) {
-    sign = 1;
-    temp = (((temp & 0x7FFF) * 3125) / 10 + bi->curr_offset) / 1000;
-  }else{
+       temp = (data[0] << 8) | data[1];
+       bi->curr_raw = ((temp & 0x7FFF) * 3125) / 10000;
+
+       if (data[0] & (1 << 7)) {
+               sign = 1;
+               temp = (((temp & 0x7FFF) * 3125) / 10 + bi->curr_offset) / 1000;
+       } else {
                if ((temp * 3125) / 10 > bi->curr_offset)
                        temp = ((temp * 3125) / 10 - bi->curr_offset) / 1000;
        }
-       
-  if (temp < DEADBAND)
+       if (temp < DEADBAND)
                temp = 0;
-  
-  if (sign){
-    temp *= -1;
-    bi->curr_raw *= -1;
+       if (sign) {
+               temp *= -1;
+               bi->curr_raw *= -1;
        }
 #else
-  temp = (data[0]<<8) | data[1];
-  if (data[0] & (1 << 7)) {
-    sign = 1;
-    temp = temp & 0x7FFF;
-    if(temp > bi->curr_offset)
+       temp = (data[0] << 8) | data[1];
+       if (data[0] & (1 << 7)) {
+               sign = 1;
+               temp = temp & 0x7FFF;
+               if (temp > bi->curr_offset)
                        temp = temp - bi->curr_offset;
-  }else {
-    temp = temp + bi->curr_offset;
+       } else {
+                       temp = temp + bi->curr_offset;
        }
-
-  temp = (temp * 37375) / 100000; //Unit: 0.3125mA
-  if (temp < DEADBAND)
+       temp = (temp * 37375) / 100000; /*Unit: 0.3125mA*/
+       if (temp < DEADBAND)
                temp = 0;
-  
-  if (sign)
-    temp *= -1;
+       if (sign)
+               temp *= -1;
 #endif
 
-  if (bi->avg_flag) 
-    bi->curr = temp;
-  else
-         bi->curr = (bi->curr + temp) / 2;
+       if (bi->avg_flag)
+               bi->curr = temp;
+       else
+               bi->curr = (bi->curr + temp) / 2;
 
-  if(bi->curr > 0)
-    bi->internal_status = POWER_SUPPLY_STATUS_CHARGING;
-  else
-    bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
-  RTINFO("current=%d, internal_status=%d\n", bi->curr, bi->internal_status);
+       if (bi->curr > -500)
+               curr_region = 0;
+       else if (bi->curr <= -500 && bi->curr > -1500)
+               curr_region = 1;
+       else
+               curr_region = 2;
+
+       if (curr_region != bi->edv_region) {
+               switch (curr_region) {
+               case 0:
+                       bi->empty_edv = rt5025_battery_param2[4].x;
+                       break;
+               case 1:
+                       bi->empty_edv = rt5025_battery_param2[4].x - 75;
+                       break;
+               case 2:
+                       bi->empty_edv = rt5025_battery_param2[4].x - 100;
+                       break;
+               }
+       bi->edv_region = curr_region;
+       }
+       RTINFO("empty_voltage=%d\n", bi->empty_edv);
+
+       if (bi->curr > 0) {
+               bi->internal_status = POWER_SUPPLY_STATUS_CHARGING;
+               bi->last_tp_flag = false;
+               /*b. add fcc update flag; 2013/12/18*/
+               bi->fcc_update_flag = true;
+       } else {
+               bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
+       }
+       RTINFO("current=%d, internal_status=%d\n", bi->curr, bi->internal_status);
 
 #if RT5025_CSV
- // if (!bi->avg_flag)
-  //  pr_info("%d,",bi->curr);
+       /*if (!bi->avg_flag)*/
+       /*pr_info("%d,",bi->curr);*/
 #else
-  if (bi->avg_flag)
+       if (bi->avg_flag)
                RTINFO("current_pre: %d\n", bi->curr);
-  else  
+       else
                RTINFO("current_avg: %d\n", bi->curr);
 #endif
 }
 
+static void rt5025_get_internal_temp(struct rt5025_battery_info *bi)
+{
+       u8 data[2];
+       s32 temp;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_INTEMPH, data, 2) < 0)
+               pr_err("%s: Failed to read internal TEMPERATURE\n", __func__);
+
+       temp = ((data[0] & 0x1F) << 8) + data[1];
+       temp *= 15625;
+       temp /= 100000;
+
+       temp = (data[0] & 0x20) ? -temp : temp;
+       bi->int_temp = temp;
+       RTINFO("internal temperature: %d\n", bi->int_temp);
+}
+
 static void rt5025_get_external_temp(struct rt5025_battery_info *bi)
 {
-  u8 data[2];
-  s32 temp;
+       u8 data[2];
+       s32 temp;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_AINH, data, 2) < 0)
+               pr_err("%s: Failed to read TEMPERATURE\n", __func__);
+       bi->ain_volt = (data[0] * 256 + data[1]) * 61 / 100;
+       if (bi->ain_volt < 1150)
+               bi->present = 1;
+       else
+               bi->present = 0;
+
+       temp =  (bi->ain_volt * (-91738) + 81521000) / 100000;
+       bi->ext_temp = (int)temp;
+       /*test bi->ext_temp = 250;*/
 
-  if (rt5025_read_reg(bi->client, RT5025_REG_EXT_TEMPERATUE_MSB, data, 2) < 0) {
-    printk(KERN_ERR "%s: Failed to read TEMPERATURE\n", __func__);
-  }
-  bi->ain_volt = (data[0] * 256 + data[1]) * 61 / 100;
-  if(bi->ain_volt < 1150) 
-  {
-       bi->present = 1;
-  }
-  else
-  {
-       bi->present = 0;  
-  }
-  
-  temp =  (bi->ain_volt * (-91738) + 81521000) / 100000;
-  bi->ext_temp = (int)temp;
-       //test
-       //bi->ext_temp = 250;
-       
        if (bi->ext_temp >= HIGH_TEMP_THRES) {
                if (bi->health != POWER_SUPPLY_HEALTH_OVERHEAT)
                        bi->temp_high_cnt++;
-       } else if (bi->ext_temp <= HIGH_TEMP_RECOVER && bi->ext_temp >= LOW_TEMP_RECOVER) {
-               if (bi->health == POWER_SUPPLY_HEALTH_OVERHEAT ||
-                   bi->health == POWER_SUPPLY_HEALTH_COLD)
+       } else if (bi->ext_temp <= HIGH_TEMP_RECOVER
+                  && bi->ext_temp >= LOW_TEMP_RECOVER) {
+               if (bi->health == POWER_SUPPLY_HEALTH_OVERHEAT
+                   || bi->health == POWER_SUPPLY_HEALTH_COLD)
                        bi->temp_recover_cnt++;
        } else if (bi->ext_temp <= LOW_TEMP_THRES) {
                if (bi->health != POWER_SUPPLY_HEALTH_COLD)
                        bi->temp_low_cnt++;
-       }else {
-               bi->temp_high_cnt = 0;
-               bi->temp_low_cnt = 0;
-               bi->temp_recover_cnt = 0;
+       } else {
+                       bi->temp_high_cnt = 0;
+                       bi->temp_low_cnt = 0;
+                       bi->temp_recover_cnt = 0;
        }
-       
+
        if (bi->temp_high_cnt >= TEMP_ABNORMAL_COUNT) {
-        bi->health = POWER_SUPPLY_HEALTH_OVERHEAT;
-        bi->temp_high_cnt = 0;
+               bi->health = POWER_SUPPLY_HEALTH_OVERHEAT;
+               bi->temp_high_cnt = 0;
        } else if (bi->temp_low_cnt >= TEMP_ABNORMAL_COUNT) {
-        bi->health = POWER_SUPPLY_HEALTH_COLD;
-        bi->temp_low_cnt = 0;
+               bi->health = POWER_SUPPLY_HEALTH_COLD;
+               bi->temp_low_cnt = 0;
        } else if (bi->temp_recover_cnt >= TEMP_ABNORMAL_COUNT) {
-        bi->health = POWER_SUPPLY_HEALTH_GOOD;
-        bi->temp_recover_cnt = 0;
+               bi->health = POWER_SUPPLY_HEALTH_GOOD;
+               bi->temp_recover_cnt = 0;
        }
-       //RTINFO("external temperature: %d\n", bi->ext_temp);
+       RTINFO("external temperature: %d\n", bi->ext_temp);
 }
 
 static void rt5025_clear_cc(struct rt5025_battery_info *bi, operation_mode mode)
-{  
-  u8 data[2];
-       
-  if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_MSB, data, 2) < 0){
-    pr_err("%s: failed to read channel\n", __func__);
-  }
+{
+       u8 data[2];
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_CHANNELH, data, 2) < 0)
+       pr_err("%s: failed to read channel\n", __func__);
 
-  if (mode == CHG)
+       if (mode == CHG)
                data[0] = data[0] | CHANNEL_H_BIT_CLRQCHG;
        else
                data[0] = data[0] | CHANNEL_H_BIT_CLRQDCHG;
-               
-  if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_MSB, data, 2) < 0){
-    pr_err("%s: failed to write channel\n", __func__);
-  }
+
+       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNELH, data, 2) < 0)
+               pr_err("%s: failed to write channel\n", __func__);
 }
 
 static void rt5025_get_chg_cc(struct rt5025_battery_info *bi)
 {
-  u8 data[4];
-  u32 qh_old,ql_old,qh_new,ql_new;
-  u32 cc_masec,offset;
-  
-  if (rt5025_read_reg(bi->client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
-    pr_err("%s: Failed to read QCHG\n", __func__);
-  }
-  qh_old = (data[0]<<8) + data[1];
-  ql_old = (data[2]<<8) + data[3];
-  
-  if (rt5025_read_reg(bi->client, RT5025_REG_QCHGH_MSB, data, 4) < 0){
-    pr_err("%s: Failed to read QCHG\n", __func__);
-  }
-  qh_new = (data[0]<<8) + data[1];
-  ql_new = (data[2]<<8) + data[3];
+       u8 data[4];
+       u32 qh_old, ql_old, qh_new, ql_new;
+       u32 cc_masec, offset = 0;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QCHGHH, data, 4) < 0)
+               pr_err("%s: Failed to read QCHG\n", __func__);
+
+       qh_old = (data[0]<<8) + data[1];
+       ql_old = (data[2]<<8) + data[3];
+       RTINFO("qh_old=%d, ql_old=%d\n", qh_old, ql_old);
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QCHGHH, data, 4) < 0)
+               pr_err("%s: Failed to read QCHG\n", __func__);
+
+       qh_new = (data[0]<<8) + data[1];
+       ql_new = (data[2]<<8) + data[3];
+       RTINFO("qh_new=%d, ql_new=%d\n", qh_new, ql_new);
 
 #if RT5025_B
-  if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-    }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+       if (qh_new > qh_old) {
+       /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+       cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+       } else if (qh_new == qh_old) {
+               if (ql_new >= ql_old) {
+                       /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+                       cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+               } else {
+                       /*cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;*/
+                       cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
                }
-  }    
-  
-       offset = bi->curr_offset * bi->time_interval;
-                         
-  if (cc_masec > offset){
-               cc_masec = (cc_masec - offset) / 1000;
        }
-#else          
-  if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
-    }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000;
-               }
-  }    
-  
+
+       if (!bi->init_once)
+               offset = bi->curr_offset * bi->time_interval;
+       if (cc_masec > offset)
+               cc_masec = cc_masec - (offset / 1000);
+#else
+       if (qh_new > qh_old) {
+       cc_masec = (((qh_new << 16) + ql_new) * 5996) / 1000;
+       } else if (qh_new == qh_old) {
+               if (ql_new >= ql_old)
+                       cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+               else
+                       cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000;
+       }
+
        offset = (bi->curr_offset * bi->time_interval * 37375) / 100000;
-                         
-  if (cc_masec != 0){
+
+       if (cc_masec != 0)
                cc_masec = cc_masec - offset;
-       }
 #endif
        if (cc_masec < (DEADBAND * bi->time_interval))
                cc_masec = 0;
 
 #if RT5025_CSV
-  //pr_info("%d,\n", cc_masec);
 #else
        RTINFO("chg_cc_mAsec: %d\n", cc_masec);
 #endif
 
+       /*if (!bi->init_once)*/
        bi->chg_cc = cc_masec;
-       //bi->chg_cc = (cc_masec + bi->chg_cc_unuse) / 3600;
-  //bi->chg_cc_unuse = (cc_masec + bi->chg_cc_unuse) % 3600;
-  rt5025_clear_cc(bi, CHG);
+       /*bi->chg_cc = (cc_masec + bi->chg_cc_unuse) / 3600;*/
+       /*bi->chg_cc_unuse = (cc_masec + bi->chg_cc_unuse) % 3600;*/
+       rt5025_clear_cc(bi, CHG);
 }
 
 static void rt5025_get_dchg_cc(struct rt5025_battery_info *bi)
 {
-  u8 data[4];
-  u32 qh_old,ql_old,qh_new,ql_new;
-  u32 cc_masec,offset;
-  
-  if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
-    printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
-  }
-  qh_old = (data[0]<<8) + data[1];
-  ql_old = (data[2]<<8) + data[3];
-  
-  if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGH_MSB, data, 4) < 0){
-    printk(KERN_ERR "%s: Failed to read QDCHG\n", __func__);
-  }
-  qh_new = (data[0]<<8) + data[1];
-  ql_new = (data[2]<<8) + data[3];
-  
+       u8 data[4];
+       u32 qh_old, ql_old, qh_new, ql_new;
+       u32 cc_masec, offset = 0;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGHH, data, 4) < 0)
+               pr_err("%s: Failed to read QDCHG\n",
+                       __func__);
+
+       qh_old = (data[0] << 8) + data[1];
+       ql_old = (data[2] << 8) + data[3];
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGHH, data, 4) < 0)
+               pr_err("%s: Failed to read QDCHG\n",
+                       __func__);
+
+       qh_new = (data[0] << 8) + data[1];
+       ql_new = (data[2] << 8) + data[3];
+
 #if RT5025_B
-  if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-    }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
+       if (qh_new > qh_old) {
+               /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+               cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+       } else if (qh_new == qh_old) {
+               if (ql_new >= ql_old) {
+                       /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+                       cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+               } else {
+                       /*cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;*/
+                       cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
                }
-  }    
-  
-       offset = bi->curr_offset * bi->time_interval;
-                         
-  if (cc_masec != 0){
-               cc_masec = (cc_masec + offset) / 1000;
        }
-#else  
-  if (qh_new > qh_old){
-     cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-      cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
-    }else {  
-      cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000;
-               }
-  }
-  
+       if (!bi->init_once)
+               offset = bi->curr_offset * bi->time_interval;
+       if (cc_masec != 0)
+               cc_masec = cc_masec + (offset / 1000);
+#else
+       if (qh_new > qh_old) {
+               cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+       } else if (qh_new == qh_old) {
+               if (ql_new >= ql_old)
+                       cc_masec = (((qh_new<<16) + ql_new) * 5996) / 1000;
+               else
+                       cc_masec = (((qh_old<<16) + ql_old) * 5996) / 1000;
+       }
+
        offset = (bi->curr_offset * bi->time_interval * 37375) / 100000;
-                         
-  if (cc_masec > offset){
+
+       if (cc_masec > offset)
                cc_masec = cc_masec - offset;
-       }
 #endif
        if (cc_masec < (DEADBAND * bi->time_interval))
                cc_masec = 0;
-               
+
 #if RT5025_CSV
-  //pr_info("%d,", cc_masec);
 #else
        RTINFO("dchg_cc_mAsec: %d\n", cc_masec);
 #endif
        bi->dchg_cc = cc_masec;
-       //bi->dchg_cc = (cc_masec + bi->dchg_cc_unuse) / 3600;
-  //bi->dchg_cc_unuse = (cc_masec + bi->dchg_cc_unuse) % 3600;
+       /*b. add fcc update flag; 2013/12/18*/
+       if ((bi->last_tp_flag) && (bi->fcc_update_flag))
+               bi->cal_fcc += cc_masec;
+       else
+               bi->cal_fcc = 0;
+
+       RTINFO("bi->cal_fcc=%d, bi->last_tp_flag=%d\n",
+               bi->cal_fcc, bi->last_tp_flag);
+       /*bi->dchg_cc = (cc_masec + bi->dchg_cc_unuse) / 3600;*/
+       /*bi->dchg_cc_unuse = (cc_masec + bi->dchg_cc_unuse) % 3600;*/
        rt5025_clear_cc(bi, DCHG);
-       
+
 }
 
 static void rt5025_cycle_count(struct rt5025_battery_info *bi)
 {
        bi->acc_dchg_cap +=  bi->dchg_cc;
-       if(bi->acc_dchg_cap >= (bi->dc * 3600)){
+       if (bi->acc_dchg_cap >= (bi->dc * 3600)) {
                bi->cycle_cnt++;
                bi->acc_dchg_cap -= (bi->dc * 3600);
        }
@@ -504,114 +575,113 @@ static void rt5025_cycle_count(struct rt5025_battery_info *bi)
 
 static void rt5025_get_irq_flag(struct rt5025_battery_info *bi, u8 flag)
 {
-#if 0
-  u8 data[1];
-
-  if (rt5025_read_reg(bi->client, RT5025_REG_IRQ_FLAG, data, 1) < 0){
-    pr_err("%s: Failed to read irq_flag\n", __func__);
-  }
-#endif
-               
-  bi->irq_flag = flag;
-       //RTINFO("IRQ_FLG 0x%x\n", bi->irq_flag);
+       bi->irq_flag = flag;
+       /*RTINFO("IRQ_FLG 0x%x\n", bi->irq_flag);*/
 }
 
 static void rt5025_get_timer(struct rt5025_battery_info *bi)
 {
-  u8 data[2];
-  //frankie
-       //u16 gauge_timer;
-       
-  if (rt5025_read_reg(bi->client, RT5025_REG_TIMER, data, 2) < 0){
-       pr_err("%s: Failed to read Timer\n", __func__);
-  }
-               
-  bi->gauge_timer = (data[0] << 8) + data[1];
-  if (!bi->device_suspend){
-    if (bi->gauge_timer > bi->pre_gauge_timer)
-                 bi->time_interval = bi->gauge_timer - bi->pre_gauge_timer;
-         else  
-                 bi->time_interval = 65536 - bi->pre_gauge_timer + bi->gauge_timer;
-  }
-    
-  bi->pre_gauge_timer = bi->gauge_timer;
+       u8 data[2];
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_TIMERH, data, 2) < 0)
+               pr_err("%s: Failed to read Timer\n", __func__);
+
+       bi->gauge_timer = (data[0] << 8) + data[1];
+       if (!bi->device_suspend) {
+               if (bi->gauge_timer > bi->pre_gauge_timer)
+                       bi->time_interval = bi->gauge_timer - bi->pre_gauge_timer;
+               else
+                       bi->time_interval = 65536 - bi->pre_gauge_timer + bi->gauge_timer;
+       }
+
+       bi->pre_gauge_timer = bi->gauge_timer;
 #if RT5025_CSV
- // pr_info("%d,%d,", bi->gauge_timer,bi->time_interval);
+       /*pr_info("%d,%d,", bi->gauge_timer,bi->time_interval);*/
 #else
-       RTINFO("timer %d , interval %d\n", bi->gauge_timer,bi->time_interval);
+       RTINFO("timer %d , interval %d\n", bi->gauge_timer, bi->time_interval);
 #endif
 }
 
-static void rt5025_alert_setting(struct rt5025_battery_info *bi, alert_type type, bool enable)
+static void rt5025_alert_setting(struct rt5025_battery_info *bi,
+       alert_type type, bool enable)
 {
        u8 data[1];
-       
-       if (rt5025_read_reg(bi->client, RT5025_REG_IRQ_CTL, data, 1) < 0){
-               printk(KERN_ERR "%s: Failed to read CONFIG\n", __func__);
-       }
 
-       if(enable){
-               switch(type){
-                       case MAXTEMP:
-                               data[0] |= IRQ_CTL_BIT_TMX; //Enable max temperature alert
-                               bi->max_temp_irq = true;
-                               //RTDBG("Enable min temperature alert");
-                               break;
-                       case MINTEMP:
-                               data[0] |= IRQ_CTL_BIT_TMN; //Enable min temperature alert
-                               bi->min_temp_irq = true;  
-                               //RTDBG("Enable max temperature alert");
-                               break;
-                       case MAXVOLT:
-                               data[0] |= IRQ_CTL_BIT_VMX; //Enable max voltage alert
-                               bi->max_volt_irq = true;
-                               //RTDBG("Enable max voltage alert");
-                               break;
-                       case MINVOLT1:
-                               data[0] |= IRQ_CTL_BIT_VMN1; //Enable min1 voltage alert        
-                               bi->min_volt1_irq = true;
-                               //RTDBG("Enable min1 voltage alert");
-                               break;
-                       case MINVOLT2:
-                               data[0] |= IRQ_CTL_BIT_VMN2; //Enable min2 voltage alert
-                               bi->min_volt2_irq = true;
-                               //RTDBG("Enable min2 voltage alert");
-                               break;
-                       default:
-                               break;
+       if (rt5025_read_reg(bi->client, RT5025_REG_IRQCTL, data, 1) < 0)
+               pr_err("%s: Failed to read CONFIG\n", __func__);
+
+       if (enable) {
+               switch (type) {
+               case MAXTEMP:
+                       data[0] |= IRQ_CTL_BIT_TMX;
+                       /*Enable max temperature alert*/
+                       bi->max_temp_irq = true;
+                       /*RTDBG("Enable min temperature alert");*/
+                       break;
+               case MINTEMP:
+                       data[0] |= IRQ_CTL_BIT_TMN;
+                       /*Enable min temperature alert*/
+                       bi->min_temp_irq = true;
+                       /*RTDBG("Enable max temperature alert");*/
+                       break;
+               case MAXVOLT:
+                       data[0] |= IRQ_CTL_BIT_VMX;
+                       /*Enable max voltage alert*/
+                       bi->max_volt_irq = true;
+                       /*RTDBG("Enable max voltage alert");*/
+                       break;
+               case MINVOLT1:
+                       data[0] |= IRQ_CTL_BIT_VMN1;
+                       /*Enable min1 voltage alert*/
+                       bi->min_volt1_irq = true;
+                       /*RTDBG("Enable min1 voltage alert");*/
+                       break;
+               case MINVOLT2:
+                       data[0] |= IRQ_CTL_BIT_VMN2;
+                       /*Enable min2 voltage alert*/
+                       bi->min_volt2_irq = true;
+                       /*RTDBG("Enable min2 voltage alert");*/
+                       break;
+               default:
+                       break;
                }
-       }else{
-               switch(type){
-                       case MAXTEMP:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_TMX; //Disable max temperature alert
-                               bi->max_temp_irq = false;
-                               //RTDBG("Disable min temperature alert");
-                               break;
-                       case MINTEMP:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_TMN; //Disable min temperature alert
-                               bi->min_temp_irq = false;
-                               //RTDBG("Disable max temperature alert");
-                               break;
-                       case MAXVOLT:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_VMX; //Disable max voltage alert
-                               bi->max_volt_irq = false;
-                               //RTDBG("Disable max voltage alert");
-                               break;
-                       case MINVOLT1:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_VMN1; //Disable min1 voltage alert     
-                               bi->min_volt1_irq = false;
-                               //RTDBG("Disable min1 voltage alert");
-                               break;
-                       case MINVOLT2:
-                               data[0] = data[0] &~ IRQ_CTL_BIT_VMN2; //Disable min2 voltage alert
-                               bi->min_volt2_irq = false;
-                               //RTDBG("Disable min2 voltage alert");
-                               break;
-                       default:
-                               break;
+       } else {
+               switch (type) {
+               case MAXTEMP:
+                       data[0] = data[0] & ~IRQ_CTL_BIT_TMX;
+                       /*Disable max temperature alert*/
+                       bi->max_temp_irq = false;
+                       /*RTDBG("Disable min temperature alert");*/
+                       break;
+               case MINTEMP:
+                       data[0] = data[0] & ~IRQ_CTL_BIT_TMN;
+                       /*Disable min temperature alert*/
+                       bi->min_temp_irq = false;
+                       /*RTDBG("Disable max temperature alert");*/
+                       break;
+               case MAXVOLT:
+                       data[0] = data[0] & ~IRQ_CTL_BIT_VMX;
+                       /*Disable max voltage alert*/
+                       bi->max_volt_irq = false;
+                       /*RTDBG("Disable max voltage alert");*/
+                       break;
+               case MINVOLT1:
+                       data[0] = data[0] & ~IRQ_CTL_BIT_VMN1;
+                       /*Disable min1 voltage alert*/
+                       bi->min_volt1_irq = false;
+                       /*RTDBG("Disable min1 voltage alert");*/
+                       break;
+               case MINVOLT2:
+                       data[0] = data[0] & ~IRQ_CTL_BIT_VMN2;
+                       /*Disable min2 voltage alert*/
+                       bi->min_volt2_irq = false;
+                       /*RTDBG("Disable min2 voltage alert");*/
+                       break;
+               default:
+                       break;
                }
        }
-       if (rt5025_write_reg(bi->client, RT5025_REG_IRQ_CTL, data, 1) < 0)
+       if (rt5025_write_reg(bi->client, RT5025_REG_IRQCTL, data, 1) < 0)
                pr_err("%s: failed to write IRQ control\n", __func__);
 }
 
@@ -619,28 +689,21 @@ static void rt5025_alert_threshold_init(struct i2c_client *client)
 {
        u8 data[1];
 
-       #if 0 //change the operating right to jeita driver
-       /* TALRT MAX threshold setting */
-       data[0] = irq_thres[MAXTEMP];
-       if (rt5025_write_reg(client, RT5025_REG_TALRT_MAXTH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write TALRT MAX threshold\n", __func__); 
-       /* TALRT MIN threshold setting */
-       data[0] = irq_thres[MINTEMP];
-       if (rt5025_write_reg(client, RT5025_REG_TALRT_MINTH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write TALRT MIN threshold\n", __func__); 
-       #endif
        /* VALRT MAX threshold setting */
        data[0] = irq_thres[MAXVOLT];
-       if (rt5025_write_reg(client, RT5025_REG_VALRT_MAXTH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write VALRT MAX threshold\n", __func__); 
+       if (rt5025_write_reg(client, RT5025_REG_VALRTMAX, data, 1) < 0)
+               pr_err("%s: failed to write VALRT MAX threshold\n",
+                       __func__);
        /* VALRT MIN1 threshold setting */
        data[0] = irq_thres[MINVOLT1];
-       if (rt5025_write_reg(client, RT5025_REG_VALRT_MIN1TH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write VALRT MIN1 threshold\n", __func__);        
+       if (rt5025_write_reg(client, RT5025_REG_VALRTMIN1, data, 1) < 0)
+               pr_err("%s: failed to write VALRT MIN1 threshold\n",
+                       __func__);
        /* VALRT MIN2 threshold setting */
        data[0] = irq_thres[MINVOLT2];
-       if (rt5025_write_reg(client, RT5025_REG_VALRT_MIN2TH, data, 1) < 0)
-               printk(KERN_ERR "%s: failed to write VALRT MIN2 threshold\n", __func__);        
+       if (rt5025_write_reg(client, RT5025_REG_VALRTMIN2, data, 1) < 0)
+               pr_err("%s: failed to write VALRT MIN2 threshold\n",
+                       __func__);
 }
 
 static void rt5025_alert_init(struct rt5025_battery_info *bi)
@@ -649,103 +712,148 @@ static void rt5025_alert_init(struct rt5025_battery_info *bi)
        /* Set RT5025 gauge alert configuration */
        rt5025_alert_threshold_init(bi->client);
        /* Enable gauge alert function */
-       rt5025_alert_setting(bi, MINVOLT2,VOLTAGE_ALERT);       
+       rt5025_alert_setting(bi, MINVOLT2, VOLTAGE_ALERT);
 }
 
-void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, u8 irq_flag)
+void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi,
+       unsigned int irq_flag)
 {
-  rt5025_get_irq_flag(bi, irq_flag);
+       rt5025_get_irq_flag(bi, irq_flag);
 
-  if ((bi->irq_flag) & IRQ_FLG_BIT_TMX){       
-               //printk(KERN_INFO "[RT5025]: Min temperature IRQ received\n");
-               rt5025_alert_setting(bi,MAXTEMP,false);
+       if ((bi->irq_flag) & IRQ_FLG_BIT_TMX) {
+               /*printk(KERN_INFO "[RT5025]: Min temperature IRQ received\n");*/
+               rt5025_alert_setting(bi, MAXTEMP, false);
                bi->max_temp_irq = false;
        }
-  if ((bi->irq_flag) & IRQ_FLG_BIT_TMN){
-               //printk(KERN_INFO "[RT5025]: Max temperature IRQ received\n");
-               rt5025_alert_setting(bi,MINTEMP,false);
-               bi->min_temp_irq = false; 
+       if ((bi->irq_flag) & IRQ_FLG_BIT_TMN) {
+               /*printk(KERN_INFO "[RT5025]: Max temperature IRQ received\n");*/
+               rt5025_alert_setting(bi, MINTEMP, false);
+               bi->min_temp_irq = false;
        }
-  if ((bi->irq_flag) & IRQ_FLG_BIT_VMX){
-               //printk(KERN_INFO "[RT5025]: Max voltage IRQ received\n");
-               rt5025_alert_setting(bi,MAXVOLT,false);
+       if ((bi->irq_flag) & IRQ_FLG_BIT_VMX) {
+               /*printk(KERN_INFO "[RT5025]: Max voltage IRQ received\n");*/
+               rt5025_alert_setting(bi, MAXVOLT, false);
                bi->max_volt_irq = false;
        }
-  if ((bi->irq_flag) & IRQ_FLG_BIT_VMN1){
-               //printk(KERN_INFO "[RT5025]: Min voltage1 IRQ received\n");
-               rt5025_alert_setting(bi,MINVOLT1,false);
+       if ((bi->irq_flag) & IRQ_FLG_BIT_VMN1) {
+               /*printk(KERN_INFO "[RT5025]: Min voltage1 IRQ received\n");*/
+               rt5025_alert_setting(bi, MINVOLT1, false);
                bi->min_volt1_irq = false;
        }
-  if ((bi->irq_flag) & IRQ_FLG_BIT_VMN2){
-               //printk(KERN_INFO "[RT5025]: Min voltage2 IRQ received\n");
-               rt5025_alert_setting(bi,MINVOLT2,false);
+       if ((bi->irq_flag) & IRQ_FLG_BIT_VMN2) {
+               /*printk(KERN_INFO "[RT5025]: Min voltage2 IRQ received\n");*/
+               rt5025_alert_setting(bi, MINVOLT2, false);
                bi->min_volt2_irq = false;
                bi->min_volt2_alert = true;
-               wake_lock_timeout(&bi->low_battery_wake_lock, msecs_to_jiffies(LOW_BAT_WAKE_LOK_TIME*MSEC_PER_SEC));
+               wake_lock_timeout(&bi->low_battery_wake_lock,
+                                 msecs_to_jiffies(LOW_BAT_WAKE_LOK_TIME *
+                                                  MSEC_PER_SEC));
        }
-       
-       wake_lock(&bi->monitor_wake_lock);
-       schedule_delayed_work(&bi->monitor_work, 0);
 }
 EXPORT_SYMBOL(rt5025_gauge_irq_handler);
 
 static void rt5025_convert_masec_to_permille(struct rt5025_battery_info *bi)
 {
-  bi->permille = bi->rm / 3600 * 1000 / bi->fcc;
-  RTINFO("permille=%d\n", bi->permille);
-  return;
+       bi->permille = bi->rm / 3600 * 1000 / bi->fcc;
+       RTINFO("permille=%d\n", bi->permille);
+       /*return;*/
 }
 
 static void rt5025_convert_permille_to_masec(struct rt5025_battery_info *bi)
-{ 
-  bi->rm = bi->permille * bi->fcc / 1000 * 3600;
-  return;
+{
+       bi->rm = bi->permille * bi->fcc / 1000 * 3600;
+       /*return;*/
 }
 
 static void rt5025_init_capacity(struct rt5025_battery_info *bi)
 {
-  int i = 1;
-  int size;
-  int slope, const_term;
-  int delta_y, delta_x;
-
-  size = ARRAY_SIZE(rt5025_battery_param1);
-  while((bi->vcell < rt5025_battery_param1[i].x) &&
-                               (i < (size - 1))){
-    i++;
-  }
+       int i = 1;
+       int size;
+       int slope, const_term;
+       int delta_y, delta_x;
+
+       size = ARRAY_SIZE(rt5025_battery_param1);
+       while ((bi->vcell < rt5025_battery_param1[i].x) &&
+               (i < (size - 1))) {
+               i++;
+       }
 
-  delta_x = rt5025_battery_param1[i-1].x - rt5025_battery_param1[i].x;
-  delta_y = (rt5025_battery_param1[i-1].y - rt5025_battery_param1[i].y);
+       delta_x = rt5025_battery_param1[i-1].x - rt5025_battery_param1[i].x;
+       delta_y = (rt5025_battery_param1[i-1].y - rt5025_battery_param1[i].y);
 
-  slope = delta_y  * 1000 / delta_x;
+       slope = delta_y  * 1000 / delta_x;
 
-  const_term = (rt5025_battery_param1[i].y) - ((rt5025_battery_param1[i].x * slope) / 1000);
+       const_term = (rt5025_battery_param1[i].y) - ((rt5025_battery_param1[i].x * slope) / 1000);
 
-  if (bi->vcell >= rt5025_battery_param1[0].x)
-    bi->permille = rt5025_battery_param1[0].y; 
-  else if (bi->vcell <= rt5025_battery_param1[size-1].x)
-    bi->permille = rt5025_battery_param1[size-1].y;
-  else
-    bi->permille = (bi->vcell * slope) / 1000 + const_term;
-  rt5025_convert_permille_to_masec(bi);
-  bi->soc = bi->rm /36/bi->fcc_aging;
+       if (bi->vcell >= rt5025_battery_param1[0].x)
+               bi->permille = rt5025_battery_param1[0].y;
+       else if (bi->vcell <= rt5025_battery_param1[size-1].x)
+               bi->permille = rt5025_battery_param1[size-1].y;
+       else
+               bi->permille = (bi->vcell * slope) / 1000 + const_term;
+       rt5025_convert_permille_to_masec(bi);
+       bi->soc = bi->rm / 36 / bi->fcc_aging;
        bi->init_cap = false;
 
-  //pr_err("[rt5025] i=%d, delta_x=%d, delta_y=%d, slope=%d, const_term=%d\n", i, delta_x, delta_y, slope, const_term);
-       RTINFO("voltage=%d, permille=%d, soc=%d, rm=%d\n", bi->vcell, bi->permille, bi->soc, bi->rm);
-  return;              
+       rt5025_battery_parameter_backup(bi);
+
+       RTINFO("voltage=%d, permille=%d, soc=%d, rm=%d\n",
+               bi->vcell, bi->permille, bi->soc, bi->rm);
+       /*return;*/
 }
 
 static void rt5025_smooth_soc(struct rt5025_battery_info *bi)
 {
-       if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) &&
-           (bi->soc < 100)){
-               bi->soc++;
-       }else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
-                 (bi->soc > 0)){
-               bi->soc--;
-       }else{
+       if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING || bi->tp_flag) &&
+           (bi->soc < 100)) {
+               if (bi->last_suspend  == true) {
+                       bi->soc = 100;
+                       bi->last_suspend = false;
+               } else {
+                       bi->soc++;
+               }
+               bi->rm = bi->fcc * bi->soc * 36;
+               rt5025_convert_masec_to_permille(bi);
+
+               if (bi->soc == 100) {
+                       /*fcc update in soc smooth 100%.*/
+                       if (bi->cal_soc_offset != 0) {
+                               bi->fcc_aging -= bi->cal_soc_offset;
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->soc * 36;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                               }
+                               bi->cal_soc_offset = 0;
+                       }
+                       wake_unlock(&bi->smooth100_wake_lock);
+                       bi->last_tp = true;
+                       bi->tp_flag = false;
+                       bi->pre_soc = bi->soc;
+
+                       /*c. Only EOC occurs and full discharge to update FCC; 2013/12/17*/
+                       bi->last_tp_flag = true;
+                       mutex_lock(&bi->status_change_lock);
+                       if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) {
+                               bi->status = POWER_SUPPLY_STATUS_FULL;
+                               rt5025_set_battery_led(bi, bi->status);
+                       }
+                       mutex_unlock(&bi->status_change_lock);
+               }
+       } else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+               (bi->soc > 0)) {
+               if (bi->last_suspend  == true) {
+                       bi->soc = 0;
+                       bi->last_suspend = false;
+               } else {
+                       bi->soc--;
+               }
+               bi->rm = bi->fcc * bi->soc * 36;
+               rt5025_convert_masec_to_permille(bi);
+               if (bi->soc == 0)
+                       wake_unlock(&bi->smooth0_wake_lock);
+       } else {
          bi->smooth_flag = false;
          bi->update_time = NORMAL_POLL;
   }
@@ -754,366 +862,373 @@ static void rt5025_smooth_soc(struct rt5025_battery_info *bi)
 
 static void rt5025_soc_irreversible(struct rt5025_battery_info *bi)
 {
-       // Prevent inverse
-       //if (!bi->init_cap){
-       if (!bi->init_once){
-               if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING){
+       if (!bi->init_once) {
+               if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) {
                        if (bi->soc < bi->pre_soc)
                                bi->soc = bi->pre_soc;
-               }else if (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING){
+               } else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+                                               (bi->tp_flag == 0)) {
                        if (bi->soc > bi->pre_soc)
-                               bi->soc = bi->pre_soc;          
+                               bi->soc = bi->pre_soc;
                }
-       }
-       else
+       } else {
                bi->init_once = false;
+       }
 
-       bi->pre_soc = bi->soc; 
+       if (bi->pre_soc != bi->soc)
+               rt5025_battery_parameter_backup(bi);
+
+       bi->pre_soc = bi->soc;
+       RTINFO("pre_soc=%d, soc=%d, internal status=%d\n",
+               bi->pre_soc, bi->soc, bi->internal_status);
 }
 
 static void rt5025_soc_lock(struct rt5025_battery_info *bi)
 {
-        // lock 99%
-  RTINFO("internal status=%d, tp_flag=%d, soc=%d\n", bi->internal_status, bi->tp_flag, bi->soc);
-  if ((bi->soc >= 99) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING))
-  {
-       if (bi->tp_flag)
-               bi->soc = 100;
-       else
-       {
-               if (bi->status == POWER_SUPPLY_STATUS_FULL)
+        /*lock 99%*/
+       u16 eoc_fcc_new  = 0;
+
+       RTINFO("internal status=%d, tp_flag=%d, soc=%d, soc99_lock_cnt=%d\n",
+               bi->internal_status, bi->tp_flag, bi->soc,
+               bi->soc99_lock_cnt);
+       RTINFO("init_once=%d, rm=%d, soc=%d\n",
+               bi->init_once, bi->rm, bi->soc);
+
+       if (bi->soc >= 99) {
+               if (bi->soc99_lock_cnt >= 3600) {
                        bi->soc = 100;
-               else
-                       bi->soc = 99;
+                       bi->permille = 1000;
+                       /*eoc fcc update function: when flag is true, update FCC.*/
+                       if (bi->cal_eoc_fcc != 0) {
+                               /*eoc fcc update function: fcc update limitation 3%*/
+                               eoc_fcc_new = bi->fcc_aging + bi->cal_eoc_fcc / 3600;
+                               if (eoc_fcc_new > ((bi->fcc_aging * 103) / 100))
+                                       bi->fcc_aging = (bi->fcc_aging * 103) / 100;
+                               else
+                                       bi->fcc_aging = eoc_fcc_new;
+
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->permille * 36 / 10;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                                       }
+                               bi->cal_eoc_fcc = 0;
+                       }
+                       wake_unlock(&bi->full_battery_wake_lock);
+                       bi->soc99_lock_cnt = 0;
+                       bi->last_tp = true;
+                       bi->tp_flag = false;
+                       bi->pre_soc = bi->soc;
+                       /*b. add fcc update flag; 2013/12/18*/
+                       bi->fcc_update_flag = false;
+
+                       /*a. When SOC = 100, report battery status is full; 2013/12/17
+                       bi->status = POWER_SUPPLY_STATUS_FULL;
+                       */
+               } else if (bi->tp_flag) {
+                       RTINFO("before_eoc_fcc_new=%d\n", eoc_fcc_new);
+                       RTINFO("before_cal_eoc_fcc=%d\n", bi->cal_eoc_fcc);
+                       RTINFO("before_fcc_aging=%d\n", bi->fcc_aging);
+                       bi->soc = 100;
+                       bi->permille = 1000;
+                       if (bi->cal_eoc_fcc != 0) {
+                               /*fcc update in eoc occurs. */
+                               eoc_fcc_new = bi->fcc_aging + bi->cal_eoc_fcc/3600;
+                               if (eoc_fcc_new > ((bi->fcc_aging*103)/100))
+                                       bi->fcc_aging = (bi->fcc_aging*103)/100;
+                               else
+                                       bi->fcc_aging = eoc_fcc_new;
+
+                               RTINFO("after_eoc_fcc_new=%d\n", eoc_fcc_new);
+                               RTINFO("after_cal_eoc_fcc=%d\n", bi->cal_eoc_fcc);
+                               RTINFO("after_fcc_aging=%d\n", bi->fcc_aging);
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->permille * 36 / 10;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                               }
+                               bi->cal_eoc_fcc = 0;
+                       } else if (bi->cal_soc_offset != 0) {
+                               bi->fcc_aging -= bi->cal_soc_offset;
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->permille * 36 / 10;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                               }
+                               bi->cal_soc_offset = 0;
+                       }
+
+                       wake_unlock(&bi->full_battery_wake_lock);
+                       bi->soc99_lock_cnt = 0;
+                       bi->last_tp = true;
+                       bi->tp_flag = false;
+                       bi->pre_soc = bi->soc;
+
+                       /*c. Only EOC occurs and full discharge to update FCC; 2013/12/17*/
+                       bi->last_tp_flag = true;
+
+                       mutex_lock(&bi->status_change_lock);
+                       if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) {
+                               bi->status = POWER_SUPPLY_STATUS_FULL;
+                               rt5025_set_battery_led(bi, bi->status);
+                       }
+                       mutex_unlock(&bi->status_change_lock);
+               } else if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)  &&
+                                               (bi->last_tp == false)) {
+                       bi->soc = 99;
+                       bi->pre_soc = 99;
+                       bi->soc99_lock_cnt += bi->time_interval;
+               }
+       } else if ((bi->soc < 99) && (bi->tp_flag)) {
+               /*calculate soc offset */
+               if (bi->cal_soc_offset == 0) {
+                       bi->cal_soc_offset = bi->fcc*3600 - bi->rm;
+                       if (bi->cal_soc_offset > (bi->fcc_aging*3/100))
+                               bi->cal_soc_offset = bi->fcc_aging*3/100;
+               }
+               wake_lock(&bi->smooth100_wake_lock);
+               bi->update_time = SMOOTH_POLL;
+               bi->smooth_flag = true;
+               rt5025_smooth_soc(bi);
+       } else {
+               wake_unlock(&bi->smooth100_wake_lock);
+               bi->tp_flag = false;
+               bi->soc99_lock_cnt = 0;
+       }
+               /* a. When SOC = 100, report battery status is full; 2013/12/17
+               /// a. judge charging status to check battery full condition; 2013/12/18*/
+       if ((bi->soc == 100) &&
+               (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)) {
+               mutex_lock(&bi->status_change_lock);
+               if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) {
+                       bi->status = POWER_SUPPLY_STATUS_FULL;
+                       rt5025_set_battery_led(bi, bi->status);
+               }
+               mutex_unlock(&bi->status_change_lock);
        }
-  }
-  else if ((bi->soc < 99) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) && \
-          (bi->tp_flag))
-  {
-       bi->update_time = SMOOTH_POLL;
-       bi->smooth_flag = true;
-       rt5025_smooth_soc(bi);
-  }else
-  {
-       bi->tp_flag = false;
-  }
 
-  // lock 1%   
-  if ((bi->soc <= 1) &&
-      (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)){
-    if (bi->edv_flag)
-      bi->soc = 0;
-    else
-      bi->soc = 1;
-       }else if ((bi->soc > 1) &&
-            (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
-            (bi->edv_flag)){
+       /*lock 1%   */
+       if ((bi->soc <= 1) &&
+         (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)) {
+               if (bi->edv_flag) {
+                       bi->soc = 0;
+               } else {
+                       if (bi->rm <= 0) {
+                               bi->soc1_lock_cnt += bi->time_interval;
+                               if (bi->soc1_lock_cnt >= 600) {
+                                       bi->soc = 0;
+                                       bi->soc1_lock_cnt = 0;
+                               } else {
+                                       bi->soc = 1;
+                                       bi->pre_soc = 1;
+                               }
+                       } else {
+                               bi->soc = 1;
+                               bi->pre_soc = 1;
+                               bi->soc1_lock_cnt = 0;
+                       }
+               }
+       } else if ((bi->soc > 1) &&
+               (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+                       (bi->edv_flag)) {
+               wake_lock(&bi->smooth0_wake_lock);
                bi->update_time = SMOOTH_POLL;
                bi->smooth_flag = true;
                rt5025_smooth_soc(bi);
-       }else{
+       } else {
                bi->edv_flag = false;
+               wake_unlock(&bi->smooth0_wake_lock);
        }
+       RTINFO("cal_soc_offset=%d\n", bi->cal_soc_offset);
 }
 
 static void rt5025_get_soc(struct rt5025_battery_info *bi)
 {
-  if (bi->smooth_flag){
-    bi->smooth_flag = false;
-    bi->update_time = NORMAL_POLL;
-  }
+       if (bi->smooth_flag) {
+               bi->smooth_flag = false;
+               bi->update_time = NORMAL_POLL;
+       }
        RTINFO("before rm=%d\n", bi->rm);
-       if ((!bi->tp_flag) &&
-                       (!bi->edv_flag)){
-               bi->rm = (bi->rm + bi->chg_cc) > bi->dchg_cc ? 
-                           bi->rm + bi->chg_cc - bi->dchg_cc : 0;
+       if ((!bi->tp_flag) && (!bi->edv_flag)) {
+               bi->rm = (bi->rm + bi->chg_cc) > bi->dchg_cc ?
+                       bi->rm + bi->chg_cc - bi->dchg_cc : 0;
                if (bi->rm > (bi->fcc * 3600))
-                                       bi->rm = bi->fcc * 3600;
+                       bi->rm = bi->fcc * 3600;
+
+               /* accumulate coulomb counter when rm = fcc and enable flag = true.*/
+               if (bi->rm == (bi->fcc * 3600))
+                       bi->cal_eoc_fcc += (bi->chg_cc - bi->dchg_cc);
+               else
+                       bi->cal_eoc_fcc = 0;
+
+               RTINFO("cal_eoc_fcc=%d\n", bi->cal_eoc_fcc);
                rt5025_convert_masec_to_permille(bi);
+               /*a. When SOC = 100, report battery status is full; 2113/12/17*/
                bi->soc = DIV_ROUND_UP(bi->permille, 10);
+       }
 #if RT5025_CSV
-    bi->temp_soc = bi->soc;
-    //pr_info("%d", bi->soc);
+       bi->temp_soc = bi->soc;
+       /*pr_info("%d", bi->soc);*/
 #else
        RTINFO("after rm=%d\n", bi->rm);
-               RTINFO("temp_soc=%d\n", bi->soc);
+       RTINFO("temp_soc=%d\n", bi->soc);
 #endif
-  }
 #if RT5025_CSV
- // pr_info("%d,%d,%d,%d,%d", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);
-#else  
-       RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);
+       RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n",
+               bi->soc, bi->permille, bi->rm,
+               bi->fcc, bi->smooth_flag);
+       /*pr_info("%d,%d,%d,%d,%d", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);*/
+#else
+       RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n",
+               bi->soc, bi->permille, bi->rm,
+               bi->fcc, bi->smooth_flag);
 #endif
-  return;
+       /*return;*/
 }
 
 static void rt5025_soc_relearn_check(struct rt5025_battery_info *bi)
 {
-  // TP relearn
-/*  if ((bi->vcell >= TP_VOLT) &&
-                       (bi->curr <= TP_CURR) &&
-                       (bi->status == POWER_SUPPLY_STATUS_CHARGING) &&
-                       (!bi->tp_flag)){
-               bi->tp_cnt++;
-               bi->update_time = TP_POLL;
-       }else {
-               bi->tp_cnt = 0;
-               bi->update_time = NORMAL_POLL;
-       }
-   
-  if (bi->tp_cnt == TP_TOTAL_COUNT){
-               bi->tp_cnt = 0;
-               bi->tp_flag = true;
-               bi->rm = bi->fcc * 3600;
-               rt5025_convert_masec_to_permille();
-               bi->update_time = NORMAL_POLL;
-       }*/
-       
-       // if EOC happened, the tp_flag should be set 1.
-       if(bi->tp_flag == true)
-       {
+
+       if (bi->tp_flag == true) {
                bi->rm = bi->fcc * 3600;
                rt5025_convert_masec_to_permille(bi);
                bi->update_time = NORMAL_POLL;
        }
-       
-       if(rt5025_battery_param2[4].x < bi->vcell && bi->vcell <= rt5025_battery_param2[4].x+300)
-       {
+
+       if (bi->vcell <= bi->empty_edv) {
+               if (bi->edv_cnt < 2)
+                       bi->edv_cnt++;
+       } else {
+               bi->edv_cnt = 0;
+       }
+
+       if (bi->empty_edv < bi->vcell && bi->vcell <= bi->empty_edv + 300) {
                bi->update_time = EDV_POLL;
                bi->edv_detection = true;
-       }
-       else if((bi->vcell >= rt5025_battery_param2[4].x + 300 +EDV_HYS) && (bi->edv_detection == true))
-       {
+       } else if ((bi->vcell >= bi->empty_edv + 300 + EDV_HYS)
+               && (bi->edv_detection == true)) {
                 bi->update_time = NORMAL_POLL;
-                bi->edv_detection = false;              
-       }
-       else if((bi->vcell <= rt5025_battery_param2[4].x) && (bi->min_volt2_alert == true))
-       {
+                bi->edv_detection = false;
+       } else if ((bi->vcell <= bi->empty_edv && bi->edv_cnt == 2)) {
                bi->edv_flag = true;
                bi->rm = 0;
                rt5025_convert_masec_to_permille(bi);
                bi->edv_detection = false;
                bi->update_time = NORMAL_POLL;
-       }
-       else if((bi->vcell > rt5025_battery_param2[4].x + EDV_HYS) && (bi->min_volt2_alert == true))
-       {
+       } else if ((bi->vcell > bi->empty_edv + EDV_HYS)) {
                bi->min_volt2_alert = false;
-       }
-       
-       /*// EDV relearn
-  if (bi->vcell <= EDV_VOLT){
-               if ((bi->curr <= EDV_CURR) ||
-                               (bi->vcell <= rt5025_battery_param2[4].x))
-                       bi->edv_cnt++;
-               else
-               {
-                       bi->edv_cnt = 0;        
-               }
-               bi->edv_detection = true;
-               bi->update_time = EDV_POLL;
-       }else if ((bi->vcell > (EDV_VOLT + EDV_HYS)) &&
-                 (bi->edv_detection)) {
-               bi->edv_cnt = 0;
-               bi->edv_detection = false;
                bi->edv_flag = false;
-               bi->update_time = NORMAL_POLL;
-       }
-       else
-       {
-               bi->edv_cnt = 0;
        }
-   
-  if (bi->edv_cnt == EDV_TOTAL_COUNT){
-               bi->edv_cnt = 0;
-               bi->edv_flag = true;
-               bi->rm = 0;
-               rt5025_convert_masec_to_permille();
-               bi->edv_detection = false;
-               bi->update_time = NORMAL_POLL;
-       }
-  if(bi->edv_detection)
-  {
-       bi->update_time = EDV_POLL;
-  }*/
-  if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING) 
-         bi->edv_flag = false;
-  else if (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)
-    bi->tp_flag = false;
+
+       if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)
+               bi->edv_flag = false;
 
 #if RT5025_CSV
-  //pr_err("%d,%d,%d,%d,%d", 
-   // bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag);
-#else  
-       RTINFO("tp_cnt=%d, tp_flag=%d, edv_detection=%d, edv_cnt=%d, edv_flag=%d\n", 
-    bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag);
+#else
+       RTINFO("tp_cnt=%d, tp_flag=%d, edv_detection=%d, edv_cnt=%d, edv_flag=%d\n",
+       bi->tp_cnt, bi->tp_flag, bi->edv_detection,
+       bi->edv_cnt, bi->edv_flag);
 #endif
 
-  return;
+ /* return;*/
 }
 
-static void rt5025_channel_cc(struct rt5025_battery_info *bi, bool enable)
+static u16 get_crc16_value(u8 *data, int size)
 {
-  u8 data[1];
-       
-  if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
-    printk(KERN_INFO "%s: failed to read channel\n", __func__);
-  }
-
-  if (enable){
-    data[0] = data[0] | 0x80;
-  }else { 
-    data[0] = data[0] & 0x7F;
-  }
-    
-  if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
-    printk(KERN_INFO "%s: failed to write channel\n", __func__);
-  }
+       u16 fcs = 0xffff;
+       int len = size;
+       int i = 0;
+       u16 temp = 0;
+
+       while (len > 0) {
+               fcs = (u16)((fcs >> 8) ^ crctab16[(fcs ^ data[i]) & 0xff]);
+               len--;
+               i++;
+       }
+       temp = (u16)~fcs;
+       return temp;
 }
 
-#if 0
-static void rt5025_pretrim(struct rt5025_battery_info *bi)
+static int IsCrc16Good(u8 *data, int size)
 {
-       u8 data0[2];
-       u8 data1[1];
-       
-       data0[0] = 0x55;
-       data0[1] = 0xAA;
-  if (rt5025_write_reg(bi->client, 0xF0, data0, 2) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-       data0[0] = 0x07;
-  if (rt5025_write_reg(bi->client, 0xF1, data0, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-  // write trim data D0
-       data0[0] = 0xDE;
-  if (rt5025_write_reg(bi->client, 0xD0, data0, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-  // Read back to verify
-  if (rt5025_read_reg(bi->client, 0xD0, data1, 1) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-  if (data1[0] != data0[0])
-               printk(KERN_ERR "%s: 0xD0 write fail\n", __func__);
-       // write trim data D1
-       data0[0] = 0x01;
-  if (rt5025_write_reg(bi->client, 0xD1, data0, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-  // Read back to verify
-  if (rt5025_read_reg(bi->client, 0xD1, data1, 1) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-  if (data1[0] != data0[0])
-               printk(KERN_ERR "%s: 0xD1 write fail\n", __func__);
-  // write trim data D2
-       data0[0] = 0x10;
-  if (rt5025_write_reg(bi->client, 0xD2, data0, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-  // Read back to verify
-  if (rt5025_read_reg(bi->client, 0xD2, data1, 1) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-  if(data1[0] != data0[0])
-               printk(KERN_ERR "%s: 0xD2 write fail\n", __func__);
-  // write trim data D3
-       data0[0] = 0x89;
-  if (rt5025_write_reg(bi->client, 0xD3, data0, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-  // Read back to verify
-  if (rt5025_read_reg(bi->client, 0xD3, data1, 1) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-  if(data1[0] != data0[0])
-               printk(KERN_ERR "%s: 0xD3 write fail\n", __func__);
-  // write trim data D4
-       data0[0] = 0xF2;
-  if (rt5025_write_reg(bi->client, 0xD4, data0, 1) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
-  // Read back to verify
-  if (rt5025_read_reg(bi->client, 0xD4, data1, 1) < 0){
-    printk(KERN_ERR "%s: failed to read channel\n", __func__);
-  }
-  if (data1[0] != data0[0])
-               printk(KERN_ERR "%s: 0xD4 write fail\n", __func__);                             
-                        
-       data0[0] = 0x55;
-       data0[1] = 0x55;
-  if (rt5025_write_reg(bi->client, 0xF0, data0, 2) < 0){
-    printk(KERN_ERR "%s: failed to write channel\n", __func__);
-  }
+       u16 fcs = 0xffff;
+       int len = size;
+       int i = 0;
+
+       while (len > 0) {
+               fcs = (u16)((fcs >> 8) ^ crctab16[((fcs ^ data[i]) & 0xff)]);
+               len--;
+               i++;
+       }
+       return (fcs == 0xf0b8);
 }
-#endif
 
 static int rt5025_battery_parameter_backup(struct rt5025_battery_info *bi)
 {
-       u8 data[4];
+       u16 crc_value = 0;
+       u8 data[15] = {0};
+
        RTINFO("\n");
-       //backup fcc_aging, rm, cycle_count, acc_dchg_cap
-       //fcc_aging
-       data[0] = (bi->fcc_aging>>8)&0xff;
-       data[1] = (bi->fcc_aging)&0xff;
-       rt5025_write_reg(bi->client, 0x21, data, 2);
-       //rm
-       data[0] = (bi->rm>>24)&0xff;
-       data[1] = (bi->rm>>16)&0xff;
-       data[2] = (bi->rm>>8)&0xff;
-       data[3] = (bi->rm)&0xff;
-       rt5025_write_reg(bi->client, 0x23, data, 4);
-       //acc_dchg_cap
-       data[0] = (bi->acc_dchg_cap>>24)&0xff;
-       data[1] = (bi->acc_dchg_cap>>16)&0xff;
-       data[2] = (bi->acc_dchg_cap>>8)&0xff;
-       data[3] = (bi->acc_dchg_cap)&0xff;
-       rt5025_write_reg(bi->client, 0x27, data, 4);
-       //cycle_count
-       data[0] = (bi->cycle_cnt)&0xff;
-       rt5025_write_reg(bi->client, 0x2B, data, 1);
+       /*backup fcc_aging, rm, cycle_count, acc_dchg_cap*/
+       /*fcc_aging*/
+       data[0] = (bi->fcc_aging >> 8) & 0xff;
+       data[1] = (bi->fcc_aging) & 0xff;
+       /*acc_dchg_cap*/
+       data[2] = (bi->acc_dchg_cap >> 24) & 0xff;
+       data[3] = (bi->acc_dchg_cap >> 16) & 0xff;
+       data[4] = (bi->acc_dchg_cap >> 8) & 0xff;
+       data[5] = (bi->acc_dchg_cap) & 0xff;
+       /*cycle_count*/
+       data[6] = (bi->cycle_cnt) & 0xff;
+       /*soc*/
+       data[7] = (bi->permille >> 8) & 0xff;
+       data[8] = (bi->permille) & 0xff;
+       /*gauge_timer*/
+       data[9] = (bi->pre_gauge_timer >> 8) & 0xff;
+       data[10] = bi->pre_gauge_timer & 0xff;
+       /*CRC value*/
+       crc_value = get_crc16_value(data, 13);
+       data[13] = crc_value & 0xff;
+       data[14] = (crc_value >> 8) & 0xff;
+       rt5025_write_reg(bi->client, RT5025_REG_RESV1, data, 15);
        return 0;
 }
 
 static int rt5025_battery_parameter_restore(struct rt5025_battery_info *bi)
 {
-       u8 data[4];
+       u8 data[15];
+
        RTINFO("\n");
-       //restore fcc_aging, rm ,cycle_count, acc_dchg_cap
-       //fcc_aging
-       rt5025_read_reg(bi->client, 0x21, data, 2);
-       bi->fcc = bi->fcc_aging = data[0]<<8 | data[1];
-       //rm
-       rt5025_read_reg(bi->client, 0x23, data, 4);
-       bi->rm = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
-       //acc_dchg_cap
-       rt5025_read_reg(bi->client, 0x27, data, 4);
-       bi->acc_dchg_cap = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
-       //cycle_count
-       rt5025_read_reg(bi->client, 0x2B, data, 1);
-       bi->cycle_cnt = data[0];
-       
+       rt5025_read_reg(bi->client, RT5025_REG_RESV1, data, 15);
+       /*restore fcc_aging, rm ,cycle_count, acc_dchg_cap*/
+       /*fcc_aging*/
+       bi->fcc = bi->fcc_aging = data[0] << 8 | data[1];
+       /*acc_dchg_cap*/
+       bi->acc_dchg_cap = data[2] << 24 | data[3] << 16 | data[4] << 8 | data[5];
+       /*cycle_count*/
+       bi->cycle_cnt = data[6];
+       /*soc*/
+       bi->permille = data[7] << 8 | data[8];
+       /*pre_gauge_timer*/
+       bi->pre_gauge_timer = bi->gauge_timer = (data[9] << 8) + data[10];
+
        return 0;
 }
 
-
-// return value; 1-> initialized, 0-> no initial value
+/*return value; 1-> initialized, 0-> no initial value*/
 static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi)
 {
-       u8 data[2];
-       u16 value;
+       u8 data[15] = {0};
        int ret = 0;
 
-       if (rt5025_read_reg(bi->client, 0x21, data, 2) < 0)
-       {
+       if (rt5025_read_reg(bi->client, RT5025_REG_RESV1, data, 15) < 0) {
                pr_err("%s: check initial value error\n", __func__);
-       }
-       else
-       {
-               value = data[1]<<8 | data[0];
-               if (value)
-                       ret = 1;
+               return 0;
+       } else {
+               ret = IsCrc16Good(data, 15);
        }
        RTINFO("initial check = %d\n", ret);
 
@@ -1121,18 +1236,19 @@ static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi)
 }
 
 static void rt5025_register_init(struct rt5025_battery_info *bi)
-{  
+{
        u8 data[1];
-       
+
        /* enable the channel of current,qc,ain,vbat and vadc */
-       if (rt5025_read_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+       if (rt5025_read_reg(bi->client, RT5025_REG_CHANNELL, data, 1) < 0)
                pr_err("%s: failed to read channel\n", __func__);
-       }
+
+       RTINFO("initial change enable=%02x\n", data[0]);
        data[0] = data[0] | CHANNEL_L_BIT_CADC_EN | CHANNEL_L_BIT_AINCH | \
-               CHANNEL_L_BIT_VBATSCH | CHANNEL_L_BIT_VADC_EN;
-       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+               CHANNEL_L_BIT_VBATSCH | CHANNEL_L_BIT_VADC_EN | CHANNEL_L_BIT_INTEMPCH;
+       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNELL, data, 1) < 0)
                pr_err("%s: failed to write channel\n", __func__);
-       }
+
        /* set the alert threshold value */
        irq_thres[MINVOLT2] = VALRTMIN2_VALUE;
        irq_thres[VOLT_RLS] = VRLS_VALUE;
@@ -1141,9 +1257,10 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
        bi->dchg_cc_unuse = 0;
        bi->pre_gauge_timer = 0;
        bi->online = 1;
+       bi->batt_present = 1;
        bi->status = bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
        bi->health = POWER_SUPPLY_HEALTH_GOOD;
-       
+
        bi->init_cap = true;
        bi->avg_flag = true;
 
@@ -1159,18 +1276,24 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
 
        bi->tp_cnt = 0;
        bi->tp_flag = false;
-  
+
        bi->acc_dchg_cap = 0;
        bi->cycle_cnt = 0;
+       bi->empty_edv = rt5025_battery_param2[4].x;
+       bi->edv_region = 0;
+       bi->soc1_lock_cnt = 0;
+       /*eoc fcc update function: initial variable.  */
+       bi->cal_eoc_fcc = 0;
+       bi->cal_soc_offset = 0;
+
 
-       // if has initial data, rewrite to the stored data
-       if (rt5025_battery_parameter_initcheck(bi))
-       {
+       /*if has initial data, rewrite to the stored data*/
+       if (rt5025_battery_parameter_initcheck(bi)) {
                bi->init_cap = false;
                rt5025_battery_parameter_restore(bi);
-               bi->soc = bi->rm/36/bi->fcc_aging;
+               bi->rm = bi->permille*bi->fcc_aging * 36 / 10;
        }
-  
+
        bi->update_time = NORMAL_POLL;
        bi->device_suspend = false;
        RTINFO("register initialized\n");
@@ -1178,337 +1301,393 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
 
 static void rt5025_soc_aging(struct rt5025_battery_info *bi)
 {
-       if (bi->cycle_cnt >= rt5025_battery_param2[3].x)
-       {
-               bi->fcc_aging = bi->fcc_aging*(1000-rt5025_battery_param2[3].y)/1000;
-               bi->rm = bi->rm*(1000-rt5025_battery_param2[3].y)/1000;
+       if (bi->cycle_cnt >= rt5025_battery_param2[3].x) {
+               bi->fcc_aging = bi->fcc_aging * (1000 - rt5025_battery_param2[3].y) / 1000;
+               bi->rm = bi->rm * (1000 - rt5025_battery_param2[3].y) / 1000;
                bi->cycle_cnt -= rt5025_battery_param2[3].x;
        }
-       RTINFO("fcc_aging=%d, rm=%d, cycle_cnt=%d\n", bi->fcc_aging, bi->rm, bi->cycle_cnt);
+       RTINFO("fcc_aging=%d, rm=%d, cycle_cnt=%d\n",
+               bi->fcc_aging, bi->rm, bi->cycle_cnt);
 }
 
 static void rt5025_temp_comp(struct rt5025_battery_info *bi)
 {
        int i = 1;
-  int size;
-  int slope, const_term;
-  int delta_y, delta_x;        
-  
-  size = 3;
-  while((bi->ext_temp < rt5025_battery_param2[i].x) &&
-                               (i < (size - 1))){
-    i++;
-  }
+       int size;
+       int slope, const_term;
+       int delta_y, delta_x;
+
+       size = 3;
+       while ((bi->ext_temp < rt5025_battery_param2[i].x) &&
+                               (i < (size - 1))) {
+               i++;
+       }
+
+       delta_x = rt5025_battery_param2[i-1].x - rt5025_battery_param2[i].x;
+       delta_y = (rt5025_battery_param2[i-1].y - rt5025_battery_param2[i].y);
+
+       slope = delta_y  * 1000 / delta_x;
 
-  delta_x = rt5025_battery_param2[i-1].x - rt5025_battery_param2[i].x;
-  delta_y = (rt5025_battery_param2[i-1].y - rt5025_battery_param2[i].y);
-
-  slope = delta_y  * 1000 / delta_x;
-
-  const_term = (rt5025_battery_param2[i].y) - ((rt5025_battery_param2[i].x * slope) / 1000);
-
-  if (bi->ext_temp >= rt5025_battery_param2[0].x)
-    bi->tempcmp = rt5025_battery_param2[0].y; 
-  else if (bi->ext_temp <= rt5025_battery_param2[size-1].x)
-    bi->tempcmp = rt5025_battery_param2[size-1].y;
-  else
-    bi->tempcmp = (bi->ext_temp * slope) / 1000 + const_term;
-       
-  bi->fcc = bi->fcc_aging + bi->fcc_aging * bi->tempcmp /1000;
-  if (bi->fcc >= (bi->dc*3>>1))
-       bi->fcc = bi->dc*3>>1;
-  if (bi->fcc <= (bi->dc>>1))
-       bi->fcc = bi->dc>>1;
-  bi->rm = bi->fcc * bi->soc * 36;
-  //pr_err("[rt5025] i=%d, delta_x=%d, delta_y=%d, slope=%d, const_term=%d\n", i, delta_x, delta_y, slope, const_term);
-  RTINFO("tempcmp=%d, ext_temp=%d, fcc=%d, rm=%d\n", bi->tempcmp, bi->ext_temp, bi->fcc, bi->rm);
-  return;              
+       const_term = (rt5025_battery_param2[i].y) - ((rt5025_battery_param2[i].x * slope) / 1000);
+
+       if (bi->ext_temp >= rt5025_battery_param2[0].x)
+               bi->tempcmp = rt5025_battery_param2[0].y;
+       else if (bi->ext_temp <= rt5025_battery_param2[size-1].x)
+               bi->tempcmp = rt5025_battery_param2[size-1].y;
+       else
+               bi->tempcmp = (bi->ext_temp * slope) / 1000 + const_term;
+
+       bi->fcc = bi->fcc_aging + bi->fcc_aging * bi->tempcmp  / 1000;
+       if (bi->fcc >= (bi->dc*3>>1))
+               bi->fcc = bi->dc*3>>1;
+       if (bi->fcc <= (bi->dc>>1))
+               bi->fcc = bi->dc>>1;
+       bi->rm = bi->fcc * bi->permille * 36 / 10;
+       RTINFO("tempcmp=%d, ext_temp=%d, fcc=%d, rm=%d\n",
+               bi->tempcmp, bi->ext_temp, bi->fcc, bi->rm);
+       /*return;       */
 }
 
 static void rt5025_soc_temp_comp(struct rt5025_battery_info *bi)
 {
-  RTINFO("soc->%d++\n", bi->soc);
-  bi->temp_range_0_5 = false;
-  bi->temp_range_5_10 = false;
-  bi->temp_range_10_15 = false;
-  bi->temp_range_15_20 = false;
-  bi->temp_range_20_30 = false; 
-  bi->temp_range_30_35 = false;
-  bi->temp_range_35_40 = false;
-  bi->temp_range_40_45 = false;
-  bi->temp_range_45_50 = false;
-  
-  if (bi->ext_temp < 50)
-       bi->temp_range_0_5 = true;
-  else if (50 <= bi->ext_temp && bi->ext_temp < 100)
-       bi->temp_range_5_10 = true;
-  else if (100 <= bi->ext_temp && bi->ext_temp < 150)
-       bi->temp_range_10_15 = true;
-  else if (150 <= bi->ext_temp && bi->ext_temp < 200)
-               bi->temp_range_15_20 = true;
-  else if (200 <= bi->ext_temp && bi->ext_temp <= 300)
-       bi->temp_range_20_30 = true;
-  else if (300 < bi->ext_temp && bi->ext_temp <= 350)
-       bi->temp_range_30_35 = true;
-  else if (350 < bi->ext_temp && bi->ext_temp <= 400)
-       bi->temp_range_35_40 = true;
-  else if (400 < bi->ext_temp && bi->ext_temp <= 450)
-       bi->temp_range_40_45 = true;
-  else if (450 < bi->ext_temp)
-       bi->temp_range_45_50 = true;
-       
-  if((bi->temp_range_0_5 == true) && (bi->range_0_5_done == false))    
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = true;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }
-       else if((bi->temp_range_5_10 == true) && (bi->range_5_10_done == false))        
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = true;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }
-  else if((bi->temp_range_10_15 == true) && (bi->range_10_15_done == false))   
-  {
-    rt5025_temp_comp(bi);
-    bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = true;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }
-  else if((bi->temp_range_15_20 == true) && (bi->range_15_20_done == false))   
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = true;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }
-  else if((bi->temp_range_20_30 == true) && (bi->range_20_30_done == false))   
-  {
-       bi->fcc = bi->fcc_aging;
-       bi->rm = bi->fcc*bi->soc*36;
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = true;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }  
-  else if((bi->temp_range_30_35 == true) && (bi->range_30_35_done == false))   
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = true;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }  
-  else if((bi->temp_range_35_40 == true) && (bi->range_35_40_done == false))   
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = true;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = false;
-  }  
-  else if((bi->temp_range_40_45 == true) && (bi->range_40_45_done == false))   
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = true;
-       bi->range_45_50_done = false;
-  }  
-  else if((bi->temp_range_45_50 == true) && (bi->range_45_50_done == false))   
-  {
-       rt5025_temp_comp(bi);
-       bi->range_0_5_done = false;
-       bi->range_5_10_done = false;
-       bi->range_10_15_done = false;
-       bi->range_15_20_done = false;
-       bi->range_20_30_done = false;
-       bi->range_30_35_done = false;
-       bi->range_35_40_done = false;
-       bi->range_40_45_done = false;
-       bi->range_45_50_done = true;
-  } 
-  RTINFO("soc->%d--\n", bi->soc);
+       RTINFO("soc->%d++\n", bi->soc);
+       bi->temp_range_0_5 = 0;
+       bi->temp_range_5_10 = 0;
+       bi->temp_range_10_15 = 0;
+       bi->temp_range_15_20 = 0;
+       bi->temp_range_20_30 = 0;
+       bi->temp_range_30_35 = 0;
+       bi->temp_range_35_40 = 0;
+       bi->temp_range_40_45 = 0;
+       bi->temp_range_45_50 = 0;
+
+       if (bi->ext_temp < 50)
+               bi->temp_range_0_5 = 1;
+       else if (50 <= bi->ext_temp && bi->ext_temp < 100)
+               bi->temp_range_5_10 = 1;
+       else if (100 <= bi->ext_temp && bi->ext_temp < 150)
+               bi->temp_range_10_15 = 1;
+       else if (150 <= bi->ext_temp && bi->ext_temp < 200)
+                       bi->temp_range_15_20 = 1;
+       else if (200 <= bi->ext_temp && bi->ext_temp <= 300)
+               bi->temp_range_20_30 = 1;
+       else if (300 < bi->ext_temp && bi->ext_temp <= 350)
+               bi->temp_range_30_35 = 1;
+       else if (350 < bi->ext_temp && bi->ext_temp <= 400)
+               bi->temp_range_35_40 = 1;
+       else if (400 < bi->ext_temp && bi->ext_temp <= 450)
+               bi->temp_range_40_45 = 1;
+       else if (450 < bi->ext_temp)
+               bi->temp_range_45_50 = 1;
+
+       if ((bi->temp_range_0_5 == 1) && (bi->range_0_5_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 1;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_5_10 == 1)
+               && (bi->range_5_10_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 1;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_10_15 == 1)
+               && (bi->range_10_15_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 1;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_15_20 == 1)
+               && (bi->range_15_20_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 1;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_20_30 == 1)
+               && (bi->range_20_30_done == 0)) {
+               bi->fcc = bi->fcc_aging;
+               bi->rm = bi->fcc * bi->permille * 36 / 10;
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 1;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_30_35 == 1)
+               && (bi->range_30_35_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 1;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_35_40 == 1)
+               && (bi->range_35_40_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 1;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_40_45 == 1)
+               && (bi->range_40_45_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 1;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_45_50 == 1)
+               && (bi->range_45_50_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 1;
+       }
+       RTINFO("soc->%d--\n", bi->soc);
 }
 
 static void rt5025_update(struct rt5025_battery_info *bi)
 {
-  /* Update voltage */
-  rt5025_get_vcell(bi);
-  /* Update current */
-  rt5025_get_current(bi);
-       
-  /* Update external temperature */
-  rt5025_get_external_temp(bi);
-  /* Read timer */
-  rt5025_get_timer(bi);
-  /* Update chg cc */
-  rt5025_get_chg_cc(bi);
-  /* Update dchg cc */
-  rt5025_get_dchg_cc(bi);
-  /* Update cycle count check */
-  rt5025_cycle_count(bi);
-  /* Calculate cycle count */
-  rt5025_soc_aging(bi);
-  /* calculate initial soc */
-  if (bi->init_cap){  
-    rt5025_init_capacity(bi);
-#if RT5025_CSV
-    pr_info("vcell,offset,current,timer,interval,QCHG,QDCHG,tp_cnt,tp_flag,edv_det,edv_cnt,edv_flag,soc,permille,RM,FCC,smooth_flag,acc_QD,cycle,update_time\n");
-#endif
-  }
+       int batt_type = 1;
+       /* Update voltage */
+       rt5025_get_vcell(bi);
+       /* Update current */
+       rt5025_get_current(bi);
+       /* Update internal temperature */
+       rt5025_get_internal_temp(bi);
+       /* Update external temperature */
+       rt5025_get_external_temp(bi);
+       /* Read timer */
+       rt5025_get_timer(bi);
+       /* Update chg cc */
+       rt5025_get_chg_cc(bi);
+       /* Update dchg cc */
+       rt5025_get_dchg_cc(bi);
+       /* Update cycle count check */
+       rt5025_cycle_count(bi);
+       /* Calculate cycle count */
+       rt5025_soc_aging(bi);
+       /* calculate initial soc */
+       if (bi->init_cap) {
+               rt5025_init_capacity(bi);
+               #if RT5025_CSV
+               pr_info("vcell,offset,current,timer,interval,QCHG,QDCHG,tp_cnt,tp_flag,edv_det,edv_cnt,edv_flag,soc,permille,RM,FCC,smooth_flag,acc_QD,cycle,update_time\n");
+               #endif
+       }
 
        /* Relearn SOC */
        rt5025_soc_relearn_check(bi);
        /* SOC_Temp_Comp*/
        rt5025_soc_temp_comp(bi);
-  /* Update SOC */
-  rt5025_get_soc(bi);
-  
-  /* SOC Control Process */
-  rt5025_soc_lock(bi);
-  rt5025_soc_irreversible(bi);
-  
-  /* Update RTTF or RTTE */
-  //rt5025_run_time(bi);
-       
-#if TEMPERATURE_ALERT 
-  if ((bi->max_temp_irq == false) &&
-                 (((irq_thres[MAXTEMP] * IRQ_THRES_UNIT) / 100 - bi->ain_volt) > irq_thres[TEMP_RLS])){
-               rt5025_alert_setting(bi,MAXTEMP,true);
-       }else if ((bi->min_temp_irq == false) &&
-                                         ((bi->ain_volt - (irq_thres[MINTEMP] * IRQ_THRES_UNIT) / 100) > irq_thres[TEMP_RLS])){
-               rt5025_alert_setting(bi,MINTEMP,true);
-  }
-#endif  
-#if 0          
-       }else if ((bi->min_volt1_irq == false) &&
-                                       ((bi->vcell - ((irq_thres[MINVOLT1] * IRQ_THRES_UNIT) / 100)) > irq_thres[VOLT_RLS])){
-               rt5025_alert_setting(bi,MINVOLT1,true);                         
-       }else if ((bi->min_volt2_irq == false) &&
-                                       ((bi->vcell - ((irq_thres[MINVOLT2] * IRQ_THRES_UNIT) / 100)) > irq_thres[VOLT_RLS])){
-               rt5025_alert_setting(bi,MINVOLT2,true);                                         
+       /* Update SOC */
+       rt5025_get_soc(bi);
+
+       /* SOC Control Process */
+       rt5025_soc_lock(bi);
+       rt5025_soc_irreversible(bi);
+
+       if (bi->soc <= 99)
+               bi->last_tp = false;
+
+       if (rt5025_battery_param1[0].x >= 4250)
+               batt_type = 0;
+       else if (rt5025_battery_param1[0].x >= 4100)
+               batt_type = 1;
+
+       switch (batt_type) {
+       case 0:
+                       if ((bi->vcell >= 4250) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING))
+                               wake_lock(&bi->full_battery_wake_lock);
+                       else
+                               wake_unlock(&bi->full_battery_wake_lock);
+               break;
+       case 1:
+       default:
+                       if ((bi->vcell >= 4100) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING))
+                               wake_lock(&bi->full_battery_wake_lock);
+                       else
+                               wake_unlock(&bi->full_battery_wake_lock);
+               break;
+       }
+
+       /* Update RTTF or RTTE */
+
+#if TEMPERATURE_ALERT
+       if ((bi->max_temp_irq == false) &&
+                 (((irq_thres[MAXTEMP] * IRQ_THRES_UNIT) / 100 - bi->ain_volt) > irq_thres[TEMP_RLS])) {
+               rt5025_alert_setting(bi, MAXTEMP, true);
+       } else if ((bi->min_temp_irq == false) &&
+                                         ((bi->ain_volt - (irq_thres[MINTEMP] * IRQ_THRES_UNIT) / 100) > irq_thres[TEMP_RLS])) {
+               rt5025_alert_setting(bi, MINTEMP, true);
        }
 #endif
-       
+
 #if VOLTAGE_ALERT
        if ((bi->min_volt2_irq == false) &&
-                               (bi->vcell > (rt5025_battery_param2[4].x + EDV_HYS))){  
-               rt5025_alert_setting(bi,MINVOLT2,true);                                         
-       }
+               (bi->vcell > (bi->empty_edv + EDV_HYS)))
+               rt5025_alert_setting(bi, MINVOLT2, true);
 #endif
+       bi->last_suspend = false;
 #if RT5025_CSV
-  printk(KERN_INFO "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",bi->vcell,bi->curr_offset,bi->curr,bi->gauge_timer,bi->time_interval,bi->chg_cc,
-               bi->dchg_cc,bi->tp_cnt,bi->tp_flag,bi->edv_detection,bi->edv_cnt,bi->edv_flag,bi->soc,
-               bi->permille,bi->rm,bi->fcc,bi->smooth_flag,bi->acc_dchg_cap,bi->cycle_cnt,bi->update_time);
+       printk(KERN_INFO "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+       bi->vcell, bi->curr_offset, bi->curr, bi->gauge_timer,
+       bi->time_interval, bi->chg_cc, bi->dchg_cc,
+       bi->tp_cnt, bi->tp_flag, bi->edv_detection,
+       bi->edv_cnt, bi->edv_flag, bi->soc, bi->permille,
+       bi->rm, bi->fcc, bi->smooth_flag, bi->acc_dchg_cap,
+       bi->cycle_cnt, bi->update_time);
 #else
-  pr_info("[RT5025] update_time=%d\n",bi->update_time);
-  pr_info("\n");
+       RTINFO("[RT5025] update_time=%d\n", bi->update_time);
+       RTINFO("\n");
 #endif
 }
 
 static void rt5025_update_work(struct work_struct *work)
 {
-       struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
-       struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(delayed_work, struct rt5025_battery_info, monitor_work);
-       unsigned long flags;
-       
-  rt5025_update(bi);
-  
-       /* prevent suspend before starting the alarm */
-       local_irq_save(flags);
-       bi->last_poll = alarm_get_elapsed_realtime();
-       rt5025_program_alarm(bi);
-       local_irq_restore(flags);
+       struct delayed_work *delayed_work = (struct delayed_work *)container_of(work,
+               struct delayed_work, work);
+       struct rt5025_battery_info *bi = (struct rt5025_battery_info *)container_of(delayed_work,
+               struct rt5025_battery_info, monitor_work);
+
+       wake_lock(&bi->monitor_wake_lock);
+       rt5025_update(bi);
+       if (bi->soc != bi->last_soc) {
+               power_supply_changed(&bi->battery);
+               bi->last_soc = bi->soc;
+       }
 
        wake_unlock(&bi->monitor_wake_lock);
+       if (!bi->device_suspend)
+               schedule_delayed_work(&bi->monitor_work, bi->update_time*HZ);
 }
 
 static enum power_supply_property rt5025_battery_props[] = {
-  POWER_SUPPLY_PROP_STATUS,
-  POWER_SUPPLY_PROP_HEALTH,
-  POWER_SUPPLY_PROP_PRESENT,
-  POWER_SUPPLY_PROP_TEMP,
-  POWER_SUPPLY_PROP_ONLINE,
-  POWER_SUPPLY_PROP_VOLTAGE_NOW,
-  POWER_SUPPLY_PROP_CURRENT_NOW,
-  POWER_SUPPLY_PROP_CAPACITY,
-  POWER_SUPPLY_PROP_TECHNOLOGY,
-  #if 0
-  POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
-  POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
-  #endif
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_TEMP_AMBIENT,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+#if 0
+       POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+       POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+#endif
 };
 
-static int rt5025_battery_suspend(struct platform_device *pdev, pm_message_t state)
+static int rt5025_battery_sleepvth_setting(struct rt5025_battery_info *bi)
+{
+       u32 temp;
+       u8 vmax_th, vmin_th;
+       u8 vbat[2];
+
+       RTINFO("\n");
+       rt5025_read_reg(bi->client, RT5025_REG_VBATSH, vbat, 2);
+       temp = ((vbat[0] << 8) + vbat[1]) * 61;
+       vmax_th = (temp + 5000) / 1953;
+       vmin_th = (temp - 5000) / 1953;
+
+       rt5025_write_reg(bi->client, RT5025_REG_VALRTMAX, &vmax_th, 1);
+       rt5025_write_reg(bi->client, RT5025_REG_VALRTMIN1, &vmin_th, 1);
+
+       RTINFO("vmax_th=0x%02x, vmin_th=0x%02x\n", vmax_th, vmin_th);
+       return 0;
+}
+
+static int rt5025_gauge_reginit(struct i2c_client *client)
+{
+       rt5025_reg_block_write(client, RT5025_REG_VALRTMAX,
+               5, gauge_init_regval);
+       rt5025_reg_write(client, RT5025_REG_IRQCTL, 0x00);
+       rt5025_reg_read(client, RT5025_REG_IRQFLG);
+       RTINFO("\n");
+       return 0;
+}
+
+static int rt5025_battery_suspend(struct platform_device *pdev,
+       pm_message_t state)
 {
        struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
-       //bi->last_event = ktime_get();
+
+       RTINFO("\n");
+       /*rt5025_get_timer(bi);*/
+       /*bi->last_event = ktime_get();*/
        bi->last_event = current_kernel_time();
 
-       //cy add for battery parameter backup
-       rt5025_battery_parameter_backup(bi);
+       /*cy add for battery parameter backup
+       //rt5025_battery_parameter_backup(bi);
 
-       rt5025_channel_cc(bi, false);
-       cancel_delayed_work(&bi->monitor_work);
-       rt5025_get_timer(bi);
+       //rt5025_channel_cc(bi, false);
+       //rt5025_update(bi);*/
        bi->device_suspend = true;
-       //bi->update_time = SUSPEND_POLL;
-       RTINFO("RM=%d\n",bi->rm);
+       cancel_delayed_work_sync(&bi->monitor_work);
+       /* prevent suspend before starting the alarm */
+       /*bi->update_time = SUSPEND_POLL;*/
+       rt5025_alert_setting(bi, MAXVOLT, false);
+       rt5025_alert_setting(bi, MINVOLT1, false);
+       rt5025_battery_sleepvth_setting(bi);
+       if (bi->status == POWER_SUPPLY_STATUS_CHARGING)
+               rt5025_alert_setting(bi, MAXVOLT, true);
+       else if (bi->status == POWER_SUPPLY_STATUS_DISCHARGING)
+               rt5025_alert_setting(bi, MINVOLT1, true);
+       RTINFO("RM=%d\n", bi->rm);
        return 0;
 }
 
 static int rt5025_battery_resume(struct platform_device *pdev)
 {
        struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
-       //ktime_t now;
+
+       /*ktime_t now;
        //struct timespec now = current_kernel_time();
        //struct timeval tv;
        //long time_interval;
@@ -1520,13 +1699,13 @@ static int rt5025_battery_resume(struct platform_device *pdev)
 
        //time_interval = now.tv_sec - bi->last_event.tv_sec;
        //bi->rm = bi->rm - (time_interval * SLEEP_CURRENT);
-       //RTINFO("Sleep time=%d, RM=%d",(int)time_interval,bi->rm);  
+       //RTINFO("Sleep time=%d, RM=%d",(int)time_interval,bi->rm);
 
-       rt5025_channel_cc(bi, true);
-       wake_lock(&bi->monitor_wake_lock);
-       schedule_delayed_work(&bi->monitor_work, 0);
+       //rt5025_channel_cc(bi, true);*/
+       bi->last_suspend = true;
        bi->device_suspend = false;
-       //RTINFO("\n");
+       schedule_delayed_work(&bi->monitor_work, 0);
+       RTINFO("\n");
        return 0;
 }
 
@@ -1538,6 +1717,7 @@ static int rt5025_battery_remove(struct platform_device *pdev)
        cancel_delayed_work(&bi->monitor_work);
        wake_lock_destroy(&bi->monitor_wake_lock);
        kfree(bi);
+       RTINFO("\n");
        return 0;
 }
 
@@ -1547,32 +1727,38 @@ static int rt5025_battery_probe(struct platform_device *pdev)
        struct rt5025_battery_info *bi;
        int ret;
 
-       bi = kzalloc(sizeof(*bi), GFP_KERNEL);
-       if (!bi)
-               return -ENOMEM;
-   
-       bi->client = chip->i2c;
-       bi->chip = chip;
-
+       bi = devm_kzalloc(&pdev->dev, sizeof(*bi), GFP_KERNEL);
+       if (!bi)
+               return -ENOMEM;
 
-       bi->last_poll = alarm_get_elapsed_realtime();
-       alarm_init(&bi->wakeup_alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
-               rt5025_gauge_alarm);
+       bi->client = chip->i2c;
 
        INIT_DELAYED_WORK(&bi->monitor_work, rt5025_update_work);
-       
-       wake_lock_init(&bi->monitor_wake_lock, WAKE_LOCK_SUSPEND, "rt-battery-monitor");
-       wake_lock_init(&bi->low_battery_wake_lock, WAKE_LOCK_SUSPEND, "low_battery_wake_lock");
+
+       wake_lock_init(&bi->monitor_wake_lock,
+               WAKE_LOCK_SUSPEND, "rt-battery-monitor");
+       wake_lock_init(&bi->low_battery_wake_lock,
+               WAKE_LOCK_SUSPEND, "low_battery_wake_lock");
+       wake_lock_init(&bi->status_wake_lock,
+               WAKE_LOCK_SUSPEND, "battery-status-changed");
+       wake_lock_init(&bi->smooth100_wake_lock,
+               WAKE_LOCK_SUSPEND, "smooth100_soc_wake_lock");
+       wake_lock_init(&bi->smooth0_wake_lock,
+               WAKE_LOCK_SUSPEND, "smooth0_soc_wake_lock");
+       wake_lock_init(&bi->full_battery_wake_lock,
+               WAKE_LOCK_SUSPEND, "full_battery_wake_lock");
 #if RT5025_TEST_WAKE_LOCK
        wake_lock_init(&bi->test_wake_lock, WAKE_LOCK_SUSPEND, "rt-test");
 #endif
-       /* Write trimed data */
-       //rt5025_pretrim(client);
+       mutex_init(&bi->status_change_lock);
+       /* Write trimed data */
+       /*rt5025_pretrim(client);*/
+       rt5025_gauge_reginit(bi->client);
        /* enable channel */
        rt5025_register_init(bi);
        /* enable gauge IRQ */
        rt5025_alert_init(bi);
-  
+
        /* register callback functions */
        /*
        chip->cb.rt5025_gauge_irq_handler = rt5025_irq_handler;
@@ -1581,40 +1767,36 @@ static int rt5025_battery_probe(struct platform_device *pdev)
        chip->cb.rt5025_gauge_suspend = rt5025_gauge_suspend;
        chip->cb.rt5025_gauge_resume = rt5025_gauge_resume;
        chip->cb.rt5025_gauge_remove = rt5025_gauge_remove;
-       
        rt5025_register_gauge_callbacks(&chip->cb);
        */
 
        platform_set_drvdata(pdev, bi);
 
-       bi->battery.name = "rt5025-battery";
+       bi->battery.name = RT_BATT_NAME;
        bi->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       bi->battery.set_property = rt5025_set_property;
        bi->battery.get_property = rt5025_get_property;
        bi->battery.properties = rt5025_battery_props;
        bi->battery.num_properties = ARRAY_SIZE(rt5025_battery_props);
-  
+
        ret = power_supply_register(&pdev->dev, &bi->battery);
        if (ret) {
-               printk(KERN_ERR "[RT5025] power supply register failed\n");
+               pr_err("[RT5025] power supply register failed\n");
                goto err_wake_lock;
        }
-  
 
-       wake_lock(&bi->monitor_wake_lock);
+       /*wake_lock(&bi->monitor_wake_lock);*/
 #if RT5025_TEST_WAKE_LOCK
        wake_lock(&bi->test_wake_lock);
 #endif
-       schedule_delayed_work(&bi->monitor_work, msecs_to_jiffies(INIT_POLL*MSEC_PER_SEC));
+       schedule_delayed_work(&bi->monitor_work, INIT_POLL*HZ);
        chip->battery_info = bi;
 
        pr_info("rt5025-battery driver is successfully loaded\n");
-       
-  return 0;
 
+       return 0;
 err_wake_lock:
        wake_lock_destroy(&bi->monitor_wake_lock);
-       kfree(bi);
-
        return ret;
 }
 
@@ -1623,36 +1805,58 @@ static void rt5025_battery_shutdown(struct platform_device *pdev)
        struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
 
        RTINFO("\n");
+       if (bi->soc == 0 && bi->cal_fcc != 0) {
+               /*d. FCC update limitation +/-3%; 2013/12/27
+               //bi->fcc_aging = bi->cal_fcc/3600 - (bi->fcc -bi->fcc_aging);*/
+               u16 fcc_new  = 0;
+
+               fcc_new = bi->cal_fcc / 3600 - (bi->fcc - bi->fcc_aging);
+               if (fcc_new > ((bi->fcc_aging * 103) / 100))
+                       bi->fcc_aging = (bi->fcc_aging * 103) / 100;
+               else if (fcc_new < ((bi->fcc_aging * 97) / 100))
+                       bi->fcc_aging = (bi->fcc_aging * 97) / 100;
+               else
+                       bi->fcc_aging = fcc_new;
+
+               RTINFO("bi->cal_fcc=%d\n", bi->cal_fcc);
+       }
        rt5025_battery_parameter_backup(bi);
+       RTINFO("\n");
 }
 
-static struct platform_driver rt5025_battery_driver = 
-{
+static struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-battery",},
+       {},
+};
+
+static struct platform_driver rt5025_battery_driver = {
        .driver = {
-               .name = RT5025_DEVICE_NAME "-battery",
+               .name = RT5025_DEV_NAME "-battery",
                .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe = rt5025_battery_probe,
-       .remove = __devexit_p(rt5025_battery_remove),
+       .remove = rt5025_battery_remove,
        .shutdown = rt5025_battery_shutdown,
        .suspend = rt5025_battery_suspend,
        .resume = rt5025_battery_resume,
 };
 
-static int __init rt5025_battery_init(void)
+static int rt5025_battery_init(void)
 {
        return platform_driver_register(&rt5025_battery_driver);
 }
-module_init(rt5025_battery_init);
+fs_initcall_sync(rt5025_battery_init);
 
-static void __exit rt5025_battery_exit(void)
+static void rt5025_battery_exit(void)
 {
        platform_driver_unregister(&rt5025_battery_driver);
 }
 module_exit(rt5025_battery_exit);
 
 
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Nick Hung <nick_hung@richtek.com");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nick Hung <nick_hung@richtek.com>");
 MODULE_DESCRIPTION("battery gauge driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-battery");
+MODULE_ALIAS("platform:" RT5025_DEV_NAME "-battery");
+MODULE_VERSION(RT5025_DRV_VER);