PCI: rockchip: fix wrong clr for phy interrupt
[firefly-linux-kernel-4.4.55.git] / drivers / power / ricoh619-battery.c
old mode 100644 (file)
new mode 100755 (executable)
index 2a01c4f..24e840a
@@ -19,6 +19,9 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
+#define RICOH619_BATTERY_VERSION "RICOH619_BATTERY_VERSION: 2014.05.06"
+
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/power/ricoh61x_battery_init.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <mach/board.h>
-
+#include <linux/of.h>
+#include <linux/rtc.h>
 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 
 /* define for function */
 #define ENABLE_FUEL_GAUGE_FUNCTION
 #define ENABLE_LOW_BATTERY_DETECTION
-#define ENABLE_FACTORY_MODE
+//#define ENABLE_FACTORY_MODE
 #define DISABLE_CHARGER_TIMER
 /* #define ENABLE_FG_KEEP_ON_MODE */
-
+/* #define ENABLE_OCV_TABLE_CALIB */
+//#define SUPPORT_USB_CONNECT_TO_ADP
 
 
 /* FG setting */
@@ -71,16 +75,27 @@ enum int_type {
 #define RICOH619_CHARGE_RESUME_TIME            1
 #define RICOH619_CHARGE_CALC_TIME              1
 #define RICOH619_JEITA_UPDATE_TIME             60
+#define RICOH619_DELAY_TIME                            60
 /* define for FG parameter */
 #define RICOH619_MAX_RESET_SOC_DIFF            5
 #define RICOH619_GET_CHARGE_NUM                10
 #define RICOH619_UPDATE_COUNT_DISP             4
 #define RICOH619_UPDATE_COUNT_FULL             4
+#define RICOH619_UPDATE_COUNT_FULL_RESET       7
 #define RICOH619_CHARGE_UPDATE_TIME            3
+#define RICOH619_FULL_WAIT_TIME                        4
 #define RE_CAP_GO_DOWN                         10      /* 40 */
 #define RICOH619_ENTER_LOW_VOL                 70
-#define RICOH619_TAH_SEL2                              5
-#define RICOH619_TAL_SEL2                              6
+#define RICOH619_TAH_SEL2                      5
+#define RICOH619_TAL_SEL2                      6
+
+#define RICOH619_OCV_OFFSET_BOUND      3
+#define RICOH619_OCV_OFFSET_RATIO      2
+
+#define RICOH619_VADP_DROP_WORK
+#define RICOH619_TIME_CHG_STEP (1*HZ)// unit:secound
+#define RICOH619_TIME_CHG_COUNT        15*60//only for test //15*60 
+
 /* define for FG status */
 enum {
        RICOH619_SOCA_START,
@@ -101,7 +116,9 @@ enum {
 struct ricoh619_soca_info {
        int Rbat;
        int n_cap;
+       int ocv_table_def[11];
        int ocv_table[11];
+       int ocv_table_low[11];
        int soc;                /* Latest FG SOC value */
        int displayed_soc;
        int suspend_soc;
@@ -110,31 +127,41 @@ struct ricoh619_soca_info {
        int chg_status;         /* chg_status */
        int soc_delta;          /* soc delta for status3(DISP) */
        int cc_delta;
+       int cc_cap_offset;
        int last_soc;
+       int last_displayed_soc;
        int ready_fg;
        int reset_count;
        int reset_soc[3];
-       int reset_flg_90;
-       int reset_flg_95;
-       int f_chg_margin;
+       int chg_cmp_times;
        int dischg_state;
        int Vbat[RICOH619_GET_CHARGE_NUM];
        int Vsys[RICOH619_GET_CHARGE_NUM];
        int Ibat[RICOH619_GET_CHARGE_NUM];
        int Vbat_ave;
+       int Vbat_old;
        int Vsys_ave;
        int Ibat_ave;
        int chg_count;
-       int update_count;
+       int full_reset_count;
+       int soc_full;
+       int fc_cap;
        /* for LOW VOL state */
        int target_use_cap;
        int hurry_up_flg;
+       int zero_flg;
        int re_cap_old;
        int cutoff_ocv;
        int Rsys;
        int target_vsys;
        int target_ibat;
        int jt_limit;
+       int OCV100_min;
+       int OCV100_max;
+       int R_low;
+       int rsoc_ready_flag;
+       int init_pswr;
+       int last_cc_sum;
 };
 
 struct ricoh619_battery_info {
@@ -150,10 +177,13 @@ struct ricoh619_battery_info {
        struct delayed_work     charge_monitor_work;
        struct delayed_work     get_charge_work;
        struct delayed_work     jeita_work;
+       struct delayed_work     charge_complete_ready;
 
        struct work_struct      irq_work;       /* for Charging & VUSB/VADP */
        struct work_struct      usb_irq_work;   /* for ADC_VUSB */
-
+       #ifdef RICOH619_VADP_DROP_WORK
+       struct delayed_work     vadp_drop_work;
+       #endif
        struct workqueue_struct *monitor_wqueue;
        struct workqueue_struct *workqueue;     /* for Charging & VUSB/VADP */
        struct workqueue_struct *usb_workqueue; /* for ADC_VUSB */
@@ -192,6 +222,7 @@ struct ricoh619_battery_info {
        int             ch_icchg;
        int             fg_target_vsys;
        int             fg_target_ibat;
+       int             fg_poff_vbat;
        int             jt_en;
        int             jt_hw_sw;
        int             jt_temp_h;
@@ -201,17 +232,27 @@ struct ricoh619_battery_info {
        int             jt_ichg_h;
        int             jt_ichg_l;
 
+       int     chg_complete_rd_flag;
+       int     chg_complete_rd_cnt;
+       int             chg_complete_tm_ov_flag;
+       int             chg_complete_sleep_flag;
+       int             chg_old_dsoc;
+
        int             num;
        };
 
+struct power_supply powerac;
+struct power_supply powerusb;
+
+int g_full_flag;
 int charger_irq;
 /* this value is for mfd fucntion */
 int g_soc;
 int g_fg_on_mode;
-extern int dwc_vbus_status(void);
+int type_n;
+extern int dwc_otg_check_dpdm(bool wait);
 /*This is for full state*/
-int g_full_flag;
-static int BatteryTableFlageDef=0;
+static int BatteryTableFlagDef=0;
 static int BatteryTypeDef=0;
 static int Battery_Type(void)
 {
@@ -220,7 +261,7 @@ static int Battery_Type(void)
 
 static int Battery_Table(void)
 {
-       return BatteryTableFlageDef;
+       return BatteryTableFlagDef;
 }
 
 static void ricoh619_battery_work(struct work_struct *work)
@@ -238,19 +279,24 @@ static void ricoh619_battery_work(struct work_struct *work)
 static int measure_vbatt_FG(struct ricoh619_battery_info *info, int *data);
 static int measure_Ibatt_FG(struct ricoh619_battery_info *info, int *data);
 static int calc_capacity(struct ricoh619_battery_info *info);
+static int calc_capacity_2(struct ricoh619_battery_info *info);
 static int get_OCV_init_Data(struct ricoh619_battery_info *info, int index);
 static int get_OCV_voltage(struct ricoh619_battery_info *info, int index);
 static int get_check_fuel_gauge_reg(struct ricoh619_battery_info *info,
                                         int Reg_h, int Reg_l, int enable_bit);
 static int calc_capacity_in_period(struct ricoh619_battery_info *info,
-                                        int *cc_cap, bool *is_charging);
-static int get_charge_priority(struct ricoh619_battery_info *info, bool *data);
-static int set_charge_priority(struct ricoh619_battery_info *info, bool *data);
+                                int *cc_cap, bool *is_charging, bool cc_rst);
+//static int get_charge_priority(struct ricoh619_battery_info *info, bool *data);
+//static int set_charge_priority(struct ricoh619_battery_info *info, bool *data);
 static int get_power_supply_status(struct ricoh619_battery_info *info);
+static int get_power_supply_Android_status(struct ricoh619_battery_info *info);
 static int measure_vsys_ADC(struct ricoh619_battery_info *info, int *data);
 static int Calc_Linear_Interpolation(int x0, int y0, int x1, int y1, int y);
 static int get_battery_temp(struct ricoh619_battery_info *info);
+static int get_battery_temp_2(struct ricoh619_battery_info *info);
 static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita_updated);
+static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per);
+//static int ricoh619_Check_OCV_Offset(struct ricoh619_battery_info *info);
 
 static int calc_ocv(struct ricoh619_battery_info *info)
 {
@@ -267,18 +313,214 @@ static int calc_ocv(struct ricoh619_battery_info *info)
        return ocv;
 }
 
+#if 0
+static int set_Rlow(struct ricoh619_battery_info *info)
+{
+       int err;
+       int Rbat_low_max;
+       uint8_t val;
+       int Vocv;
+       int temp;
+
+       if (info->soca->Rbat == 0)
+                       info->soca->Rbat = get_OCV_init_Data(info, 12) * 1000 / 512
+                                                        * 5000 / 4095;
+       
+       Vocv = calc_ocv(info);
+       Rbat_low_max = info->soca->Rbat * 1.5;
+
+       if (Vocv < get_OCV_voltage(info,3))
+       {
+               info->soca->R_low = Calc_Linear_Interpolation(info->soca->Rbat,get_OCV_voltage(info,3),
+                       Rbat_low_max, get_OCV_voltage(info,0), Vocv);
+               RICOH_FG_DBG("PMU: Modify RBAT from %d to %d ", info->soca->Rbat, info->soca->R_low);
+               temp = info->soca->R_low *4095/5000*512/1000;
+               
+               val = info->soca->R_low>>8;
+               err = ricoh619_write_bank1(info->dev->parent, 0xD4, val);
+               if (err < 0) {
+                       dev_err(info->dev, "batterry initialize error\n");
+                       return err;
+               }
+
+               val = info->soca->R_low & 0xff;
+               err = ricoh619_write_bank1(info->dev->parent, 0xD5, val);
+               if (err < 0) {
+                       dev_err(info->dev, "batterry initialize error\n");
+                       return err;
+               }
+       }
+       else  info->soca->R_low = 0;
+               
+
+       return err;
+}
+
+static int Set_back_ocv_table(struct ricoh619_battery_info *info)
+{
+       int err;
+       uint8_t val;
+       int temp;
+       int i;
+       uint8_t debug_disp[22];
+
+       /* Modify back ocv table */
+
+       if (0 != info->soca->ocv_table_low[0])
+       {
+               for (i = 0 ; i < 11; i++){
+                       battery_init_para[info->num][i*2 + 1] = info->soca->ocv_table_low[i];
+                       battery_init_para[info->num][i*2] = info->soca->ocv_table_low[i] >> 8;
+               }
+               err = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+
+               err = ricoh619_bulk_writes_bank1(info->dev->parent,
+                       BAT_INIT_TOP_REG, 22, battery_init_para[info->num]);
+
+               err = ricoh619_set_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+
+               /* debug comment start*/
+               err = ricoh619_bulk_reads_bank1(info->dev->parent,
+                       BAT_INIT_TOP_REG, 22, debug_disp);
+               for (i = 0; i < 11; i++){
+                       RICOH_FG_DBG("PMU : %s : after OCV table %d 0x%x\n",__func__, i * 10, (debug_disp[i*2] << 8 | debug_disp[i*2+1]));
+               }
+               /* end */
+               /* clear table*/
+               for(i = 0; i < 11; i++)
+               {
+                       info->soca->ocv_table_low[i] = 0;
+               }
+       }
+       
+       /* Modify back Rbat */
+       if (0!=info->soca->R_low)
+       {               
+               RICOH_FG_DBG("PMU: Modify back RBAT from %d to %d ",  info->soca->R_low,info->soca->Rbat);
+               temp = info->soca->Rbat*4095/5000*512/1000;
+               
+               val = info->soca->R_low>>8;
+               err = ricoh619_write_bank1(info->dev->parent, 0xD4, val);
+               if (err < 0) {
+                       dev_err(info->dev, "batterry initialize error\n");
+                       return err;
+               }
+
+               val = info->soca->R_low & 0xff;
+               err = ricoh619_write_bank1(info->dev->parent, 0xD5, val);
+               if (err < 0) {
+                       dev_err(info->dev, "batterry initialize error\n");
+                       return err;
+               }
+
+               info->soca->R_low = 0;
+       }
+       return 0;
+}
+
+/**
+**/
+
+static int ricoh619_Check_OCV_Offset(struct ricoh619_battery_info *info)
+{
+       int ocv_table[11]; // HEX value
+       int i;
+       int temp;
+       int ret;
+       uint8_t debug_disp[22];
+       uint8_t val = 0;
+
+       RICOH_FG_DBG("PMU : %s : calc ocv %d get OCV %d\n",__func__,calc_ocv(info),get_OCV_voltage(info, RICOH619_OCV_OFFSET_BOUND));
+
+       /* check adp/usb status */
+       ret = ricoh619_read(info->dev->parent, CHGSTATE_REG, &val);
+       if (ret < 0) {
+               dev_err(info->dev, "Error in reading the control register\n");
+               return ret;
+       }
+
+       val = (val & 0xC0) >> 6;
+
+       if (val != 0){ /* connect adp or usb */
+               if (calc_ocv(info) < get_OCV_voltage(info, RICOH619_OCV_OFFSET_BOUND) )
+               {
+                       if(0 == info->soca->ocv_table_low[0]){
+                               for (i = 0 ; i < 11; i++){
+                               ocv_table[i] = (battery_init_para[info->num][i*2]<<8) | (battery_init_para[info->num][i*2+1]);
+                               RICOH_FG_DBG("PMU : %s : OCV table %d 0x%x\n",__func__,i * 10, ocv_table[i]);
+                               info->soca->ocv_table_low[i] = ocv_table[i];
+                               }
+
+                               for (i = 0 ; i < 11; i++){
+                                       temp = ocv_table[i] * (100 + RICOH619_OCV_OFFSET_RATIO) / 100;
+
+                                       battery_init_para[info->num][i*2 + 1] = temp;
+                                       battery_init_para[info->num][i*2] = temp >> 8;
+                               }
+                               ret = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+
+                               ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+                                       BAT_INIT_TOP_REG, 22, battery_init_para[info->num]);
+
+                               ret = ricoh619_set_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+
+                               /* debug comment start*/
+                               ret = ricoh619_bulk_reads_bank1(info->dev->parent,
+                                       BAT_INIT_TOP_REG, 22, debug_disp);
+                               for (i = 0; i < 11; i++){
+                                       RICOH_FG_DBG("PMU : %s : after OCV table %d 0x%x\n",__func__, i * 10, (debug_disp[i*2] << 8 | debug_disp[i*2+1]));
+                               }
+                               /* end */
+                       }
+               }
+       }
+       
+       return 0;
+}
+#endif
+static int reset_FG_process(struct ricoh619_battery_info *info)
+{
+       int err;
+
+       //err = set_Rlow(info);
+       //err = ricoh619_Check_OCV_Offset(info);
+       err = ricoh619_write(info->dev->parent,
+                                        FG_CTRL_REG, 0x51);
+       info->soca->ready_fg = 0;
+       return err;
+}
+
+
 static int check_charge_status_2(struct ricoh619_battery_info *info, int displayed_soc_temp)
 {
        if (displayed_soc_temp < 0)
                        displayed_soc_temp = 0;
        
        get_power_supply_status(info);
-       /* for issue 5 */
+       info->soca->soc = calc_capacity(info) * 100;
+
        if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) {
-               g_full_flag = 1;
-               info->soca->displayed_soc = 100*100;
+               if ((info->first_pwon == 1)
+                       && (RICOH619_SOCA_START == info->soca->status)) {
+                               g_full_flag = 1;
+                               info->soca->soc_full = info->soca->soc;
+                               info->soca->displayed_soc = 100*100;
+                               info->soca->full_reset_count = 0;
+               } else {
+                       if ( (displayed_soc_temp > 97*100)
+                               && (calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10)  )){
+                               g_full_flag = 1;
+                               info->soca->soc_full = info->soca->soc;
+                               info->soca->displayed_soc = 100*100;
+                               info->soca->full_reset_count = 0;
+                       } else {
+                               g_full_flag = 0;
+                               info->soca->displayed_soc = displayed_soc_temp;
+                       }
+
+               }
        }
-       if (info->soca->Ibat_ave >= 0) {        /* for issue 3 */
+       if (info->soca->Ibat_ave >= 0) {
                if (g_full_flag == 1) {
                        info->soca->displayed_soc = 100*100;
                } else {
@@ -291,10 +533,10 @@ static int check_charge_status_2(struct ricoh619_battery_info *info, int display
        }
        if (info->soca->Ibat_ave < 0) {
                if (g_full_flag == 1) {
-                       if ((calc_ocv(info) < (get_OCV_voltage(info, 10) - info->soca->f_chg_margin) )
-                       && (info->soca->soc/100 <= 98) ) {
+                       if (calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10)  ) {
                                g_full_flag = 0;
-                               info->soca->displayed_soc = 100*100;
+                               //info->soca->displayed_soc = 100*100;
+                               info->soca->displayed_soc = displayed_soc_temp;
                        } else {
                                info->soca->displayed_soc = 100*100;
                        }
@@ -315,20 +557,26 @@ static int check_charge_status_2(struct ricoh619_battery_info *info, int display
 * @is_charging: Flag of charging current direction
 *               TRUE : charging (plus)
 *               FALSE: discharging (minus)
+* @cc_rst: reset CC_SUM or not
+*               TRUE : reset
+*               FALSE: not reset
 **/
 static int calc_capacity_in_period(struct ricoh619_battery_info *info,
-                                        int *cc_cap, bool *is_charging)
+                                int *cc_cap, bool *is_charging, bool cc_rst)
 {
        int err;
-       uint8_t cc_sum_reg[4];
-       uint8_t cc_clr[4] = {0, 0, 0, 0};
-       uint8_t fa_cap_reg[2];
-       uint16_t fa_cap;
-       uint32_t cc_sum;
-       int     cc_stop_flag;
-       uint8_t status;
-       uint8_t charge_state;
-       int Ocv;
+       uint8_t         cc_sum_reg[4];
+       uint8_t         cc_clr[4] = {0, 0, 0, 0};
+       uint8_t         fa_cap_reg[2];
+       uint16_t        fa_cap;
+       uint32_t        cc_sum;
+       int             cc_stop_flag;
+       uint8_t         status;
+       uint8_t         charge_state;
+       int             Ocv;
+       uint32_t        cc_cap_temp;
+       uint32_t        cc_cap_min;
+       int             cc_cap_res;
 
        *is_charging = true;    /* currrent state initialize -> charging */
 
@@ -380,11 +628,13 @@ static int calc_capacity_in_period(struct ricoh619_battery_info *info,
        if (err < 0)
                goto out;
 
-       /* CC_SUM <- 0 */
-       err = ricoh619_bulk_writes(info->dev->parent,
-                                       CC_SUMREG3_REG, 4, cc_clr);
-       if (err < 0)
-               goto out;
+       if (cc_rst == true) {
+               /* CC_SUM <- 0 */
+               err = ricoh619_bulk_writes(info->dev->parent,
+                                               CC_SUMREG3_REG, 4, cc_clr);
+               if (err < 0)
+                       goto out;
+       }
 
        /* CC_pause exist */
        err = ricoh619_write(info->dev->parent, CC_CTRL_REG, 0);
@@ -433,9 +683,34 @@ static int calc_capacity_in_period(struct ricoh619_battery_info *info,
                cc_sum = (cc_sum^0xffffffff)+0x01;
                *is_charging = false;           /* discharge */
        }
+       /* (CC_SUM x 10000)/3600/FA_CAP */
+       *cc_cap = cc_sum*25/9/fa_cap;           /* unit is 0.01% */
 
-       *cc_cap = cc_sum*25/9/fa_cap;   /* CC_SUM/3600/FA_CAP */
-
+       //////////////////////////////////////////////////////////////////      
+       cc_cap_min = fa_cap*3600/100/100/100;   /* Unit is 0.0001% */
+       cc_cap_temp = cc_sum / cc_cap_min;
+               
+       cc_cap_res = cc_cap_temp % 100;
+       
+       RICOH_FG_DBG("PMU: cc_sum = %d: cc_cap_res= %d: \n", cc_sum, cc_cap_res);
+       
+       
+       if(*is_charging) {
+               info->soca->cc_cap_offset += cc_cap_res;
+               if (info->soca->cc_cap_offset >= 100) {
+                       *cc_cap += 1;
+                       info->soca->cc_cap_offset %= 100;
+               }
+       } else {
+               info->soca->cc_cap_offset -= cc_cap_res;
+               if (info->soca->cc_cap_offset <= -100) {
+                       *cc_cap += 1;
+                       info->soca->cc_cap_offset %= 100;
+               }
+       }
+       RICOH_FG_DBG("PMU: cc_cap_offset= %d: \n", info->soca->cc_cap_offset);
+       
+       //////////////////////////////////////////////////////////////////
        return 0;
 out:
        dev_err(info->dev, "Error !!-----\n");
@@ -446,10 +721,10 @@ out:
 **/
 static int get_target_use_cap(struct ricoh619_battery_info *info)
 {
-       int i;
+       int i,j;
        int ocv_table[11];
        int temp;
-       int Target_Cutoff_Vol;
+//     int Target_Cutoff_Vol = 0;
        int Ocv_ZeroPer_now;
        int Ibat_now;
        int fa_cap,use_cap;
@@ -459,6 +734,12 @@ static int get_target_use_cap(struct ricoh619_battery_info *info)
        int CC_OnePer_step;
        int Ibat_min;
 
+//     int Ocv_now;
+       int Ocv_now_table;
+//     int soc_per;
+//     int use_cap_now;
+       int Rsys_now;
+
        /* get const value */
        Ibat_min = -1 * info->soca->target_ibat;
        if (info->soca->Ibat_ave > Ibat_min) /* I bat is minus */
@@ -470,22 +751,44 @@ static int get_target_use_cap(struct ricoh619_battery_info *info)
        fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG,
                                                                0x7fff);
        use_cap = fa_cap - info->soca->re_cap_old;
-       
-       Ocv_ZeroPer_now = info->soca->target_vsys * 1000 - Ibat_now * info->soca->Rsys;
-
-       RICOH_FG_DBG("PMU: -------  Rsys= %d: cutoff_ocv= %d: Ocv_ZeroPer_now= %d =======\n",
-              info->soca->Rsys, info->soca->cutoff_ocv, Ocv_ZeroPer_now);
 
-       /* get FA_CAP_now */
-       /* Check Start % */
+       /* get OCV table % */
        for (i = 0; i <= 10; i = i+1) {
                temp = (battery_init_para[info->num][i*2]<<8)
                         | (battery_init_para[info->num][i*2+1]);
                /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
                temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
                ocv_table[i] = temp;
+               RICOH_FG_DBG("PMU : %s : ocv_table %d is %d v\n",__func__, i, ocv_table[i]);
+       }
+
+       /* Find out Current OCV */
+       i = info->soca->soc/1000;
+       j = info->soca->soc - info->soca->soc/1000*1000;
+       Ocv_now_table = ocv_table[i]*100+(ocv_table[i+1]-ocv_table[i])*j/10;
+
+       Rsys_now = (info->soca->Vsys_ave - Ocv_now_table) / info->soca->Ibat_ave;
+       if (((abs(info->soca->soc - info->soca->displayed_soc)) > 10)
+               && (info->soca->Ibat_ave > -250)) {
+               if (Rsys_now < 0)
+                       Rsys_now = max(-info->soca->Rbat, Rsys_now);
+               else
+                       Rsys_now = min(info->soca->Rbat, Rsys_now);
        }
+
+       Ocv_ZeroPer_now = info->soca->target_vsys * 1000 - Ibat_now * Rsys_now;
+
+       RICOH_FG_DBG("PMU: -------  Ocv_now_table= %d: Rsys_now= %d =======\n",
+              Ocv_now_table, Rsys_now);
+
+       RICOH_FG_DBG("PMU: -------  Rsys= %d: cutoff_ocv= %d: Ocv_ZeroPer_now= %d =======\n",
+              info->soca->Rsys, info->soca->cutoff_ocv, Ocv_ZeroPer_now);
+
+       /* get FA_CAP_now */
+
+       
        for (i = 1; i < 11; i++) {
+               RICOH_FG_DBG("PMU : %s : ocv_table %d is %d v Ocv_ZerPernow is %d\n",__func__, i, ocv_table[i],(Ocv_ZeroPer_now / 100));
                if (ocv_table[i] >= Ocv_ZeroPer_now / 100) {
                        /* unit is 0.001% */
                        start_per = Calc_Linear_Interpolation(
@@ -495,33 +798,120 @@ static int get_target_use_cap(struct ricoh619_battery_info *info)
                }
        }
 
+       start_per = max(0, start_per);
+
        FA_CAP_now = fa_cap * ((10000 - start_per) / 100 ) / 100;
 
-       RICOH_FG_DBG("PMU: -------  Target_Cutoff_Vol= %d: Ocv_ZeroPer_now= %d: start_per= %d =======\n",
-              Target_Cutoff_Vol, Ocv_ZeroPer_now, start_per);
+       RICOH_FG_DBG("PMU: -------Ocv_ZeroPer_now= %d: start_per= %d =======\n",
+               Ocv_ZeroPer_now, start_per);
 
        /* get RE_CAP_now */
        RE_CAP_now = FA_CAP_now - use_cap;
        
-       if (RE_CAP_now < RE_CAP_GO_DOWN || info->soca->Vsys_ave < info->soca->target_vsys*1000) {
+       if (RE_CAP_now < RE_CAP_GO_DOWN) {
                info->soca->hurry_up_flg = 1;
-       } else {
-               info->soca->hurry_up_flg = 0;
-               /* get CC_OnePer_step */
-               if (info->soca->displayed_soc > 0) { /* avoid divide-by-0 */
-                       CC_OnePer_step = RE_CAP_now / (info->soca->displayed_soc / 100);
+       } else if (info->soca->Vsys_ave < info->soca->target_vsys*1000) {
+               info->soca->hurry_up_flg = 1;
+       } else if (info->fg_poff_vbat != 0) {
+               if (info->soca->Vbat_ave < info->fg_poff_vbat*1000) {
+                       info->soca->hurry_up_flg = 1;
                } else {
-                       CC_OnePer_step = 0;
+                       info->soca->hurry_up_flg = 0;
                }
-               /* get info->soca->target_use_cap */
-               info->soca->target_use_cap = use_cap + CC_OnePer_step;
+       } else {
+               info->soca->hurry_up_flg = 0;
+       }
+
+       /* get CC_OnePer_step */
+       if (info->soca->displayed_soc > 0) { /* avoid divide-by-0 */
+               CC_OnePer_step = RE_CAP_now / (info->soca->displayed_soc / 100 + 1);
+       } else {
+               CC_OnePer_step = 0;
+       }
+       /* get info->soca->target_use_cap */
+       info->soca->target_use_cap = use_cap + CC_OnePer_step;
+       
+       RICOH_FG_DBG("PMU: ------- FA_CAP_now= %d: RE_CAP_now= %d: CC_OnePer_step= %d: target_use_cap= %d: hurry_up_flg= %d -------\n",
+              FA_CAP_now, RE_CAP_now, CC_OnePer_step, info->soca->target_use_cap, info->soca->hurry_up_flg);
+       
+       return 0;
+}
+#ifdef ENABLE_OCV_TABLE_CALIB
+/**
+* Calibration OCV Table
+* - Update the value of VBAT on 100% in OCV table 
+*    if battery is Full charged.
+* - int vbat_ocv <- unit is uV
+**/
+static int calib_ocvTable(struct ricoh619_battery_info *info, int vbat_ocv)
+{
+       int ret;
+       int cutoff_ocv;
+       int i;
+       int ocv100_new;
+       int start_per = 0;
+       int end_per = 0;
+       
+       RICOH_FG_DBG("PMU: %s\n", __func__);
+       
+       if (info->soca->Ibat_ave > RICOH619_REL1_SEL_VALUE) {
+               RICOH_FG_DBG("PMU: %s IBAT > 64mA -- Not Calibration --\n", __func__);
+               return 0;
        }
        
-       RICOH_FG_DBG("PMU: -------  FA_CAP_now= %d: RE_CAP_now= %d: target_use_cap= %d: hurry_up_flg= %d -------\n",
-              FA_CAP_now, RE_CAP_now, info->soca->target_use_cap, info->soca->hurry_up_flg);
+       if (vbat_ocv < info->soca->OCV100_max) {
+               if (vbat_ocv < info->soca->OCV100_min)
+                       ocv100_new = info->soca->OCV100_min;
+               else
+                       ocv100_new = vbat_ocv;
+       } else {
+               ocv100_new = info->soca->OCV100_max;
+       }
+       RICOH_FG_DBG("PMU : %s :max %d min %d current %d\n",__func__,info->soca->OCV100_max,info->soca->OCV100_min,vbat_ocv);
+       RICOH_FG_DBG("PMU : %s : New OCV 100% = 0x%x\n",__func__,ocv100_new);
        
+       /* FG_En Off */
+       ret = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+       if (ret < 0) {
+               dev_err("PMU: %s Error in FG_En OFF\n", __func__);
+               goto err;
+       }
+
+
+       //cutoff_ocv = (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]);
+       cutoff_ocv = get_OCV_voltage(info, 0);
+
+       info->soca->ocv_table_def[10] = info->soca->OCV100_max;
+
+       ricoh619_scaling_OCV_table(info, cutoff_ocv/1000, ocv100_new/1000, &start_per, &end_per);
+
+       ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+                               BAT_INIT_TOP_REG, 22, battery_init_para[info->num]);
+       if (ret < 0) {
+               dev_err(info->dev, "batterry initialize error\n");
+               goto err;
+       }
+
+       for (i = 0; i <= 10; i = i+1) {
+               info->soca->ocv_table[i] = get_OCV_voltage(info, i);
+               RICOH_FG_DBG("PMU: %s : * %d0%% voltage = %d uV\n",
+                                __func__, i, info->soca->ocv_table[i]);
+       }
+       
+       /* FG_En on & Reset*/
+       ret = reset_FG_process(info);
+       if (ret < 0) {
+               dev_err("PMU: %s Error in FG_En On & Reset\n", __func__);
+               goto err;
+       }
+
+       RICOH_FG_DBG("PMU: %s Exit \n", __func__);
        return 0;
+err:
+       return ret;
+
 }
+#endif
 
 static void ricoh619_displayed_work(struct work_struct *work)
 {
@@ -532,11 +922,18 @@ static void ricoh619_displayed_work(struct work_struct *work)
        int last_soc_round;
        int last_disp_round;
        int displayed_soc_temp;
+       int disp_dec;
        int cc_cap = 0;
        bool is_charging = true;
-       int i;
        int re_cap,fa_cap,use_cap;
        bool is_jeita_updated;
+       uint8_t reg_val;
+       int delay_flag = 0;
+       int Vbat = 0;
+       int Ibat = 0;
+       int Vsys = 0;
+       int temp_ocv;
+       int fc_delta = 0;
 
        struct ricoh619_battery_info *info = container_of(work,
        struct ricoh619_battery_info, displayed_work.work);
@@ -553,107 +950,58 @@ static void ricoh619_displayed_work(struct work_struct *work)
        is_jeita_updated = false;
 
        if ((RICOH619_SOCA_START == info->soca->status)
-                || (RICOH619_SOCA_STABLE == info->soca->status))
+                || (RICOH619_SOCA_STABLE == info->soca->status)
+                || (RICOH619_SOCA_FULL == info->soca->status))
                info->soca->ready_fg = 1;
 
-       /* judege Full state or Moni Vsys state */
+       /* judge Full state or Moni Vsys state */
        if ((RICOH619_SOCA_DISP == info->soca->status)
                 || (RICOH619_SOCA_STABLE == info->soca->status))
        {
-               /* for issue 1 solution start*/
-               if(g_full_flag == 1){
+               /* caluc 95% ocv */
+               temp_ocv = get_OCV_voltage(info, 10) -
+                                       (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2;
+               
+               if(g_full_flag == 1){   /* for issue 1 solution start*/
                        info->soca->status = RICOH619_SOCA_FULL;
-                       info->soca->update_count = 0;
-               }
-               /* for issue1 solution end */
-               /* check Full state or not*/
-               if (info->soca->Ibat_ave >= 0) {
-                       if ((calc_ocv(info) > (get_OCV_voltage(info, 10) - info->soca->f_chg_margin))
-                               || (info->soca->displayed_soc/100 >= 99))
+               }else if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status)
+                       && (calc_ocv(info) > temp_ocv)) {
+                       info->soca->status = RICOH619_SOCA_FULL;
+                       g_full_flag = 0;
+               } else if (info->soca->Ibat_ave >= -20) {
+                       /* for issue1 solution end */
+                       /* check Full state or not*/
+                       if ((calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10))
+                               || (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status)
+                               || (info->soca->displayed_soc > 9850))
                        {
+                               info->soca->status = RICOH619_SOCA_FULL;
                                g_full_flag = 0;
+                       } else if ((calc_ocv(info) > (get_OCV_voltage(info, 9)))
+                               && (info->soca->Ibat_ave < 300))
+                       {
                                info->soca->status = RICOH619_SOCA_FULL;
-                               info->soca->update_count = 0;
+                               g_full_flag = 0;
                        }
                } else { /* dis-charging */
                        if (info->soca->displayed_soc/100 < RICOH619_ENTER_LOW_VOL) {
+                               info->soca->target_use_cap = 0;
                                info->soca->status = RICOH619_SOCA_LOW_VOL;
                        }
                }
        }
 
        if (RICOH619_SOCA_STABLE == info->soca->status) {
-               info->soca->soc = calc_capacity(info) * 100;
-               soc_round = info->soca->soc / 100;
-               last_soc_round = info->soca->last_soc / 100;
-
-               info->soca->soc_delta = soc_round - last_soc_round;
-
-               //get charge status
-               if (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING) {
-                       if (soc_round >= 90) {
-                               if(soc_round < 95) {
-                                       if (info->soca->reset_flg_90 == 0) {
-                                               err = ricoh619_write(info->dev->parent,
-                                                FG_CTRL_REG, 0x51);
-                                               if (err< 0)
-                                                       dev_err(info->dev, "Error in writing the control register\n");
-
-                                               info->soca->ready_fg = 0;
-
-                                               for (i = 0; i < 3; i = i+1) {
-                                                       info->soca->reset_soc[i] = 0;
-                                               }
-                                               info->soca->stable_count = 0;
-
-                                               info->soca->status = RICOH619_SOCA_FG_RESET;
-                                               /* Delay for addition Reset Time (6s) */
-                                               info->soca->stable_count = 1;
-                                               queue_delayed_work(info->monitor_wqueue,
-                                                               &info->charge_stable_work,
-                                                               RICOH619_FG_RESET_TIME*HZ);
-
-                                               info->soca->reset_flg_90 = 1;
-                                               goto end_flow;
-                                       }
-                               } else if (soc_round < 100) {
-                                       if (info->soca->reset_flg_95 == 0) {
-                                               err = ricoh619_write(info->dev->parent,
-                                                FG_CTRL_REG, 0x51);
-                                               if (err < 0)
-                                                       dev_err(info->dev, "Error in writing the control register\n");
-
-                                               info->soca->ready_fg = 0;
-
-                                               for (i = 0; i < 3; i = i+1) {
-                                                       info->soca->reset_soc[i] = 0;
-                                               }
+               info->soca->soc = calc_capacity_2(info);
+               info->soca->soc_delta = info->soca->soc - info->soca->last_soc;
 
-                                               info->soca->stable_count = 0;
-                                               info->soca->status = RICOH619_SOCA_FG_RESET;
-                                               info->soca->stable_count = 1;
-                                               queue_delayed_work(info->monitor_wqueue,
-                                                               &info->charge_stable_work,
-                                                               RICOH619_FG_RESET_TIME*HZ);
-
-                                               info->soca->reset_flg_95 = 1;
-                                               goto end_flow;
-                                       }
-                               }
-                       } else {
-                               info->soca->reset_flg_90 = 0;
-                               info->soca->reset_flg_95 = 0;
-                       }
-               }
-
-               if (info->soca->soc_delta >= -1 && info->soca->soc_delta <= 1) {
+               if (info->soca->soc_delta >= -100 && info->soca->soc_delta <= 100) {
                        info->soca->displayed_soc = info->soca->soc;
                } else {
                        info->soca->status = RICOH619_SOCA_DISP;
                }
                info->soca->last_soc = info->soca->soc;
                info->soca->soc_delta = 0;
-               info->soca->update_count = 0;
        } else if (RICOH619_SOCA_FULL == info->soca->status) {
                err = check_jeita_status(info, &is_jeita_updated);
                if (err < 0) {
@@ -661,55 +1009,142 @@ static void ricoh619_displayed_work(struct work_struct *work)
                        goto end_flow;
                }
                info->soca->soc = calc_capacity(info) * 100;
-               if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) {
-                       if (0 == info->soca->jt_limit) {
-                               g_full_flag = 1;
-                               info->soca->displayed_soc = 100*100;
-                               info->soca->update_count = 0;
-                       } else {
-                               info->soca->update_count = 0;
-                       }
-               } 
-               if (info->soca->Ibat_ave >= 0) {        /* for issue 3 */
+               info->soca->last_soc = calc_capacity_2(info);   /* for DISP */
+
+               if (info->soca->Ibat_ave >= -20) { /* charging */
                        if (0 == info->soca->jt_limit) {
                                if (g_full_flag == 1) {
-                                       info->soca->displayed_soc = 100*100;
-                                       info->soca->update_count = 0;
+                                       
+                                       if (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) {
+                                               if(info->soca->full_reset_count < RICOH619_UPDATE_COUNT_FULL_RESET) {
+                                                       info->soca->full_reset_count++;
+                                               } else if (info->soca->full_reset_count < (RICOH619_UPDATE_COUNT_FULL_RESET + 1)) {
+                                                       err = reset_FG_process(info);
+                                                       if (err < 0)
+                                                               dev_err(info->dev, "Error in writing the control register\n");
+                                                       info->soca->full_reset_count++;
+                                                       goto end_flow;
+                                               } else if(info->soca->full_reset_count < (RICOH619_UPDATE_COUNT_FULL_RESET + 2)) {
+                                                       info->soca->full_reset_count++;
+                                                       info->soca->fc_cap = 0;
+                                                       info->soca->soc_full = info->soca->soc;
+                                               }
+                                       } else {
+                                               if(info->soca->fc_cap < -1 * 200) {
+                                                       g_full_flag = 0;
+                                                       info->soca->displayed_soc = 99 * 100;
+                                               }
+                                               info->soca->full_reset_count = 0;
+                                       }
+                                       
+
+                                       info->soca->chg_cmp_times = 0;
+                                       err = calc_capacity_in_period(info, &cc_cap, &is_charging, true);
+                                       if (err < 0)
+                                       dev_err(info->dev, "Read cc_sum Error !!-----\n");
+
+                                       fc_delta = (is_charging == true) ? cc_cap : -cc_cap;
+
+                                       info->soca->fc_cap = info->soca->fc_cap + fc_delta;
+
+                                       if (g_full_flag == 1){
+                                               info->soca->displayed_soc = 100*100;
+                                       }
                                } else {
-                                       if (info->soca->displayed_soc/100 < 99) {
-                                               info->soca->update_count++;
-                                               if (info->soca->update_count
-                                               >= RICOH619_UPDATE_COUNT_FULL) {
-                                                       info->soca->displayed_soc = info->soca->displayed_soc + 100;
-                                                       info->soca->update_count = 0;
+                                       if (calc_ocv(info) < (get_OCV_voltage(info, 8))) { /* fail safe*/
+                                               g_full_flag = 0;
+                                               info->soca->status = RICOH619_SOCA_DISP;
+                                               info->soca->soc_delta = 0;
+                                       } else if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status) 
+                                               && (info->soca->displayed_soc >= 9890)){
+                                               if(info->soca->chg_cmp_times > RICOH619_FULL_WAIT_TIME) {
+                                                       info->soca->displayed_soc = 100*100;
+                                                       g_full_flag = 1;
+                                                       info->soca->full_reset_count = 0;
+                                                       info->soca->soc_full = info->soca->soc;
+                                                       info->soca->fc_cap = 0;
+#ifdef ENABLE_OCV_TABLE_CALIB
+                                                       err = calib_ocvTable(info,calc_ocv(info));
+                                                       if (err < 0)
+                                                               dev_err(info->dev, "Calibration OCV Error !!\n");
+#endif
+                                               } else {
+                                                       info->soca->chg_cmp_times++;
                                                }
                                        } else {
-                                               info->soca->displayed_soc = 99 * 100;
-                                               info->soca->update_count = 0;
+                                               fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG,
+                                                       0x7fff);
+                                               
+                                               if (info->soca->displayed_soc >= 9950) {
+                                                       if((info->soca->soc_full - info->soca->soc) < 200) {
+                                                               goto end_flow;
+                                                       }
+                                               }
+                                               info->soca->chg_cmp_times = 0;
+
+                                               err = calc_capacity_in_period(info, &cc_cap, &is_charging, true);
+                                               if (err < 0)
+                                               dev_err(info->dev, "Read cc_sum Error !!-----\n");
+                                               info->soca->cc_delta
+                                                        = (is_charging == true) ? cc_cap : -cc_cap;
+
+                                               if((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status)
+                                               //      || (info->soca->Ibat_ave > 200))
+                                               || (info->soca->Ibat_ave < info->ch_icchg*50 + 100) || (info->soca->displayed_soc<9700))
+                                               {
+                                                       info->soca->displayed_soc += 13 * 3000 / fa_cap;
+                                               }
+                                               else {
+                                                       info->soca->displayed_soc
+                                                      = info->soca->displayed_soc + info->soca->cc_delta*8/10;
+                                               }
+                                               
+                                               info->soca->displayed_soc
+                                                        = min(10000, info->soca->displayed_soc);
+                                               info->soca->displayed_soc = max(0, info->soca->displayed_soc);
+
+                                               if (info->soca->displayed_soc >= 9890) {
+                                                       info->soca->displayed_soc = 99 * 100;
+                                               }
                                        }
                                }
                        } else {
-                               info->soca->update_count = 0;
+                               info->soca->full_reset_count = 0;
                        }
-               }
-               if (info->soca->Ibat_ave < 0) { /* for issue 3 */
-                       info->soca->update_count = 0;
-                       if (g_full_flag == 1) {
-                               if ((calc_ocv(info) < (get_OCV_voltage(info, 10) - info->soca->f_chg_margin))
-                                       && (info->soca->soc/100 <= 98)) { /* for issue 2 */
-                                       g_full_flag = 0;
-                                       info->soca->displayed_soc = 100*100;
-                                       info->soca->status = RICOH619_SOCA_DISP;
-                                       info->soca->last_soc = info->soca->soc;
-                                       info->soca->soc_delta = 0;
-                               } else {
-                                       info->soca->displayed_soc = 100*100;
+               } else { /* discharging */
+                       if (info->soca->displayed_soc >= 9950) {
+                               if (info->soca->Ibat_ave <= -1 * RICOH619_REL1_SEL_VALUE) {
+                                       if ((calc_ocv(info) < (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*3/10))
+                                               || ((info->soca->soc_full - info->soca->soc) > 200)) {
+
+                                               g_full_flag = 0;
+                                               info->soca->full_reset_count = 0;
+                                               info->soca->displayed_soc = 100 * 100;
+                                               info->soca->status = RICOH619_SOCA_DISP;
+                                               info->soca->last_soc = info->soca->soc;
+                                               info->soca->soc_delta = 0;
+                                       } else {
+                                               info->soca->displayed_soc = 100 * 100;
+                                       }
+                               } else { /* into relaxation state */
+                                       ricoh619_read(info->dev->parent, CHGSTATE_REG, &reg_val);
+                                       if (reg_val & 0xc0) {
+                                               info->soca->displayed_soc = 100 * 100;
+                                       } else {
+                                               g_full_flag = 0;
+                                               info->soca->full_reset_count = 0;
+                                               info->soca->displayed_soc = 100 * 100;
+                                               info->soca->status = RICOH619_SOCA_DISP;
+                                               info->soca->last_soc = info->soca->soc;
+                                               info->soca->soc_delta = 0;
+                                       }
                                }
                        } else {
                                g_full_flag = 0;
                                info->soca->status = RICOH619_SOCA_DISP;
-                               info->soca->last_soc = info->soca->soc;
                                info->soca->soc_delta = 0;
+                               info->soca->full_reset_count = 0;
+                               info->soca->last_soc = info->soca->soc;
                        }
                }
        } else if (RICOH619_SOCA_LOW_VOL == info->soca->status) {
@@ -718,7 +1153,6 @@ static void ricoh619_displayed_work(struct work_struct *work)
                        info->soca->status = RICOH619_SOCA_DISP;
                        info->soca->last_soc = info->soca->soc;
                        info->soca->soc_delta = 0;
-                       info->soca->update_count = 0;
                } else {
                        re_cap = get_check_fuel_gauge_reg(info, RE_CAP_H_REG, RE_CAP_L_REG,
                                                                0x7fff);
@@ -726,14 +1160,16 @@ static void ricoh619_displayed_work(struct work_struct *work)
                                                                0x7fff);
                        use_cap = fa_cap - re_cap;
                        
-                       if ((info->soca->target_use_cap == 0)
-                       && (info->soca->hurry_up_flg == 0)) {
+                       if (info->soca->target_use_cap == 0) {
                                info->soca->re_cap_old = re_cap;
                                get_target_use_cap(info);
                        }
-
-                       if((use_cap >= info->soca->target_use_cap)
-                       || (info->soca->hurry_up_flg == 1)) {
+                       
+                       if(use_cap >= info->soca->target_use_cap) {
+                               info->soca->displayed_soc = info->soca->displayed_soc - 100;
+                               info->soca->displayed_soc = max(0, info->soca->displayed_soc);
+                               info->soca->re_cap_old = re_cap;
+                       } else if (info->soca->hurry_up_flg == 1) {
                                info->soca->displayed_soc = info->soca->displayed_soc - 100;
                                info->soca->displayed_soc = max(0, info->soca->displayed_soc);
                                info->soca->re_cap_old = re_cap;
@@ -742,16 +1178,16 @@ static void ricoh619_displayed_work(struct work_struct *work)
                        info->soca->soc = calc_capacity(info) * 100;
                }
        }
-       if (RICOH619_SOCA_DISP == info->soca->status) {
+       else if (RICOH619_SOCA_DISP == info->soca->status) {
 
-               info->soca->soc = calc_capacity(info) * 100;
+               info->soca->soc = calc_capacity_2(info);
 
-               soc_round = info->soca->soc / 100;
-               last_soc_round = info->soca->last_soc / 100;
+               soc_round = (info->soca->soc + 50) / 100;
+               last_soc_round = (info->soca->last_soc + 50) / 100;
                last_disp_round = (info->soca->displayed_soc + 50) / 100;
 
                info->soca->soc_delta =
-                       info->soca->soc_delta + (soc_round - last_soc_round);
+                       info->soca->soc_delta + (info->soca->soc - info->soca->last_soc);
 
                info->soca->last_soc = info->soca->soc;
                /* six case */
@@ -759,92 +1195,176 @@ static void ricoh619_displayed_work(struct work_struct *work)
                        /* if SOC == DISPLAY move to stable */
                        info->soca->displayed_soc = info->soca->soc ;
                        info->soca->status = RICOH619_SOCA_STABLE;
+                       delay_flag = 1;
                } else if (info->soca->Ibat_ave > 0) {
                        if ((0 == info->soca->jt_limit) || 
-                       (POWER_SUPPLY_STATUS_FULL != info->soca->chg_status)) { 
+                       (POWER_SUPPLY_STATUS_FULL != info->soca->chg_status)) {
                                /* Charge */
                                if (last_disp_round < soc_round) {
                                        /* Case 1 : Charge, Display < SOC */
-                                       info->soca->update_count++;
-                                       if ((info->soca->update_count
-                                                >= RICOH619_UPDATE_COUNT_DISP)
-                                               || (info->soca->soc_delta == 1)) {
+                                       if (info->soca->soc_delta >= 100) {
                                                info->soca->displayed_soc
-                                                       = (last_disp_round + 1)*100;
-                                               info->soca->update_count = 0;
-                                               info->soca->soc_delta = 0;
+                                                       = last_disp_round * 100 + 50;
+                                               info->soca->soc_delta -= 100;
+                                               if (info->soca->soc_delta >= 100)
+                                                       delay_flag = 1;
+                                       } else {
+                                               info->soca->displayed_soc += 25;
+                                               disp_dec = info->soca->displayed_soc % 100;
+                                               if ((50 <= disp_dec) && (disp_dec <= 74))
+                                                       info->soca->soc_delta = 0;
                                        }
-                                       if (info->soca->displayed_soc/100
+                                       if ((info->soca->displayed_soc + 50)/100
                                                                 >= soc_round) {
                                                info->soca->displayed_soc
                                                        = info->soca->soc ;
                                                info->soca->status
                                                        = RICOH619_SOCA_STABLE;
+                                               delay_flag = 1;
                                        }
                                } else if (last_disp_round > soc_round) {
                                        /* Case 2 : Charge, Display > SOC */
-                                       info->soca->update_count = 0;
-                                       if (info->soca->soc_delta >= 3) {
-                                               info->soca->displayed_soc =
-                                                       (last_disp_round + 1)*100;
-                                               info->soca->soc_delta -= 3;
+                                       if (info->soca->soc_delta >= 300) {
+                                               info->soca->displayed_soc += 100;
+                                               info->soca->soc_delta -= 300;
                                        }
-                                       if (info->soca->displayed_soc/100
+                                       if ((info->soca->displayed_soc + 50)/100
                                                                 <= soc_round) {
                                                info->soca->displayed_soc
                                                        = info->soca->soc ;
                                                info->soca->status
                                                = RICOH619_SOCA_STABLE;
+                                               delay_flag = 1;
                                        }
                                }
                        } else {
-                               info->soca->update_count = 0;
                                info->soca->soc_delta = 0;
                        }
                } else {
                        /* Dis-Charge */
                        if (last_disp_round > soc_round) {
                                /* Case 3 : Dis-Charge, Display > SOC */
-                               info->soca->update_count++;
-                               if ((info->soca->update_count
-                                        >= RICOH619_UPDATE_COUNT_DISP)
-                               || (info->soca->soc_delta == -1)) {
+                               if (info->soca->soc_delta <= -100) {
                                        info->soca->displayed_soc
-                                               = (last_disp_round - 1)*100;
-                                       info->soca->update_count = 0;
-                                       info->soca->soc_delta = 0;
+                                               = last_disp_round * 100 - 75;
+                                       info->soca->soc_delta += 100;
+                                       if (info->soca->soc_delta <= -100)
+                                               delay_flag = 1;
+                               } else {
+                                       info->soca->displayed_soc -= 25;
+                                       disp_dec = info->soca->displayed_soc % 100;
+                                       if ((25 <= disp_dec) && (disp_dec <= 49))
+                                               info->soca->soc_delta = 0;
                                }
-                               if (info->soca->displayed_soc/100
+                               if ((info->soca->displayed_soc + 50)/100
                                                         <= soc_round) {
                                        info->soca->displayed_soc
                                                = info->soca->soc ;
                                        info->soca->status
                                                = RICOH619_SOCA_STABLE;
+                                       delay_flag = 1;
                                }
                        } else if (last_disp_round < soc_round) {
                                /* Case 4 : Dis-Charge, Display < SOC */
-                               info->soca->update_count = 0;
-                               if (info->soca->soc_delta <= -3) {
-                                       info->soca->displayed_soc
-                                               = (last_disp_round - 1)*100;
-                                       info->soca->soc_delta += 3;
+                               if (info->soca->soc_delta <= -300) {
+                                       info->soca->displayed_soc -= 100;
+                                       info->soca->soc_delta += 300;
                                }
-                               if (info->soca->displayed_soc/100
+                               if ((info->soca->displayed_soc + 50)/100
                                                         >= soc_round) {
                                        info->soca->displayed_soc
                                                = info->soca->soc ;
                                        info->soca->status
                                                = RICOH619_SOCA_STABLE;
+                                       delay_flag = 1;
                                }
                        }
                }
        } else if (RICOH619_SOCA_UNSTABLE == info->soca->status) {
-               if (0 == info->soca->jt_limit) {
-                       check_charge_status_2(info, info->soca->displayed_soc);
+               /* caluc 95% ocv */
+               temp_ocv = get_OCV_voltage(info, 10) -
+                                       (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))/2;
+               
+               if(g_full_flag == 1){   /* for issue 1 solution start*/
+                       info->soca->status = RICOH619_SOCA_FULL;
+                       err = reset_FG_process(info);
+                       if (err < 0)
+                               dev_err(info->dev, "Error in writing the control register\n");
+                       
+                       goto end_flow;
+               }else if ((POWER_SUPPLY_STATUS_FULL == info->soca->chg_status)
+                       && (calc_ocv(info) > temp_ocv)) {
+                       info->soca->status = RICOH619_SOCA_FULL;
+                       g_full_flag = 0;
+                       err = reset_FG_process(info);
+                       if (err < 0)
+                               dev_err(info->dev, "Error in writing the control register\n");
+                       goto end_flow;
+               } else if (info->soca->Ibat_ave >= -20) {
+                       /* for issue1 solution end */
+                       /* check Full state or not*/
+                       if ((calc_ocv(info) > (get_OCV_voltage(info, 9) + (get_OCV_voltage(info, 10) - get_OCV_voltage(info, 9))*7/10))
+                               || (POWER_SUPPLY_STATUS_FULL == info->soca->chg_status)
+                               || (info->soca->displayed_soc > 9850))
+                       {
+                               info->soca->status = RICOH619_SOCA_FULL;
+                               g_full_flag = 0;
+                               err = reset_FG_process(info);
+                               if (err < 0)
+                                       dev_err(info->dev, "Error in writing the control register\n");
+                               goto end_flow;
+                       } else if ((calc_ocv(info) > (get_OCV_voltage(info, 9)))
+                               && (info->soca->Ibat_ave < 300))
+                       {
+                               info->soca->status = RICOH619_SOCA_FULL;
+                               g_full_flag = 0;
+                               err = reset_FG_process(info);
+                               if (err < 0)
+                                       dev_err(info->dev, "Error in writing the control register\n");                          
+                               goto end_flow;
+                       }
                }
+
+               err = ricoh619_read(info->dev->parent, PSWR_REG, &val);
+               val &= 0x7f;
+               info->soca->soc = val * 100;
+               if (err < 0) {
+                       dev_err(info->dev,
+                                "Error in reading PSWR_REG %d\n", err);
+                       info->soca->soc
+                                = calc_capacity(info) * 100;
+               }
+
+               err = calc_capacity_in_period(info, &cc_cap,
+                                                &is_charging, false);
+               if (err < 0)
+                       dev_err(info->dev, "Read cc_sum Error !!-----\n");
+
+               info->soca->cc_delta
+                        = (is_charging == true) ? cc_cap : -cc_cap;
+
+               displayed_soc_temp
+                      = info->soca->soc + info->soca->cc_delta;
+               if (displayed_soc_temp < 0)
+                       displayed_soc_temp = 0;
+               displayed_soc_temp
+                        = min(9850, displayed_soc_temp);
+               displayed_soc_temp = max(0, displayed_soc_temp);
+
+               info->soca->displayed_soc = displayed_soc_temp;
+
        } else if (RICOH619_SOCA_FG_RESET == info->soca->status) {
                /* No update */
        } else if (RICOH619_SOCA_START == info->soca->status) {
+
+               err = measure_Ibatt_FG(info, &Ibat);
+               err = measure_vbatt_FG(info, &Vbat);
+               err = measure_vsys_ADC(info, &Vsys);
+
+               info->soca->Ibat_ave = Ibat;
+               info->soca->Vbat_ave = Vbat;
+               info->soca->Vsys_ave = Vsys;
+
                err = check_jeita_status(info, &is_jeita_updated);
                is_jeita_updated = false;
                if (err < 0) {
@@ -854,6 +1374,13 @@ static void ricoh619_displayed_work(struct work_struct *work)
                val &= 0x7f;
                if (info->first_pwon) {
                        info->soca->soc = calc_capacity(info) * 100;
+                       val = (info->soca->soc + 50)/100;
+                       val &= 0x7f;
+                       err = ricoh619_write(info->dev->parent, PSWR_REG, val);
+                       if (err < 0)
+                               dev_err(info->dev, "Error in writing PSWR_REG\n");
+                       g_soc = val;
+
                        if ((info->soca->soc == 0) && (calc_ocv(info)
                                        < get_OCV_voltage(info, 0))) {
                                info->soca->displayed_soc = 0;
@@ -864,7 +1391,22 @@ static void ricoh619_displayed_work(struct work_struct *work)
                                } else {
                                        info->soca->displayed_soc = info->soca->soc;
                                }
-                               info->soca->status = RICOH619_SOCA_UNSTABLE;
+                               if (Ibat < 0) {
+                                       if (info->soca->displayed_soc < 300) {
+                                               info->soca->target_use_cap = 0;
+                                               info->soca->status = RICOH619_SOCA_LOW_VOL;
+                                       } else {
+                                               if ((info->fg_poff_vbat != 0)
+                                                     && (Vbat < info->fg_poff_vbat * 1000) ){
+                                                         info->soca->target_use_cap = 0;
+                                                         info->soca->status = RICOH619_SOCA_LOW_VOL;
+                                                 } else { 
+                                                         info->soca->status = RICOH619_SOCA_UNSTABLE;
+                                                 }
+                                       }
+                               } else {
+                                       info->soca->status = RICOH619_SOCA_UNSTABLE;
+                               }
                        }
                } else if (g_fg_on_mode && (val == 0x7f)) {
                        info->soca->soc = calc_capacity(info) * 100;
@@ -878,6 +1420,7 @@ static void ricoh619_displayed_work(struct work_struct *work)
                                } else {
                                        info->soca->displayed_soc = info->soca->soc;
                                }
+                               info->soca->last_soc = info->soca->soc;
                                info->soca->status = RICOH619_SOCA_STABLE;
                        }
                } else {
@@ -890,7 +1433,7 @@ static void ricoh619_displayed_work(struct work_struct *work)
                        }
 
                        err = calc_capacity_in_period(info, &cc_cap,
-                                                                &is_charging);
+                                                        &is_charging, false);
                        if (err < 0)
                                dev_err(info->dev, "Read cc_sum Error !!-----\n");
 
@@ -912,30 +1455,74 @@ static void ricoh619_displayed_work(struct work_struct *work)
                                } else {
                                        info->soca->displayed_soc = displayed_soc_temp;
                                }
-                               info->soca->status = RICOH619_SOCA_UNSTABLE;
+                               info->soca->last_soc = calc_capacity(info) * 100;
+                               if (Ibat < 0) {
+                                       if (info->soca->displayed_soc < 300) {
+                                               info->soca->target_use_cap = 0;
+                                               info->soca->status = RICOH619_SOCA_LOW_VOL;
+                                       } else {
+                                               if ((info->fg_poff_vbat != 0)
+                                                     && (Vbat < info->fg_poff_vbat * 1000)){
+                                                         info->soca->target_use_cap = 0;
+                                                         info->soca->status = RICOH619_SOCA_LOW_VOL;
+                                                 } else { 
+                                                         info->soca->status = RICOH619_SOCA_UNSTABLE;
+                                                 }
+                                       }
+                               } else {
+                                       if(info->soca->displayed_soc >= 9850)
+                                       {
+                                               info->soca->displayed_soc = 10000;
+                                               info->chg_complete_tm_ov_flag = 1;
+                                       }
+                                       info->soca->status = RICOH619_SOCA_UNSTABLE;
+                               }
                        }
                }
        } else if (RICOH619_SOCA_ZERO == info->soca->status) {
                if (calc_ocv(info) > get_OCV_voltage(info, 0)) {
-                       err = ricoh619_write(info->dev->parent,
-                                                        FG_CTRL_REG, 0x51);
+                       err = reset_FG_process(info);
                        if (err < 0)
                                dev_err(info->dev, "Error in writing the control register\n");
+                       info->soca->last_soc = calc_capacity_2(info);
                        info->soca->status = RICOH619_SOCA_STABLE;
-                       info->soca->ready_fg = 0;
                }
-               info->soca->displayed_soc = 0;
+               info->soca->displayed_soc = 0;
+       }
+end_flow:
+       /* keep DSOC = 1 when Vbat is over 3.4V*/
+       if( info->fg_poff_vbat != 0) {
+               if (info->soca->zero_flg == 1) {
+                       if(info->soca->Ibat_ave >= 0) {
+                               info->soca->zero_flg = 0;
+                       }
+                       info->soca->displayed_soc = 0;
+               } else if (info->soca->displayed_soc < 50) {
+                       if (info->soca->Vbat_ave < 2000*1000) { /* error value */
+                               info->soca->displayed_soc = 100;
+                       } else if (info->soca->Vbat_ave < info->fg_poff_vbat*1000) {
+                               info->soca->displayed_soc = 0;
+                               info->soca->zero_flg = 1;
+                       } else {
+                               info->soca->displayed_soc = 100;
+                       }
+               }
        }
-end_flow:
+
        if (g_fg_on_mode
                 && (info->soca->status == RICOH619_SOCA_STABLE)) {
                err = ricoh619_write(info->dev->parent, PSWR_REG, 0x7f);
                if (err < 0)
                        dev_err(info->dev, "Error in writing PSWR_REG\n");
                g_soc = 0x7F;
-       } else {
-               if (info->soca->displayed_soc < 0) {
-                       val = 0;
+               err = calc_capacity_in_period(info, &cc_cap,
+                                                       &is_charging, true);
+               if (err < 0)
+                       dev_err(info->dev, "Read cc_sum Error !!-----\n");
+
+       } else if (RICOH619_SOCA_UNSTABLE != info->soca->status) {
+               if ((info->soca->displayed_soc + 50) / 100 <= 1) {
+                       val = 1;
                } else {
                        val = (info->soca->displayed_soc + 50)/100;
                        val &= 0x7f;
@@ -946,7 +1533,8 @@ end_flow:
 
                g_soc = val;
 
-               err = calc_capacity_in_period(info, &cc_cap, &is_charging);
+               err = calc_capacity_in_period(info, &cc_cap,
+                                                        &is_charging, true);
                if (err < 0)
                        dev_err(info->dev, "Read cc_sum Error !!-----\n");
        }
@@ -985,6 +1573,9 @@ end_flow:
        if (0 == info->soca->ready_fg)
                queue_delayed_work(info->monitor_wqueue, &info->displayed_work,
                                         RICOH619_FG_RESET_TIME * HZ);
+       else if (delay_flag == 1)
+               queue_delayed_work(info->monitor_wqueue, &info->displayed_work,
+                                        RICOH619_DELAY_TIME * HZ);
        else if (RICOH619_SOCA_DISP == info->soca->status)
                queue_delayed_work(info->monitor_wqueue, &info->displayed_work,
                                         RICOH619_DISPLAY_UPDATE_TIME * HZ);
@@ -996,10 +1587,36 @@ end_flow:
                                         RICOH619_DISPLAY_UPDATE_TIME * HZ);
 
        mutex_unlock(&info->lock);
-       
-       if(true == is_jeita_updated)
+
+       if((true == is_jeita_updated)
+       || (info->soca->last_displayed_soc/100 != (info->soca->displayed_soc+50)/100))
                power_supply_changed(&info->battery);
 
+       info->soca->last_displayed_soc = info->soca->displayed_soc+50;
+
+       if ((info->soca->displayed_soc >= 9850) && (info->soca->Ibat_ave > -20) && (info->capacity < 100)
+               && (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING))
+       {
+               if(info->chg_complete_rd_flag == 0)
+               {
+                       info->chg_complete_rd_flag = 1;
+                       info->chg_complete_rd_cnt = 0;
+                       queue_delayed_work(info->monitor_wqueue, &info->charge_complete_ready, 0);
+               }
+       }
+       else
+       {
+               info->chg_complete_rd_flag = 0;
+       }
+
+       if(info->chg_complete_tm_ov_flag == 1)
+       {
+               if(info->soca->displayed_soc < 9850 || info->soca->Ibat_ave < -20)
+               {
+                       info->chg_complete_tm_ov_flag = 0;
+                       power_supply_changed(&info->battery);
+               }
+       }
        return;
 }
 
@@ -1022,11 +1639,9 @@ static void ricoh619_stable_charge_countdown_work(struct work_struct *work)
        if (2 <= info->soca->stable_count) {
                if (3 == info->soca->stable_count
                        && RICOH619_SOCA_FG_RESET == info->soca->status) {
-                       ret = ricoh619_write(info->dev->parent,
-                                                        FG_CTRL_REG, 0x51);
+                       ret = reset_FG_process(info);
                        if (ret < 0)
                                dev_err(info->dev, "Error in writing the control register\n");
-                       info->soca->ready_fg = 0;
                }
                info->soca->stable_count = info->soca->stable_count - 1;
                queue_delayed_work(info->monitor_wqueue,
@@ -1046,12 +1661,10 @@ static void ricoh619_stable_charge_countdown_work(struct work_struct *work)
                                return;
                        }
                        /* Do reset setting */
-                       ret = ricoh619_write(info->dev->parent,
-                                                FG_CTRL_REG, 0x51);
+                       ret = reset_FG_process(info);
                        if (ret < 0)
                                dev_err(info->dev, "Error in writing the control register\n");
 
-                       info->soca->ready_fg = 0;
                        info->soca->status = RICOH619_SOCA_FG_RESET;
 
                        /* Delay for addition Reset Time (6s) */
@@ -1086,13 +1699,10 @@ static void ricoh619_stable_charge_countdown_work(struct work_struct *work)
                                goto adjust;
                        } else {
                                /* Do reset setting */
-                               ret = ricoh619_write(info->dev->parent,
-                                                        FG_CTRL_REG, 0x51);
+                               ret = reset_FG_process(info);
                                if (ret < 0)
                                        dev_err(info->dev, "Error in writing the control register\n");
 
-                               info->soca->ready_fg = 0;
-
                                /* Delay for addition Reset Time (6s) */
                                queue_delayed_work(info->monitor_wqueue,
                                                 &info->charge_stable_work,
@@ -1112,7 +1722,6 @@ adjust:
                info->soca->last_soc = info->soca->soc;
                info->soca->status = RICOH619_SOCA_DISP;
                info->soca->soc_delta = 0;
-               info->soca->update_count = 0;
 
        }
        mutex_unlock(&info->lock);
@@ -1254,6 +1863,8 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info)
        int i;
        int err;
        uint8_t val;
+       int cc_cap = 0;
+       bool is_charging = true;
 
        for (i = 0; i <= 10; i = i+1) {
                info->soca->ocv_table[i] = get_OCV_voltage(info, i);
@@ -1285,6 +1896,8 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info)
                                dev_err(info->dev, "Error in writing the control register\n");
                }
 
+               err = calc_capacity_in_period(info, &cc_cap, &is_charging, true);
+
                msleep(6000);
 
                err = ricoh619_write(info->dev->parent, CHGISET_REG, val);
@@ -1298,19 +1911,22 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info)
                                                         * 5000 / 4095;
        info->soca->n_cap = get_OCV_init_Data(info, 11);
 
-       info->soca->f_chg_margin = (get_OCV_voltage(info, 10) -
-                                                               get_OCV_voltage(info, 9)) / 10 * 3;
 
        info->soca->displayed_soc = 0;
+       info->soca->last_displayed_soc = 0;
        info->soca->suspend_soc = 0;
        info->soca->ready_fg = 0;
        info->soca->soc_delta = 0;
-       info->soca->update_count = 0;
+       info->soca->full_reset_count = 0;
+       info->soca->soc_full = 0;
+       info->soca->fc_cap = 0;
        info->soca->status = RICOH619_SOCA_START;
        /* stable count down 11->2, 1: reset; 0: Finished; */
        info->soca->stable_count = 11;
+       info->soca->chg_cmp_times = 0;
        info->soca->dischg_state = 0;
        info->soca->Vbat_ave = 0;
+       info->soca->Vbat_old = 0;
        info->soca->Vsys_ave = 0;
        info->soca->Ibat_ave = 0;
        info->soca->chg_count = 0;
@@ -1318,12 +1934,20 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info)
        info->soca->hurry_up_flg = 0;
        info->soca->re_cap_old = 0;
        info->soca->jt_limit = 0;
+       info->soca->zero_flg = 0;
+       info->soca->cc_cap_offset = 0;
+
+       for (i = 0; i < 11; i++) {
+               info->soca->ocv_table_low[i] = 0;
+       }
 
        for (i = 0; i < RICOH619_GET_CHARGE_NUM; i++) {
                info->soca->Vbat[i] = 0;
                info->soca->Vsys[i] = 0;
                info->soca->Ibat[i] = 0;
        }
+
+       g_full_flag = 0;
        
 #ifdef ENABLE_FG_KEEP_ON_MODE
        g_fg_on_mode = 1;
@@ -1371,6 +1995,67 @@ static int ricoh619_init_fgsoca(struct ricoh619_battery_info *info)
 }
 #endif
 
+static void ricoh619_charging_complete_work(struct work_struct *work)
+{
+       struct ricoh619_battery_info *info = container_of(work,
+               struct ricoh619_battery_info, charge_complete_ready.work);
+
+       uint8_t time_ov_flag;
+       RICOH_FG_DBG("PMU: %s\n", __func__);
+       RICOH_FG_DBG("info->chg_complete_rd_cnt = %d\n", info->chg_complete_rd_cnt);
+       RICOH_FG_DBG("info->chg_complete_rd_flag = %d\n", info->chg_complete_rd_flag);
+       RICOH_FG_DBG("info->chg_complete_tm_ov_flag = %d\n", info->chg_complete_tm_ov_flag);
+       
+       if(info->chg_complete_rd_flag == 1)
+       {
+               // start chg 99per to 100per timer
+               time_ov_flag = 0;
+               info->chg_complete_rd_flag = 2;
+               info->chg_complete_tm_ov_flag = 0;
+       }
+       else
+       {
+               if(info->capacity == 100)
+               {
+                       // battery arriver to 100% earlier than time ov
+                       time_ov_flag = 1;
+                       info->chg_complete_rd_cnt = 0;
+                       info->chg_complete_tm_ov_flag = 1;
+               }
+               else if(info->chg_complete_rd_cnt > RICOH619_TIME_CHG_COUNT)
+               {
+                       // chg timer ov before cap arrive to 100%
+                       time_ov_flag = 1;
+                       info->chg_complete_tm_ov_flag = 1;
+                       info->chg_complete_rd_cnt = 0;
+                       info->soca->status = RICOH619_SOCA_FULL;
+                       power_supply_changed(&info->battery);
+               }
+               else
+               {
+                       time_ov_flag = 0;
+                       info->chg_complete_tm_ov_flag = 0;
+               }
+       }
+
+       if ((time_ov_flag == 0) && (info->soca->chg_status == POWER_SUPPLY_STATUS_CHARGING))
+       {
+               info->chg_complete_rd_cnt++;
+               queue_delayed_work(info->monitor_wqueue, &info->charge_complete_ready, 
+                       RICOH619_TIME_CHG_STEP);
+       }
+       else
+       {
+               info->chg_complete_rd_flag = 0;
+       }
+
+       RICOH_FG_DBG("PMU2: %s return\n", __func__);
+       RICOH_FG_DBG("info->chg_complete_rd_cnt = %d\n", info->chg_complete_rd_cnt);
+       RICOH_FG_DBG("info->chg_complete_rd_flag = %d\n", info->chg_complete_rd_flag);
+       RICOH_FG_DBG("info->chg_complete_tm_ov_flag = %d\n", info->chg_complete_tm_ov_flag);
+       RICOH_FG_DBG("time_ov_flag = %d\n", time_ov_flag);
+
+}
 static void ricoh619_changed_work(struct work_struct *work)
 {
        struct ricoh619_battery_info *info = container_of(work,
@@ -1405,7 +2090,6 @@ static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita
 {
        int temp;
        int err = 0;
-       uint8_t val;
        int vfchg;
        uint8_t chgiset_org;
        uint8_t batset2_org;
@@ -1420,7 +2104,7 @@ static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita
 
        /* Check FG Reset */
        if (info->soca->ready_fg) {
-               temp = get_battery_temp(info) / 10;
+               temp = get_battery_temp_2(info) / 10;
        } else {
                RICOH_FG_DBG(KERN_INFO "JEITA: %s *** cannot update by resetting FG ******\n", __func__);
                goto out;
@@ -1515,6 +2199,7 @@ static int check_jeita_status(struct ricoh619_battery_info *info, bool *is_jeita
                                goto out;
                        }
                        info->soca->jt_limit = 0;
+                       *is_jeita_updated = true;
                } else
                        RICOH_FG_DBG(KERN_INFO "PMU: %s *** 12<Temp<50, already set vfchg==%d, so no need to update ******\n", 
                                        __func__, info->jt_vfchg_h);
@@ -1700,95 +2385,154 @@ static int Calc_Linear_Interpolation(int x0, int y0, int x1, int y1, int y)
        return x;
 }
 
-static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info)
+static void ricoh619_scaling_OCV_table(struct ricoh619_battery_info *info, int cutoff_vol, int full_vol, int *start_per, int *end_per)
 {
-       int             ret = 0;
-       int             ocv_table[11];
        int             i, j;
-       int             available_cap;
        int             temp;
-       int             start_par;
        int             percent_step;
        int             OCV_percent_new[11];
-       int             Rbat;
-       int             Ibat_min;
 
-       info->soca->target_vsys = info->fg_target_vsys;
-       info->soca->target_ibat = info->fg_target_ibat;
+       /* get ocv table. this table is calculated by Apprication */
+       //RICOH_FG_DBG("PMU : %s : original table\n",__func__);
+       for (i = 0; i <= 10; i = i+1) {
+               RICOH_FG_DBG(KERN_INFO "PMU: %s : %d0%% voltage = %d uV\n",
+                                __func__, i, info->soca->ocv_table_def[i]);
+       }
+       //RICOH_FG_DBG("PMU: %s : cutoff_vol %d full_vol %d\n",
+       //                       __func__, cutoff_vol,full_vol);
 
-       //for debug
-       RICOH_FG_DBG("PMU : %s : target_vsys is %d target_ibat is %d",__func__,info->soca->target_vsys,info->soca->target_ibat);
-       
-       if ((info->soca->target_ibat == 0) || (info->soca->target_vsys == 0)) { /* normal version */
-       } else {        /*Slice cutoff voltage version. */
-               /* get ocv table. this table is calculated by Apprication */
-               for (i = 0; i <= 10; i = i+1) {
-                       temp = (battery_init_para[info->num][i*2]<<8)
-                                | (battery_init_para[info->num][i*2+1]);
-                       /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
-                       temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
-                       ocv_table[i] = temp;
-                       
+       /* Check Start % */
+       if (info->soca->ocv_table_def[0] > cutoff_vol * 1000) {
+               *start_per = 0;
+               RICOH_FG_DBG("PMU : %s : setting value of cuttoff_vol(%d) is out of range(%d) \n",__func__, cutoff_vol, info->soca->ocv_table_def[0]);
+       } else {
+               for (i = 1; i < 11; i++) {
+                       if (info->soca->ocv_table_def[i] >= cutoff_vol * 1000) {
+                               /* unit is 0.001% */
+                               *start_per = Calc_Linear_Interpolation(
+                                       (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000,
+                                       info->soca->ocv_table_def[i], (cutoff_vol * 1000));
+                               break;
+                       }
+               }
+       }
+
+       /* Check End % */
+       for (i = 1; i < 11; i++) {
+               if (info->soca->ocv_table_def[i] >= full_vol * 1000) {
+                       /* unit is 0.001% */
+                       *end_per = Calc_Linear_Interpolation(
+                               (i-1)*1000, info->soca->ocv_table_def[i-1], i*1000,
+                                info->soca->ocv_table_def[i], (full_vol * 1000));
+                       break;
                }
+       }
 
-               /* get internal impedence */
-               temp =  (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]);
-               Rbat = temp * 1000 / 512 * 5000 / 4095;
+       /* calc new ocv percent */
+       percent_step = ( *end_per - *start_per) / 10;
+       //RICOH_FG_DBG("PMU : %s : percent_step is %d end per is %d start per is %d\n",__func__, percent_step, *end_per, *start_per);
 
-               Ibat_min = -1 * info->soca->target_ibat;
-               info->soca->Rsys = Rbat + 55;
-               info->soca->cutoff_ocv = info->soca->target_vsys - Ibat_min * info->soca->Rsys / 1000;
+       for (i = 0; i < 11; i++) {
+               OCV_percent_new[i]
+                        = *start_per + percent_step*(i - 0);
+       }
 
+       /* calc new ocv voltage */
+       for (i = 0; i < 11; i++) {
+               for (j = 1; j < 11; j++) {
+                       if (1000*j >= OCV_percent_new[i]) {
+                               temp = Calc_Linear_Interpolation(
+                                       info->soca->ocv_table_def[j-1], (j-1)*1000,
+                                       info->soca->ocv_table_def[j] , j*1000,
+                                        OCV_percent_new[i]);
 
-               RICOH_FG_DBG("PMU: -------  Rbat= %d: Rsys= %d: cutoff_ocv= %d: =======\n",
-                       Rbat, info->soca->Rsys, info->soca->cutoff_ocv);
+                               temp = ( (temp/1000) * 4095 ) / 5000;
 
-               /* Check Start % */
-               for (i = 1; i < 11; i++) {
-                       if (ocv_table[i] >= info->soca->cutoff_ocv * 10) {
-                               /* unit is 0.001% */
-                               start_par = Calc_Linear_Interpolation(
-                                       (i-1)*1000, ocv_table[i-1], i*1000,
-                                        ocv_table[i], (info->soca->cutoff_ocv * 10));
-                               i = 11;
+                               battery_init_para[info->num][i*2 + 1] = temp;
+                               battery_init_para[info->num][i*2] = temp >> 8;
+
+                               break;
                        }
                }
-               /* calc new ocv percent */
-               percent_step = (10000 - start_par) / 10;
+       }
+       RICOH_FG_DBG("PMU : %s : new table\n",__func__);
+       for (i = 0; i <= 10; i = i+1) {
+               temp = (battery_init_para[info->num][i*2]<<8)
+                        | (battery_init_para[info->num][i*2+1]);
+               /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
+               temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
+               RICOH_FG_DBG("PMU : %s : ocv_table %d is %d v\n",__func__, i, temp);
+       }
 
-               for (i = 0; i < 11; i++) {
-                       OCV_percent_new[i]
-                                = start_par + percent_step*(i - 0);
-               }
+}
 
-               /* calc new ocv voltage */
-               for (i = 0; i < 11; i++) {
-                       for (j = 1; j < 11; j++) {
-                               if (1000*j >= OCV_percent_new[i]) {
-                                       temp = Calc_Linear_Interpolation(
-                                               ocv_table[j-1], (j-1)*1000,
-                                                ocv_table[j] , j*1000,
-                                                OCV_percent_new[i]);
+static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info)
+{
+       int             ret = 0;
+       int             i;
+       int             full_ocv;
+       int             available_cap;
+       int             available_cap_ori;
+       int             temp;
+       int             temp1;
+       int             start_per = 0;
+       int             end_per = 0;
+       int             Rbat;
+       int             Ibat_min;
+       uint8_t val;
+       uint8_t val2;
+       uint8_t val_temp;
 
-                                       temp = temp * 4095 / 50000;
 
-                                       battery_init_para[info->num][i*2 + 1] = temp;
-                                       battery_init_para[info->num][i*2] = temp >> 8;
+       //get ocv table 
+       for (i = 0; i <= 10; i = i+1) {
+               info->soca->ocv_table_def[i] = get_OCV_voltage(info, i);
+               RICOH_FG_DBG(KERN_INFO "PMU: %s : %d0%% voltage = %d uV\n",
+                        __func__, i, info->soca->ocv_table_def[i]);
+       }
 
-                                       j = 11;
-                               }
-                       }
-               }
+       temp =  (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]);
+       Rbat = temp * 1000 / 512 * 5000 / 4095;
+       info->soca->Rsys = Rbat + 55;
+
+       if ((info->fg_target_ibat == 0) || (info->fg_target_vsys == 0)) {       /* normal version */
+
+               temp =  (battery_init_para[info->num][22]<<8) | (battery_init_para[info->num][23]);
+               //fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG,
+               //                              0x7fff);
+
+               info->soca->target_ibat = temp*2/10; /* calc 0.2C*/
+               temp1 =  (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]);
+
+               info->soca->target_vsys = temp1 + ( info->soca->target_ibat * info->soca->Rsys ) / 1000;
+               
 
-               for (i = 0; i <= 10; i = i+1) {
-                       temp = (battery_init_para[info->num][i*2]<<8)
-                                | (battery_init_para[info->num][i*2+1]);
-                       /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
-                       temp = ((temp * 50000 * 10 / 4095) + 5) / 10;
-                       RICOH_FG_DBG("PMU: -------  ocv_table[%d]= %d: =======\n",
-                               i, temp);
+       } else {
+               info->soca->target_ibat = info->fg_target_ibat;
+               /* calc min vsys value */
+               temp1 =  (battery_init_para[info->num][0]<<8) | (battery_init_para[info->num][1]);
+               temp = temp1 + ( info->soca->target_ibat * info->soca->Rsys ) / 1000;
+               if( temp < info->fg_target_vsys) {
+                       info->soca->target_vsys = info->fg_target_vsys;
+               } else {
+                       info->soca->target_vsys = temp;
+                       RICOH_FG_DBG("PMU : %s : setting value of target vsys(%d) is out of range(%d)\n",__func__, info->fg_target_vsys, temp);
                }
+       }
+
+       //for debug
+       RICOH_FG_DBG("PMU : %s : target_vsys is %d target_ibat is %d\n",__func__,info->soca->target_vsys,info->soca->target_ibat);
+       
+       if ((info->soca->target_ibat == 0) || (info->soca->target_vsys == 0)) { /* normal version */
+       } else {        /*Slice cutoff voltage version. */
+
+               Ibat_min = -1 * info->soca->target_ibat;
+               info->soca->cutoff_ocv = info->soca->target_vsys - Ibat_min * info->soca->Rsys / 1000;
+               
+               full_ocv = (battery_init_para[info->num][20]<<8) | (battery_init_para[info->num][21]);
+               full_ocv = full_ocv * 5000 / 4095;
 
+               ricoh619_scaling_OCV_table(info, info->soca->cutoff_ocv, full_ocv, &start_per, &end_per);
 
                /* calc available capacity */
                /* get avilable capacity */
@@ -1797,21 +2541,103 @@ static int ricoh619_set_OCV_table(struct ricoh619_battery_info *info)
                                         | (battery_init_para[info->num][23]);
 
                available_cap = available_cap
-                        * ((10000 - start_par) / 100) / 100 ;
+                        * ((10000 - start_per) / 100) / 100 ;
 
 
                battery_init_para[info->num][23] =  available_cap;
                battery_init_para[info->num][22] =  available_cap >> 8;
 
        }
-       ret = ricoh619_bulk_writes_bank1(info->dev->parent,
-                        BAT_INIT_TOP_REG, 32, battery_init_para[info->num]);
+       ret = ricoh619_clr_bits(info->dev->parent, FG_CTRL_REG, 0x01);
+       if (ret < 0) {
+               dev_err(info->dev, "error in FG_En off\n");
+               goto err;
+       }
+       /////////////////////////////////
+       ret = ricoh619_read_bank1(info->dev->parent, 0xDC, &val);
        if (ret < 0) {
                dev_err(info->dev, "batterry initialize error\n");
-               return ret;
+               goto err;
        }
 
-       return 1;
+       val_temp = val;
+       val     &= 0x0F; //clear bit 4-7
+       val     |= 0x10; //set bit 4
+       
+       ret = ricoh619_write_bank1(info->dev->parent, 0xDC, val);
+       if (ret < 0) {
+               dev_err(info->dev, "batterry initialize error\n");
+               goto err;
+       }
+       
+       ret = ricoh619_read_bank1(info->dev->parent, 0xDC, &val2);
+       if (ret < 0) {
+               dev_err(info->dev, "batterry initialize error\n");
+               goto err;
+       }
+
+       ret = ricoh619_write_bank1(info->dev->parent, 0xDC, val_temp);
+       if (ret < 0) {
+               dev_err(info->dev, "batterry initialize error\n");
+               goto err;
+       }
+
+       RICOH_FG_DBG("PMU : %s : original 0x%x, before 0x%x, after 0x%x\n",__func__, val_temp, val, val2);
+       
+       if (val != val2) {
+               ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+                               BAT_INIT_TOP_REG, 30, battery_init_para[info->num]);
+               if (ret < 0) {
+                       dev_err(info->dev, "batterry initialize error\n");
+                       goto err;
+               }
+       } else {
+               ret = ricoh619_read_bank1(info->dev->parent, 0xD2, &val);
+               if (ret < 0) {
+               dev_err(info->dev, "batterry initialize error\n");
+               goto err;
+               }
+       
+               ret = ricoh619_read_bank1(info->dev->parent, 0xD3, &val2);
+               if (ret < 0) {
+                       dev_err(info->dev, "batterry initialize error\n");
+                       goto err;
+               }
+               
+               available_cap_ori = val2 + (val << 8);
+               available_cap = battery_init_para[info->num][23]
+                                               + (battery_init_para[info->num][22] << 8);
+
+               if (available_cap_ori == available_cap) {
+                       ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+                               BAT_INIT_TOP_REG, 22, battery_init_para[info->num]);
+                       if (ret < 0) {
+                               dev_err(info->dev, "batterry initialize error\n");
+                               return ret;
+                       }
+                       
+                       for (i = 0; i < 6; i++) {
+                               ret = ricoh619_write_bank1(info->dev->parent, 0xD4+i, battery_init_para[info->num][24+i]);
+                               if (ret < 0) {
+                                       dev_err(info->dev, "batterry initialize error\n");
+                                       return ret;
+                               }
+                       }
+               } else {
+                       ret = ricoh619_bulk_writes_bank1(info->dev->parent,
+                               BAT_INIT_TOP_REG, 30, battery_init_para[info->num]);
+                       if (ret < 0) {
+                               dev_err(info->dev, "batterry initialize error\n");
+                               goto err;
+                       }
+               }
+       }
+
+       ////////////////////////////////
+
+       return 0;
+err:
+       return ret;
 }
 
 /* Initial setting of battery */
@@ -1824,13 +2650,13 @@ static int ricoh619_init_battery(struct ricoh619_battery_info *info)
        /* -------------------------- */
 #ifdef ENABLE_FUEL_GAUGE_FUNCTION
 
-       /* set kanwa state */
+       /* set relaxation state */
        if (RICOH619_REL1_SEL_VALUE > 240)
                val = 0x0F;
        else
                val = RICOH619_REL1_SEL_VALUE / 16 ;
 
-       /* set kanwa state */
+       /* set relaxation state */
        if (RICOH619_REL2_SEL_VALUE > 120)
                val2 = 0x0F;
        else
@@ -1854,15 +2680,22 @@ static int ricoh619_init_battery(struct ricoh619_battery_info *info)
                return ret;
        }
 
-       ret = ricoh619_read(info->dev->parent, FG_CTRL_REG, &val);
+//     ret = ricoh619_read(info->dev->parent, FG_CTRL_REG, &val);
+//     if (ret < 0) {
+//             dev_err(info->dev, "Error in reading the control register\n");
+//             return ret;
+//     }
+
+//     val = (val & 0x10) >> 4;
+//     info->first_pwon = (val == 0) ? 1 : 0;
+       ret = ricoh619_read(info->dev->parent, PSWR_REG, &val);
        if (ret < 0) {
-               dev_err(info->dev, "Error in reading the control register\n");
+               dev_err(info->dev,"Error in reading PSWR_REG %d\n", ret);
                return ret;
        }
-
-       val = (val & 0x10) >> 4;
        info->first_pwon = (val == 0) ? 1 : 0;
-
+       g_soc = val & 0x7f;
+       
        ret = ricoh619_set_OCV_table(info);
        if (ret < 0) {
                dev_err(info->dev, "Error in writing the OCV Tabler\n");
@@ -1877,7 +2710,7 @@ static int ricoh619_init_battery(struct ricoh619_battery_info *info)
 
 #endif
 
-       ret = ricoh619_write(info->dev->parent, VINDAC_REG, 0x01);
+       ret = ricoh619_write(info->dev->parent, VINDAC_REG, 0x03);
        if (ret < 0) {
                dev_err(info->dev, "Error in writing the control register\n");
                return ret;
@@ -1899,6 +2732,10 @@ static int ricoh619_init_charger(struct ricoh619_battery_info *info)
        uint8_t val2;
        uint8_t val3;
        int charge_status;
+       int     vfchg_val;
+       int     icchg_val;
+       int     rbat;
+       int     temp;
 
        info->chg_ctr = 0;
        info->chg_stat1 = 0;
@@ -1998,7 +2835,7 @@ static int ricoh619_init_charger(struct ricoh619_battery_info *info)
        if ((info->ch_icchg != 0xFF) || (info->ch_icchg <= 0x03)) {
                val3 = info->ch_icchg << 6;
        } else { /* Keep OTP value */
-               val3 = (val & 0xC);
+               val3 = (val & 0xC0);
        }
 
        val = val2 + val3;
@@ -2151,6 +2988,41 @@ static int ricoh619_init_charger(struct ricoh619_battery_info *info)
                        goto free_device;
                }
        }
+       /* get OCV100_min, OCV100_min*/
+       temp = (battery_init_para[info->num][24]<<8) | (battery_init_para[info->num][25]);
+       rbat = temp * 1000 / 512 * 5000 / 4095;
+       
+       /* get vfchg value */
+       err = ricoh619_read(info->dev->parent, BATSET2_REG, &val);
+       if (err < 0) {
+               dev_err(info->dev, "Error in reading the batset2reg\n");
+               goto free_device;
+       }
+       val &= 0x70;
+       val2 = val >> 4;
+       if (val2 <= 3) {
+               vfchg_val = 4050 + val2 * 50;
+       } else {
+               vfchg_val = 4350;
+       }
+       RICOH_FG_DBG("PMU : %s : test test val %d, val2 %d vfchg %d\n", __func__, val, val2, vfchg_val);
+
+       /* get  value */
+       err = ricoh619_read(info->dev->parent, CHGISET_REG, &val);
+       if (err < 0) {
+               dev_err(info->dev, "Error in reading the chgisetreg\n");
+               goto free_device;
+       }
+       val &= 0xC0;
+       val2 = val >> 6;
+       icchg_val = 50 + val2 * 50;
+       RICOH_FG_DBG("PMU : %s : test test val %d, val2 %d icchg %d\n", __func__, val, val2, icchg_val);
+
+       info->soca->OCV100_min = ( vfchg_val * 99 / 100 - (icchg_val * (rbat +20))/1000 - 20 ) * 1000;
+       info->soca->OCV100_max = ( vfchg_val * 101 / 100 - (icchg_val * (rbat +20))/1000 + 20 ) * 1000;
+       
+       RICOH_FG_DBG("PMU : %s : 100 min %d, 100 max %d vfchg %d icchg %d rbat %d\n",__func__,
+       info->soca->OCV100_min,info->soca->OCV100_max,vfchg_val,icchg_val,rbat);
 
 #ifdef ENABLE_LOW_BATTERY_DETECTION
        /* Set ADRQ=00 to stop ADC */
@@ -2160,9 +3032,11 @@ static int ricoh619_init_charger(struct ricoh619_battery_info *info)
        /* Set ADC auto conversion interval 250ms */
        ricoh619_write(info->dev->parent, RICOH619_ADC_CNT2, 0x0);
        /* Enable VSYS pin conversion in auto-ADC */
-       ricoh619_write(info->dev->parent, RICOH619_ADC_CNT1, 0x10);
-       /* Set VSYS threshold low voltage = 3.50v */
-       ricoh619_write(info->dev->parent, RICOH619_ADC_VSYS_THL, 0x77);
+//     ricoh619_write(info->dev->parent, RICOH619_ADC_CNT1, 0x10);
+       ricoh619_write(info->dev->parent, RICOH619_ADC_CNT1, 0x16);
+       /* Set VSYS threshold low voltage value = (voltage(V)*255)/(3*2.5) */
+       val = info->alarm_vol_mv * 255 / 7500;
+       ricoh619_write(info->dev->parent, RICOH619_ADC_VSYS_THL, val);
        /* Start auto-mode & average 4-time conversion mode for ADC */
        ricoh619_write(info->dev->parent, RICOH619_ADC_CNT3, 0x28);
        /* Enable master ADC INT */
@@ -2268,6 +3142,47 @@ static int get_power_supply_status(struct ricoh619_battery_info *info)
        return info->soca->chg_status;
 }
 
+static int get_power_supply_Android_status(struct ricoh619_battery_info *info)
+{
+
+       get_power_supply_status(info);
+
+       /* get  power supply status */
+       if (info->entry_factory_mode)
+                       return POWER_SUPPLY_STATUS_NOT_CHARGING;
+
+       switch (info->soca->chg_status) {
+               case    POWER_SUPPLY_STATUS_UNKNOWN:
+                               return POWER_SUPPLY_STATUS_UNKNOWN;
+                               break;
+
+               case    POWER_SUPPLY_STATUS_NOT_CHARGING:
+                               return POWER_SUPPLY_STATUS_NOT_CHARGING;
+                               break;
+
+               case    POWER_SUPPLY_STATUS_DISCHARGING:
+                               return POWER_SUPPLY_STATUS_DISCHARGING;
+                               break;
+
+               case    POWER_SUPPLY_STATUS_CHARGING:
+                               return POWER_SUPPLY_STATUS_CHARGING;
+                               break;
+
+               case    POWER_SUPPLY_STATUS_FULL:
+                               if(info->soca->displayed_soc == 100 * 100) {
+                                       return POWER_SUPPLY_STATUS_FULL;
+                               } else {
+                                       return POWER_SUPPLY_STATUS_CHARGING;
+                               }
+                               break;
+               default:
+                               return POWER_SUPPLY_STATUS_UNKNOWN;
+                               break;
+       }
+
+       return POWER_SUPPLY_STATUS_UNKNOWN;
+}
+extern struct ricoh619 *g_ricoh619;
 static void charger_irq_work(struct work_struct *work)
 {
        struct ricoh619_battery_info *info
@@ -2277,18 +3192,67 @@ static void charger_irq_work(struct work_struct *work)
        RICOH_FG_DBG("PMU:%s In\n", __func__);
 
        power_supply_changed(&info->battery);
+       power_supply_changed(&powerac);
+       power_supply_changed(&powerusb);
 
-       mutex_lock(&info->lock);
+//     mutex_lock(&info->lock);
        
        if (info->chg_stat1 & 0x01) {
                ricoh619_read(info->dev->parent, CHGSTATE_REG, &reg_val);
-               if (reg_val & 0x40) { /* USE ADP */
-                       /* set adp limit current 2A */
-                       ricoh619_write(info->dev->parent, REGISET1_REG, 0x13);
-                       /* set charge current 2A */
-                       ricoh619_write(info->dev->parent, CHGISET_REG, 0xD3);
-               }
-               else if (reg_val & 0x80) { /* USE USB */
+               if (reg_val & 0x40) { /* USE ADP */     
+                       #ifdef SUPPORT_USB_CONNECT_TO_ADP
+                               int i;
+                               for(i =0;i<60;i++){
+                               RICOH_FG_DBG("PMU:%s usb det dwc_otg_check_dpdm =%d\n", __func__,dwc_otg_check_dpdm(0));
+                               if(2 == dwc_otg_check_dpdm(0)){
+                               /* set adp limit current 2A */
+                               ricoh619_write(info->dev->parent, REGISET1_REG, 0x16);
+                               /* set charge current 2A */
+                               ricoh619_write(info->dev->parent, CHGISET_REG, 0xD3); 
+                               }
+                               else {
+                               /* set adp limit current 500ma */
+                               ricoh619_write(info->dev->parent, REGISET1_REG, 0x04);
+                               /* set charge current 500ma */
+                               ricoh619_write(info->dev->parent, CHGISET_REG, 0xc4); 
+                               }
+                               
+                               power_supply_changed(&info->battery);
+                               power_supply_changed(&powerac);
+                               power_supply_changed(&powerusb);
+                               msleep(100);
+                               }
+                       #else //support adp and usb chag
+                       if (gpio_is_valid(g_ricoh619->dc_det)){
+                               ret = gpio_request(g_ricoh619->dc_det, "ricoh619_dc_det");
+                               if (ret < 0) {
+                                       RICOH_FG_DBG("Failed to request gpio %d with ret:""%d\n",g_ricoh619->dc_det, ret);
+                               }
+                               gpio_direction_input(g_ricoh619->dc_det);
+                               ret = gpio_get_value(g_ricoh619->dc_det);
+
+                               if (ret ==0){
+                                       /* set adp limit current 2A */
+                                       ricoh619_write(info->dev->parent, REGISET1_REG, 0x16);
+                                       /* set charge current 2A */
+                                       ricoh619_write(info->dev->parent, CHGISET_REG, 0xD3);
+                               }
+                               else {
+                                       /* set adp limit current 500ma */
+                                       ricoh619_write(info->dev->parent, REGISET1_REG, 0x04);
+                                       /* set charge current 500ma */
+                                       ricoh619_write(info->dev->parent, CHGISET_REG, 0xc4); 
+                               }
+                               gpio_free(g_ricoh619->dc_det);
+                       }
+                       else{
+                               /* set adp limit current 2A */
+                               ricoh619_write(info->dev->parent, REGISET1_REG, 0x16);
+                               /* set charge current 2A */
+                               ricoh619_write(info->dev->parent, CHGISET_REG, 0xD3); 
+                       }
+                       #endif
+               } else if (reg_val & 0x80) { /* USE ONLY USB */
                        queue_work(info->usb_workqueue, &info->usb_irq_work);
                }
        }
@@ -2309,7 +3273,7 @@ static void charger_irq_work(struct work_struct *work)
                         "%s(): Error in enable charger mask INT %d\n",
                         __func__, ret);
 
-       mutex_unlock(&info->lock);
+//     mutex_unlock(&info->lock);
        RICOH_FG_DBG("PMU:%s Out\n", __func__);
 }
 
@@ -2339,14 +3303,17 @@ static void ricoh619_usb_charge_det(void)
 {
        struct ricoh619 *ricoh619 = g_ricoh619;
        ricoh619_set_bits(ricoh619->dev,REGISET2_REG,(1 << 7));  //set usb limit current  when SDP or other mode
-       if(2 == dwc_vbus_status()){
-       ricoh619_write(ricoh619->dev,REGISET2_REG,0x13);  //set usb limit current  2A
+       RICOH_FG_DBG("PMU:%s usb det dwc_otg_check_dpdm =%d\n", __func__,dwc_otg_check_dpdm(0));
+       if(2 == dwc_otg_check_dpdm(0)){
+       ricoh619_write(ricoh619->dev,REGISET2_REG,0x16);  //set usb limit current  2A
        ricoh619_write(ricoh619->dev,CHGISET_REG,0xD3);  //set charge current  2A
        }
-       else if(1 == dwc_vbus_status()){
+       else {
        ricoh619_write(ricoh619->dev,REGISET2_REG,0x04);  //set usb limit current  500ma
        ricoh619_write(ricoh619->dev,CHGISET_REG,0xC4);  //set charge current   500ma
        }
+       power_supply_changed(&powerac);
+       power_supply_changed(&powerusb);
 }
 
 static void usb_det_irq_work(struct work_struct *work)
@@ -2355,11 +3322,12 @@ static void usb_det_irq_work(struct work_struct *work)
                 struct ricoh619_battery_info, usb_irq_work);
        int ret = 0;
        uint8_t sts;
-       int time =0;
 
        RICOH_FG_DBG("PMU:%s In\n", __func__);
 
        power_supply_changed(&info->battery);
+       power_supply_changed(&powerac);
+       power_supply_changed(&powerusb);
 
        mutex_lock(&info->lock);
 
@@ -2377,35 +3345,22 @@ static void usb_det_irq_work(struct work_struct *work)
                dev_err(info->dev, "Error in reading the control register\n");
 
        sts &= 0x02;
-       if (sts) {
-               //time = 60;
-               //do {
-               //ricoh619_usb_charge_det();
-               //time --;
-               //mdelay(1000);
-               //}while(time >0);
-       
-       } else {
-               /*********************/
-               /* No process ??     */
-               /*********************/
-       }
+       if (sts)
+               ricoh619_usb_charge_det();
        
        RICOH_FG_DBG("PMU:%s Out\n", __func__);
 }
 
-extern void rk28_send_wakeup_key(void);
+extern void rk_send_wakeup_key(void);
 static irqreturn_t charger_in_isr(int irq, void *battery_info)
 {
        struct ricoh619_battery_info *info = battery_info;
-       struct ricoh619 *ricoh619 = g_ricoh619;
-
        RICOH_FG_DBG("PMU:%s\n", __func__); 
 
        info->chg_stat1 |= 0x01;
 
        queue_work(info->workqueue, &info->irq_work);
-//     rk28_send_wakeup_key();
+//     rk_send_wakeup_key();
 
        return IRQ_HANDLED;
 }
@@ -2417,7 +3372,7 @@ static irqreturn_t charger_complete_isr(int irq, void *battery_info)
 
        info->chg_stat1 |= 0x02;
        queue_work(info->workqueue, &info->irq_work);
-       rk28_send_wakeup_key();
+//     rk_send_wakeup_key();
        
        return IRQ_HANDLED;
 }
@@ -2435,7 +3390,7 @@ static irqreturn_t charger_usb_isr(int irq, void *battery_info)
        info->soca->chg_count = 0;
 
 //     queue_work(info->usb_workqueue, &info->usb_irq_work);
-//     rk28_send_wakeup_key(); 
+       rk_send_wakeup_key(); 
         
        if (RICOH619_SOCA_UNSTABLE == info->soca->status
                || RICOH619_SOCA_FG_RESET == info->soca->status)
@@ -2447,12 +3402,11 @@ static irqreturn_t charger_usb_isr(int irq, void *battery_info)
 static irqreturn_t charger_adp_isr(int irq, void *battery_info)
 {
        struct ricoh619_battery_info *info = battery_info;
-       struct ricoh619 *ricoh619 = g_ricoh619;
        RICOH_FG_DBG("PMU:%s\n", __func__);
 
        info->chg_ctr |= 0x01;
        queue_work(info->workqueue, &info->irq_work);
-       rk28_send_wakeup_key(); 
+       rk_send_wakeup_key(); 
 
        info->soca->dischg_state = 0;
        info->soca->chg_count = 0;
@@ -2484,12 +3438,53 @@ static irqreturn_t adc_vsysl_isr(int irq, void *battery_info)
 
        RICOH_FG_DBG("PMU:%s\n", __func__);
 //     ricoh619_write(info->dev->parent, RICOH619_INT_EN_ADC1, 0x10);
-//     rk28_send_wakeup_key(); 
+       rk_send_wakeup_key(); 
+
+       return IRQ_HANDLED;
+}
+#endif
+#ifdef RICOH619_VADP_DROP_WORK
+static void vadp_drop_irq_work(struct work_struct *work)
+{
+       struct ricoh619_battery_info *info = container_of(work,
+                struct ricoh619_battery_info, vadp_drop_work.work);
+
+       int ret = 0;
+       uint8_t data[6];
+       u16 reg[2];
+
+       RICOH_FG_DBG("PMU vadp_drop_work:%s In\n", __func__);
+       mutex_lock(&info->lock);        
+       ret = ricoh619_read(info->dev->parent, 0x6a, &data[0]);
+       ret = ricoh619_read(info->dev->parent, 0x6b, &data[1]);
+       ret = ricoh619_read(info->dev->parent, 0x6c, &data[2]);
+       ret = ricoh619_read(info->dev->parent, 0x6d, &data[3]);
+       ret = ricoh619_read(info->dev->parent, CHGSTATE_REG,&data[4]);
+       reg[0]= (data[0]<<4) |data[1];
+       reg[1]= (data[2]<<4) |data[3];
+
+//     printk("PMU vadp_drop:%s In %08x %08x %08x %08x %08x %08x %d\n", __func__,data[0],data[1],data[2],data[3],reg[0],reg[1],ret);   
+       if ((2*(reg[0] +82)) > 3*reg[1]){
+               ricoh619_write(info->dev->parent, 0xb3, 0x28);
+//             printk("PMU vadp_drop charger disable:%s In  %08x %08x\n", __func__,reg[0],reg[1]); 
+       }
+       else if(data[4] & 0xc0){
+               ret = ricoh619_read(info->dev->parent, 0xb3, &data[5]);
+//              printk("PMU charger is disabled:%s data[4]= %08x data[5]=%08x\n", __func__,data[4],data[5]);
+               if(((data[5] & 0x03) ==0)|| ((data[5] & 0x08)==0)){
+                       ricoh619_write(info->dev->parent, 0xb3, 0x23);
+                        ret = ricoh619_read(info->dev->parent, 0xb3, &data[5]);
+//                     printk("PMU charger enable:%s data[4]= %08x data[5]=%08x\n", __func__,data[4],data[5]);
+               }
+       }
+       power_supply_changed(&info->battery);
+       power_supply_changed(&powerac);
+       power_supply_changed(&powerusb);
+       mutex_unlock(&info->lock);
+       queue_delayed_work(info->monitor_wqueue, &info->vadp_drop_work,3*HZ);
 
-       return IRQ_HANDLED;
 }
 #endif
-
 /*
  * Get Charger Priority
  * - get higher-priority between VADP and VUSB
@@ -2497,6 +3492,7 @@ static irqreturn_t adc_vsysl_isr(int irq, void *battery_info)
  *         true : VUSB
  *         false: VADP
  */
+ /*
 static int get_charge_priority(struct ricoh619_battery_info *info, bool *data)
 {
        int ret = 0;
@@ -2508,6 +3504,7 @@ static int get_charge_priority(struct ricoh619_battery_info *info, bool *data)
 
        return ret;
 }
+*/
 
 /*
  * Set Charger Priority
@@ -2516,18 +3513,20 @@ static int get_charge_priority(struct ricoh619_battery_info *info, bool *data)
  *         true : VUSB
  *         false: VADP
  */
+ /*
 static int set_charge_priority(struct ricoh619_battery_info *info, bool *data)
 {
        int ret = 0;
-       uint8_t val = 0;
+       uint8_t val = 0x80;
 
-       val = *data << 7;
-       val &= 0x80;
+       if (*data == 1)
+               ret = ricoh619_set_bits(info->dev->parent, CHGCTL1_REG, val);
+       else
+               ret = ricoh619_clr_bits(info->dev->parent, CHGCTL1_REG, val);
 
-       ret = ricoh619_set_bits(info->dev->parent, CHGCTL1_REG, val);
        return ret;
 }
-
+*/
 #ifdef ENABLE_FUEL_GAUGE_FUNCTION
 static int get_check_fuel_gauge_reg(struct ricoh619_battery_info *info,
                                         int Reg_h, int Reg_l, int enable_bit)
@@ -2572,7 +3571,7 @@ static int calc_capacity(struct ricoh619_battery_info *info)
        int nt;
        int temperature;
 
-       temperature = get_battery_temp(info) / 10; /* unit 0.1 degree -> 1 degree */
+       temperature = get_battery_temp_2(info) / 10; /* unit 0.1 degree -> 1 degree */
 
        if (temperature >= 25) {
                nt = 0;
@@ -2591,9 +3590,59 @@ static int calc_capacity(struct ricoh619_battery_info *info)
 
        temp = capacity * 100 * 100 / (10000 - nt);
 
+       temp = min(100, temp);
+       temp = max(0, temp);
+       
        return temp;            /* Unit is 1% */
 }
 
+static int calc_capacity_2(struct ricoh619_battery_info *info)
+{
+       uint8_t val;
+       long capacity;
+       int re_cap, fa_cap;
+       int temp;
+       int ret = 0;
+       int nt;
+       int temperature;
+
+       temperature = get_battery_temp_2(info) / 10; /* unit 0.1 degree -> 1 degree */
+
+       if (temperature >= 25) {
+               nt = 0;
+       } else if (temperature >= 5) {
+               nt = (25 - temperature) * RICOH619_TAH_SEL2 * 625 / 100;
+       } else {
+               nt = (625  + (5 - temperature) * RICOH619_TAL_SEL2 * 625 / 100);
+       }
+
+       re_cap = get_check_fuel_gauge_reg(info, RE_CAP_H_REG, RE_CAP_L_REG,
+                                               0x7fff);
+       fa_cap = get_check_fuel_gauge_reg(info, FA_CAP_H_REG, FA_CAP_L_REG,
+                                               0x7fff);
+
+       if (fa_cap != 0) {
+               capacity = ((long)re_cap * 100 * 100 / fa_cap);
+               capacity = (long)(min(10000, (int)capacity));
+               capacity = (long)(max(0, (int)capacity));
+       } else {
+               ret = ricoh619_read(info->dev->parent, SOC_REG, &val);
+               if (ret < 0) {
+                       dev_err(info->dev, "Error in reading the control register\n");
+                       return ret;
+               }
+               capacity = (long)val * 100;
+       }
+       
+
+       temp = (int)(capacity * 100 * 100 / (10000 - nt));
+
+       temp = min(10000, temp);
+       temp = max(0, temp);
+
+       return temp;            /* Unit is 0.01% */
+}
+
 static int get_battery_temp(struct ricoh619_battery_info *info)
 {
        int ret = 0;
@@ -2624,6 +3673,141 @@ static int get_battery_temp(struct ricoh619_battery_info *info)
        return ret;
 }
 
+static int get_battery_temp_2(struct ricoh619_battery_info *info)
+{
+       uint8_t reg_buff[2];
+       long temp, temp_off, temp_gain;
+       bool temp_sign, temp_off_sign, temp_gain_sign;
+       int Vsns = 0;
+       int Iout = 0;
+       int Vthm, Rthm;
+       int reg_val = 0;
+       int new_temp;
+       long R_ln1, R_ln2;
+       int ret = 0;
+
+       /* Calculate TEMP */
+       ret = get_check_fuel_gauge_reg(info, TEMP_1_REG, TEMP_2_REG, 0x0fff);
+       if (ret < 0) {
+               dev_err(info->dev, "Error in reading the fuel gauge register\n");
+               goto out;
+       }
+
+       reg_val = ret;
+       temp_sign = (reg_val & 0x0800) >> 11;
+       reg_val = (reg_val & 0x07ff);
+
+       if (temp_sign == 0)     /* positive value part */
+               /* the unit is 0.0001 degree */
+               temp = (long)reg_val * 625;
+       else {  /*negative value part */
+               reg_val = (~reg_val + 1) & 0x7ff;
+               temp = -1 * (long)reg_val * 625;
+       }
+
+       /* Calculate TEMP_OFF */
+       ret = ricoh619_bulk_reads_bank1(info->dev->parent,
+                                       TEMP_OFF_H_REG, 2, reg_buff);
+       if (ret < 0) {
+               dev_err(info->dev, "Error in reading the fuel gauge register\n");
+               goto out;
+       }
+
+       reg_val = reg_buff[0] << 8 | reg_buff[1];
+       temp_off_sign = (reg_val & 0x0800) >> 11;
+       reg_val = (reg_val & 0x07ff);
+
+       if (temp_off_sign == 0) /* positive value part */
+               /* the unit is 0.0001 degree */
+               temp_off = (long)reg_val * 625;
+       else {  /*negative value part */
+               reg_val = (~reg_val + 1) & 0x7ff;
+               temp_off = -1 * (long)reg_val * 625;
+       }
+
+       /* Calculate TEMP_GAIN */
+       ret = ricoh619_bulk_reads_bank1(info->dev->parent,
+                                       TEMP_GAIN_H_REG, 2, reg_buff);
+       if (ret < 0) {
+               dev_err(info->dev, "Error in reading the fuel gauge register\n");
+               goto out;
+       }
+
+       reg_val = reg_buff[0] << 8 | reg_buff[1];
+       temp_gain_sign = (reg_val & 0x0800) >> 11;
+       reg_val = (reg_val & 0x07ff);
+
+       if (temp_gain_sign == 0)        /* positive value part */
+               /* 1 unit is 0.000488281. the result is 0.01 */
+               temp_gain = (long)reg_val * 488281 / 100000;
+       else {  /*negative value part */
+               reg_val = (~reg_val + 1) & 0x7ff;
+               temp_gain = -1 * (long)reg_val * 488281 / 100000;
+       }
+
+       /* Calculate VTHM */
+       if (0 != temp_gain)
+               Vthm = (int)((temp - temp_off) / 4095 * 2500 / temp_gain);
+       else {
+               RICOH_FG_DBG("PMU %s Skip to compensate temperature\n", __func__);
+               goto out;
+       }
+
+       ret = measure_Ibatt_FG(info, &Iout);
+       Vsns = Iout * 2 / 100;
+
+       if (temp < -120000) {
+               /* Low Temperature */
+               if (0 != (2500 - Vthm)) {
+                       Rthm = 10 * 10 * (Vthm - Vsns) / (2500 - Vthm);
+               } else {
+                       RICOH_FG_DBG("PMU %s Skip to compensate temperature\n", __func__);
+                       goto out;
+               }
+
+               R_ln1 = Rthm / 10;
+               R_ln2 =  (R_ln1 * R_ln1 * R_ln1 * R_ln1 * R_ln1 / 100000
+                       - R_ln1 * R_ln1 * R_ln1 * R_ln1 * 2 / 100
+                       + R_ln1 * R_ln1 * R_ln1 * 11
+                       - R_ln1 * R_ln1 * 2980
+                       + R_ln1 * 449800
+                       - 784000) / 10000;
+
+               /* the unit of new_temp is 0.1 degree */
+               new_temp = (int)((100 * 1000 * B_VALUE / (R_ln2 + B_VALUE * 100 * 1000 / 29815) - 27315) / 10);
+               RICOH_FG_DBG("PMU %s low temperature %d\n", __func__, new_temp/10);  
+       } else if (temp > 520000) {
+               /* High Temperature */
+               if (0 != (2500 - Vthm)) {
+                       Rthm = 100 * 10 * (Vthm - Vsns) / (2500 - Vthm);
+               } else {
+                       RICOH_FG_DBG("PMU %s Skip to compensate temperature\n", __func__);
+                       goto out;
+               }
+               RICOH_FG_DBG("PMU %s [Rthm] Rthm %d[ohm]\n", __func__, Rthm);
+
+               R_ln1 = Rthm / 10;
+               R_ln2 =  (R_ln1 * R_ln1 * R_ln1 * R_ln1 * R_ln1 / 100000 * 15652 / 100
+                       - R_ln1 * R_ln1 * R_ln1 * R_ln1 / 1000 * 23103 / 100
+                       + R_ln1 * R_ln1 * R_ln1 * 1298 / 100
+                       - R_ln1 * R_ln1 * 35089 / 100
+                       + R_ln1 * 50334 / 10
+                       - 48569) / 100;
+               /* the unit of new_temp is 0.1 degree */
+               new_temp = (int)((100 * 100 * B_VALUE / (R_ln2 + B_VALUE * 100 * 100 / 29815) - 27315) / 10);
+               RICOH_FG_DBG("PMU %s high temperature %d\n", __func__, new_temp/10);  
+       } else {
+               /* the unit of new_temp is 0.1 degree */
+               new_temp = temp / 1000;
+       }
+
+       return new_temp;
+
+out:
+       new_temp = get_battery_temp(info);
+       return new_temp;
+}
+#if 0
 static int get_time_to_empty(struct ricoh619_battery_info *info)
 {
        int ret = 0;
@@ -2657,24 +3841,29 @@ static int get_time_to_full(struct ricoh619_battery_info *info)
 
        return  ret;
 }
-
+#endif
 /* battery voltage is get from Fuel gauge */
 static int measure_vbatt_FG(struct ricoh619_battery_info *info, int *data)
 {
        int ret = 0;
 
-       ret = get_check_fuel_gauge_reg(info, VOLTAGE_1_REG, VOLTAGE_2_REG,
-                                                               0x0fff);
-       if (ret < 0) {
-               dev_err(info->dev, "Error in reading the fuel gauge control register\n");
-               return ret;
-       }
+       if(info->soca->ready_fg == 1) {
+               ret = get_check_fuel_gauge_reg(info, VOLTAGE_1_REG, VOLTAGE_2_REG,
+                                                                       0x0fff);
+               if (ret < 0) {
+                       dev_err(info->dev, "Error in reading the fuel gauge control register\n");
+                       return ret;
+               }
 
-       *data = ret;
-       /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
-       *data = *data * 50000 / 4095;
-       /* return unit should be 1uV */
-       *data = *data * 100;
+               *data = ret;
+               /* conversion unit 1 Unit is 1.22mv (5000/4095 mv) */
+               *data = *data * 50000 / 4095;
+               /* return unit should be 1uV */
+               *data = *data * 100;
+               info->soca->Vbat_old = *data;
+       } else {
+               *data = info->soca->Vbat_old;
+       }
 
        return ret;
 }
@@ -2830,6 +4019,7 @@ static int ricoh619_batt_get_prop(struct power_supply *psy,
        mutex_lock(&info->lock);
 
        switch (psp) {
+
        case POWER_SUPPLY_PROP_ONLINE:
                ret = ricoh619_read(info->dev->parent, CHGSTATE_REG, &status);
                if (ret < 0) {
@@ -2837,23 +4027,46 @@ static int ricoh619_batt_get_prop(struct power_supply *psy,
                        mutex_unlock(&info->lock);
                        return ret;
                }
-               if (psy->type == POWER_SUPPLY_TYPE_MAINS)
-                       val->intval = (status & 0x40 ? 1 : 0);
-               else if (psy->type == POWER_SUPPLY_TYPE_USB)
-                       val->intval = (status & 0x80 ? 1 : 0);
+               #ifdef SUPPORT_USB_CONNECT_TO_ADP
+                       if (psy->type == POWER_SUPPLY_TYPE_MAINS){
+                               if((2 == dwc_otg_check_dpdm(0)) && (status & 0x40))
+                                       val->intval =1;
+                               else 
+                                       val->intval =0;
+                       }
+                       else if (psy->type == POWER_SUPPLY_TYPE_USB){
+                               if((1 == dwc_otg_check_dpdm(0)) && (status & 0x40))
+                                       val->intval =1;
+                               else 
+                                       val->intval =0;
+                       }
+               #else
+                       if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+                               val->intval = (status & 0x40 ? 1 : 0);
+                       else if (psy->type == POWER_SUPPLY_TYPE_USB)
+                               val->intval = (status & 0x80 ? 1 : 0);
+               #endif
                break;
        /* this setting is same as battery driver of 584 */
        case POWER_SUPPLY_PROP_STATUS:
-               ret = get_power_supply_status(info);
-               val->intval = ret;
-               info->status = ret;
-               /* RICOH_FG_DBG("Power Supply Status is %d\n",
+               if(info->chg_complete_tm_ov_flag == 0)
+               {
+                       ret = get_power_supply_Android_status(info);
+                       val->intval = ret;
+                       info->status = ret;
+                       /* RICOH_FG_DBG("Power Supply Status is %d\n",
                                                        info->status); */
+               }
+               else
+               {
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+               }
                break;
 
        /* this setting is same as battery driver of 584 */
        case POWER_SUPPLY_PROP_PRESENT:
-               val->intval = info->present;
+       //      val->intval = info->present;
+               val->intval = 1;
                break;
 
        /* current voltage is get from fuel gauge */
@@ -2865,7 +4078,7 @@ static int ricoh619_batt_get_prop(struct power_supply *psy,
                else {
                        //val->intval = -EINVAL;
                        data = info->cur_voltage * 1000;
-                       /* RICOH_FG_DBG( "battery voltage is not ready\n"); */
+                        RICOH_FG_DBG( "battery voltage is not ready\n"); 
                }
 #else
                ret = measure_vbatt_ADC(info, &data);
@@ -2884,22 +4097,29 @@ static int ricoh619_batt_get_prop(struct power_supply *psy,
                if (info->entry_factory_mode){
                        val->intval = 100;
                        info->capacity = 100;
-               } else if (info->soca->displayed_soc <= 0) {
-                       val->intval = 0;
-                       info->capacity = 0;
+               } else if ((info->soca->displayed_soc < 0) || (info->cur_voltage == 0)) {
+                       val->intval = 50;
+                       info->capacity = 50;
                } else {
-                       val->intval = (info->soca->displayed_soc + 50)/100;
-                       info->capacity = (info->soca->displayed_soc + 50)/100;
+                       if(info->chg_complete_tm_ov_flag == 1)
+                       {
+                               info->capacity = 100;
+                               val->intval = info->capacity;
+                       }
+                       else
+                       {
+                               info->capacity = (info->soca->displayed_soc + 50)/100;
+                               val->intval = info->capacity;
+                       }
                }
-               /* RICOH_FG_DBG("battery capacity is %d%%\n",
-                                                       info->capacity); */
+               RICOH_FG_DBG("battery capacity is %d%%\n", info->capacity); 
                break;
 
        /* current temperature of battery */
        case POWER_SUPPLY_PROP_TEMP:
                if (info->soca->ready_fg) {
                        ret = 0;
-                       val->intval = get_battery_temp(info);
+                       val->intval = get_battery_temp_2(info);
                        info->battery_temp = val->intval/10;
                        RICOH_FG_DBG( "battery temperature is %d degree\n", info->battery_temp);
                } else {
@@ -2908,6 +4128,7 @@ static int ricoh619_batt_get_prop(struct power_supply *psy,
                }
                break;
 
+       #if 0
        case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
                if (info->soca->ready_fg) {
                        ret = get_time_to_empty(info);
@@ -2935,6 +4156,8 @@ static int ricoh619_batt_get_prop(struct power_supply *psy,
                        /* RICOH_FG_DBG("time of full battery is not ready\n"); */
                }
                break;
+
+       #endif
 #endif
         case POWER_SUPPLY_PROP_TECHNOLOGY:
                val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
@@ -2968,8 +4191,8 @@ static enum power_supply_property ricoh619_batt_props[] = {
 #ifdef ENABLE_FUEL_GAUGE_FUNCTION
        POWER_SUPPLY_PROP_CAPACITY,
        POWER_SUPPLY_PROP_TEMP,
-       POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
-       POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+       //POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+       //POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
 #endif
        POWER_SUPPLY_PROP_TECHNOLOGY,
        POWER_SUPPLY_PROP_HEALTH,
@@ -2995,64 +4218,162 @@ struct power_supply    powerusb = {
                .get_property = ricoh619_batt_get_prop,
 };
 
-static __devinit int ricoh619_battery_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct ricoh619_battery_platform_data *
+ricoh619_battery_dt_init(struct platform_device *pdev)
+{
+       struct device_node *nproot = pdev->dev.parent->of_node;
+       struct device_node *np;
+       struct ricoh619_battery_platform_data *pdata;
+
+       if (!nproot)
+               return pdev->dev.platform_data;
+
+       np = of_find_node_by_name(nproot, "battery");
+       if (!np) {
+               dev_err(&pdev->dev, "failed to find battery node\n");
+               return NULL;
+       }
+
+       pdata = devm_kzalloc(&pdev->dev,
+                       sizeof(struct ricoh619_battery_platform_data),
+                       GFP_KERNEL);
+
+       of_property_read_u32(np, "ricoh,monitor-time", &pdata->monitor_time);
+       of_property_read_u32(np, "ricoh,alarm-vol-mv", &pdata->alarm_vol_mv);
+
+       /* check rage of b,.attery type */
+       type_n = Battery_Type();
+       RICOH_FG_DBG("%s type_n=%d\n", __func__, type_n);
+
+       switch (type_n) {
+       case (0):
+               of_property_read_u32(np, "ricoh,ch-vfchg", &pdata->type[0].ch_vfchg);
+               of_property_read_u32(np, "ricoh,ch-vrchg", &pdata->type[0].ch_vrchg);
+               of_property_read_u32(np, "ricoh,ch-vbatovset", &pdata->type[0].ch_vbatovset);
+               of_property_read_u32(np, "ricoh,ch-ichg", &pdata->type[0].ch_ichg);
+               of_property_read_u32(np, "ricoh,ch-ilim-adp", &pdata->type[0].ch_ilim_adp);
+               of_property_read_u32(np, "ricoh,ch-ilim-usb", &pdata->type[0].ch_ilim_usb);
+               of_property_read_u32(np, "ricoh,ch-icchg", &pdata->type[0].ch_icchg);
+               of_property_read_u32(np, "ricoh,fg-target-vsys", &pdata->type[0].fg_target_vsys);
+               of_property_read_u32(np, "ricoh,fg-target-ibat", &pdata->type[0].fg_target_ibat);
+               of_property_read_u32(np, "ricoh,fg-poff-vbat", &pdata->type[0].fg_poff_vbat);
+               of_property_read_u32(np, "ricoh,jt-en", &pdata->type[0].jt_en);
+               of_property_read_u32(np, "ricoh,jt-hw-sw", &pdata->type[0].jt_hw_sw);
+               of_property_read_u32(np, "ricoh,jt-temp-h", &pdata->type[0].jt_temp_h);
+               of_property_read_u32(np, "ricoh,jt-temp-l", &pdata->type[0].jt_temp_l);
+               of_property_read_u32(np, "ricoh,jt-vfchg-h", &pdata->type[0].jt_vfchg_h);
+               of_property_read_u32(np, "ricoh,jt-vfchg-l", &pdata->type[0].jt_vfchg_l);
+               of_property_read_u32(np, "ricoh,jt-ichg-h", &pdata->type[0].jt_ichg_h);
+               of_property_read_u32(np, "ricoh,jt-ichg-l", &pdata->type[0].jt_ichg_l);
+               break;
+#if 0
+       case (1):
+               of_property_read_u32(np, "ricoh,ch-vfchg-1", &pdata->type[1].ch_vfchg);
+               of_property_read_u32(np, "ricoh,ch-vrchg-1", &pdata->type[1].ch_vrchg);
+               of_property_read_u32(np, "ricoh,ch-vbatovset-1", &pdata->type[1].ch_vbatovset);
+               of_property_read_u32(np, "ricoh,ch-ichg-1", &pdata->type[1].ch_ichg);
+               of_property_read_u32(np, "ricoh,ch-ilim-adp-1", &pdata->type[1].ch_ilim_adp);
+               of_property_read_u32(np, "ricoh,ch-ilim-usb-1", &pdata->type[1].ch_ilim_usb);
+               of_property_read_u32(np, "ricoh,ch-icchg-1", &pdata->type[1].ch_icchg);
+               of_property_read_u32(np, "ricoh,fg-target-vsys-1", &pdata->type[1].fg_target_vsys);
+               of_property_read_u32(np, "ricoh,fg-target-ibat-1", &pdata->type[1].fg_target_ibat);
+               of_property_read_u32(np, "ricoh,fg-poff-vbat-1", &pdata->type[1].fg_poff_vbat);
+               of_property_read_u32(np, "ricoh,jt-en-1", &pdata->type[1].jt_en);
+               of_property_read_u32(np, "ricoh,jt-hw-sw-1", &pdata->type[1].jt_hw_sw);
+               of_property_read_u32(np, "ricoh,jt-temp-h-1", &pdata->type[1].jt_temp_h);
+               of_property_read_u32(np, "ricoh,jt-temp-l-1", &pdata->type[1].jt_temp_l);
+               of_property_read_u32(np, "ricoh,jt-vfchg-h-1", &pdata->type[1].jt_vfchg_h);
+               of_property_read_u32(np, "ricoh,jt-vfchg-l-1", &pdata->type[1].jt_vfchg_l);
+               of_property_read_u32(np, "ricoh,jt-ichg-h-1", &pdata->type[1].jt_ichg_h);
+               of_property_read_u32(np, "ricoh,jt-ichg-l-1", &pdata->type[1].jt_ichg_l);
+               break;
+#endif
+       default:
+               of_node_put(np);
+               return 0;
+       }
+
+       of_node_put(np);
+
+       return pdata;
+}
+#else
+static struct ricoh619_battery_platform_data *
+ricoh619_battery_dt_init(struct platform_device *pdev)
+{
+       return pdev->dev.platform_data;
+}
+#endif
+
+static int ricoh619_battery_probe(struct platform_device *pdev)
 {
        struct ricoh619_battery_info *info;
        struct ricoh619_battery_platform_data *pdata;
-       int type_n;
+       struct ricoh619 *ricoh619 = dev_get_drvdata(pdev->dev.parent);
        int ret, temp;
 
-       RICOH_FG_DBG("PMU: %s\n", __func__);
+       RICOH_FG_DBG(KERN_INFO "PMU: %s : version is %s\n", __func__,RICOH619_BATTERY_VERSION);
 
-       info = kzalloc(sizeof(struct ricoh619_battery_info), GFP_KERNEL);
+       pdata = ricoh619_battery_dt_init(pdev);
+       if (!pdata) {
+               dev_err(&pdev->dev, "platform data isn't assigned to "
+                       "power supply\n");
+               return -EINVAL;
+       }
+       info = devm_kzalloc(ricoh619->dev,sizeof(struct ricoh619_battery_info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
-       info->soca = kzalloc(sizeof(struct ricoh619_soca_info), GFP_KERNEL);
+       info->soca = devm_kzalloc(ricoh619->dev,sizeof(struct ricoh619_soca_info), GFP_KERNEL);
                if (!info->soca)
                        return -ENOMEM;
 
        info->dev = &pdev->dev;
        info->status = POWER_SUPPLY_STATUS_CHARGING;
-       pdata = pdev->dev.platform_data;
        info->monitor_time = pdata->monitor_time * HZ;
        info->alarm_vol_mv = pdata->alarm_vol_mv;
 
-       type_n = Battery_Type();
+       /* check rage of battery num */
        info->num = Battery_Table();
        temp = sizeof(battery_init_para)/(sizeof(uint8_t)*32);
-       RICOH_FG_DBG("%s temp=%d\n", __func__, temp);
        if(info->num >= (sizeof(battery_init_para)/(sizeof(uint8_t)*32)))
-               info->num = 0;
-       RICOH_FG_DBG("%s type_n=%d\n", __func__, type_n);
-       RICOH_FG_DBG("%s info->num=%d\n", __func__, info->num);
-       /* these valuse are set in platform */
-       if (type_n == 0)
        {
-               info->ch_vfchg = pdata->ch_vfchg;
-               info->ch_vrchg = pdata->ch_vrchg;
-               info->ch_vbatovset = pdata->ch_vbatovset;
-               info->ch_ichg = pdata->ch_ichg;
-               info->ch_ilim_adp = pdata->ch_ilim_adp;
-               info->ch_ilim_usb = pdata->ch_ilim_usb;
-               info->ch_icchg = pdata->ch_icchg;
-               info->fg_target_vsys = pdata->fg_target_vsys;
-               info->fg_target_ibat = pdata->fg_target_ibat;
-               info->jt_en = pdata->jt_en;
-               info->jt_hw_sw = pdata->jt_hw_sw;
-               info->jt_temp_h = pdata->jt_temp_h;
-               info->jt_temp_l = pdata->jt_temp_l;
-               info->jt_vfchg_h = pdata->jt_vfchg_h;
-               info->jt_vfchg_l = pdata->jt_vfchg_l;
-               info->jt_ichg_h = pdata->jt_ichg_h;
-               info->jt_ichg_l = pdata->jt_ichg_l;
-       } else {
+               RICOH_FG_DBG("%s : Battery num is out of range\n", __func__);
+               info->num = 0;
        }
+       RICOH_FG_DBG("%s info->num=%d,temp is %d\n", __func__, info->num,temp);
+
+       /* these valuse are set in platform */
+       info->ch_vfchg = pdata->type[type_n].ch_vfchg;
+       info->ch_vrchg = pdata->type[type_n].ch_vrchg;
+       info->ch_vbatovset = pdata->type[type_n].ch_vbatovset;
+       info->ch_ichg = pdata->type[type_n].ch_ichg;
+       info->ch_ilim_adp = pdata->type[type_n].ch_ilim_adp;
+       info->ch_ilim_usb = pdata->type[type_n].ch_ilim_usb;
+       info->ch_icchg = pdata->type[type_n].ch_icchg;
+       info->fg_target_vsys = pdata->type[type_n].fg_target_vsys;
+       info->fg_target_ibat = pdata->type[type_n].fg_target_ibat;
+       info->fg_poff_vbat = pdata->type[type_n].fg_poff_vbat;
+       info->jt_en = pdata->type[type_n].jt_en;
+       info->jt_hw_sw = pdata->type[type_n].jt_hw_sw;
+       info->jt_temp_h = pdata->type[type_n].jt_temp_h;
+       info->jt_temp_l = pdata->type[type_n].jt_temp_l;
+       info->jt_vfchg_h = pdata->type[type_n].jt_vfchg_h;
+       info->jt_vfchg_l = pdata->type[type_n].jt_vfchg_l;
+       info->jt_ichg_h = pdata->type[type_n].jt_ichg_h;
+       info->jt_ichg_l = pdata->type[type_n].jt_ichg_l;
+
        info->adc_vdd_mv = ADC_VDD_MV;          /* 2800; */
        info->min_voltage = MIN_VOLTAGE;        /* 3100; */
        info->max_voltage = MAX_VOLTAGE;        /* 4200; */
        info->delay = 500;
        info->entry_factory_mode = false;
 
+       info->chg_complete_rd_flag = 0;
+       info->chg_complete_rd_cnt = 0;
+       info->chg_complete_tm_ov_flag = 0;
+       info->chg_complete_sleep_flag = 0;
+
        mutex_init(&info->lock);
        platform_set_drvdata(pdev, info);
 
@@ -3068,28 +4389,28 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev)
        /* Disable Charger/ADC interrupt */
        ret = ricoh619_clr_bits(info->dev->parent, RICOH619_INTC_INTEN,
                                                         CHG_INT | ADC_INT);
-       if (ret)
+       if (ret<0)
                goto out;
 
        ret = ricoh619_init_battery(info);
-       if (ret)
+       if (ret<0)
                goto out;
-
+/*
 #ifdef ENABLE_FACTORY_MODE
        info->factory_mode_wqueue
                = create_singlethread_workqueue("ricoh619_factory_mode");
-       INIT_DELAYED_WORK_DEFERRABLE(&info->factory_mode_work,
+       INIT_DEFERRABLE_WORK(&info->factory_mode_work,
                                         check_charging_state_work);
 
        ret = ricoh619_factory_mode(info);
-       if (ret)
+       if (ret<0)
                goto out;
 
 #endif
-
+*/
        ret = power_supply_register(&pdev->dev, &info->battery);
 
-       if (ret)
+       if (ret<0)
                info->battery.dev->parent = &pdev->dev;
 
        ret = power_supply_register(&pdev->dev, &powerac);
@@ -3105,52 +4426,45 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev)
                = create_singlethread_workqueue("rc5t619_usb_det");
        INIT_WORK(&info->usb_irq_work, usb_det_irq_work);
 
-       INIT_DELAYED_WORK_DEFERRABLE(&info->monitor_work,
+       INIT_DEFERRABLE_WORK(&info->monitor_work,
                                         ricoh619_battery_work);
-       INIT_DELAYED_WORK_DEFERRABLE(&info->displayed_work,
+       INIT_DEFERRABLE_WORK(&info->displayed_work,
                                         ricoh619_displayed_work);
-       INIT_DELAYED_WORK_DEFERRABLE(&info->charge_stable_work,
+       INIT_DEFERRABLE_WORK(&info->charge_stable_work,
                                         ricoh619_stable_charge_countdown_work);
-       INIT_DELAYED_WORK_DEFERRABLE(&info->charge_monitor_work,
+       INIT_DEFERRABLE_WORK(&info->charge_monitor_work,
                                         ricoh619_charge_monitor_work);
-       INIT_DELAYED_WORK_DEFERRABLE(&info->get_charge_work,
+       INIT_DEFERRABLE_WORK(&info->get_charge_work,
                                         ricoh619_get_charge_work);
-       INIT_DELAYED_WORK_DEFERRABLE(&info->jeita_work, ricoh619_jeita_work);
+       INIT_DEFERRABLE_WORK(&info->jeita_work, ricoh619_jeita_work);
        INIT_DELAYED_WORK(&info->changed_work, ricoh619_changed_work);
 
+       INIT_DELAYED_WORK(&info->charge_complete_ready, ricoh619_charging_complete_work);
+
        /* Charger IRQ workqueue settings */
-       charger_irq = pdata->irq;
 
-       ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FONCHGINT,
-                                       NULL, charger_in_isr, IRQF_ONESHOT,
+       ret = request_threaded_irq( irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FONCHGINT),NULL, charger_in_isr, IRQF_ONESHOT,
                                                "rc5t619_charger_in", info);
        if (ret < 0) {
-               dev_err(&pdev->dev, "Can't get CHG_INT IRQ for chrager: %d\n",
-                                                                       ret);
+               dev_err(&pdev->dev, "Can't get CHG_INT IRQ for chrager: %d\n",ret);
                goto out;
        }
 
-       ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FCHGCMPINT,
-                                               NULL, charger_complete_isr,
-                                       IRQF_ONESHOT, "rc5t619_charger_comp",
-                                                               info);
+       ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FCHGCMPINT),NULL, charger_complete_isr,
+                                       IRQF_ONESHOT, "rc5t619_charger_comp",info);
        if (ret < 0) {
-               dev_err(&pdev->dev, "Can't get CHG_COMP IRQ for chrager: %d\n",
-                                                                        ret);
+               dev_err(&pdev->dev, "Can't get CHG_COMP IRQ for chrager: %d\n",ret);
                goto out;
        }
 
-       ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FVUSBDETSINT,
-                                       NULL, charger_usb_isr, IRQF_ONESHOT,
+       ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVUSBDETSINT) ,NULL, charger_usb_isr, IRQF_ONESHOT,
                                                "rc5t619_usb_det", info);
        if (ret < 0) {
-               dev_err(&pdev->dev, "Can't get USB_DET IRQ for chrager: %d\n",
-                                                                        ret);
+               dev_err(&pdev->dev, "Can't get USB_DET IRQ for chrager: %d\n",ret);
                goto out;
        }
 
-       ret = request_threaded_irq(charger_irq + RICOH619_IRQ_FVADPDETSINT,
-                                       NULL, charger_adp_isr, IRQF_ONESHOT,
+       ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVADPDETSINT),NULL, charger_adp_isr, IRQF_ONESHOT,
                                                "rc5t619_adp_det", info);
        if (ret < 0) {
                dev_err(&pdev->dev,
@@ -3159,21 +4473,23 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev)
        }
 
 #ifdef ENABLE_LOW_BATTERY_DETECTION
-       ret = request_threaded_irq(charger_irq + RICOH619_IRQ_VSYSLIR,
-                                       NULL, adc_vsysl_isr, IRQF_ONESHOT,
+       ret = request_threaded_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_VSYSLIR) ,NULL, adc_vsysl_isr, IRQF_ONESHOT,
                                                "rc5t619_adc_vsysl", info);
        if (ret < 0) {
                dev_err(&pdev->dev,
                        "Can't get ADC_VSYSL IRQ for chrager: %d\n", ret);
                goto out;
        }
-       INIT_DELAYED_WORK_DEFERRABLE(&info->low_battery_work,
+       INIT_DEFERRABLE_WORK(&info->low_battery_work,
                                         low_battery_irq_work);
 #endif
-
+#ifdef RICOH619_VADP_DROP_WORK
+       INIT_DEFERRABLE_WORK(&info->vadp_drop_work,vadp_drop_irq_work);
+       queue_delayed_work(info->monitor_wqueue, &info->vadp_drop_work,0);
+#endif
        /* Charger init and IRQ setting */
        ret = ricoh619_init_charger(info);
-       if (ret)
+       if (ret<0)
                goto out;
 
 #ifdef ENABLE_FUEL_GAUGE_FUNCTION
@@ -3182,19 +4498,19 @@ static __devinit int ricoh619_battery_probe(struct platform_device *pdev)
        queue_delayed_work(info->monitor_wqueue, &info->monitor_work,
                                        RICOH619_MONITOR_START_TIME*HZ);
 
-       /* Enable Charger interrupt */
-       ricoh619_set_bits(info->dev->parent, RICOH619_INTC_INTEN, CHG_INT);
+       /* Enable Charger/ADC interrupt */
+       ricoh619_set_bits(info->dev->parent, RICOH619_INTC_INTEN, CHG_INT | ADC_INT);
 
        return 0;
 
 out:
-       kfree(info);
        return ret;
 }
 
-static int __devexit ricoh619_battery_remove(struct platform_device *pdev)
+static int ricoh619_battery_remove(struct platform_device *pdev)
 {
        struct ricoh619_battery_info *info = platform_get_drvdata(pdev);
+       struct ricoh619 *ricoh619 = dev_get_drvdata(pdev->dev.parent);
        uint8_t val;
        int ret;
        int err;
@@ -3207,9 +4523,10 @@ static int __devexit ricoh619_battery_remove(struct platform_device *pdev)
                if (err < 0)
                        dev_err(info->dev, "Error in writing PSWR_REG\n");
                g_soc = 0x7f;
-       } else {
-               if (info->soca->displayed_soc < 0) {
-                       val = 0;
+       } else if (info->soca->status != RICOH619_SOCA_START
+               && info->soca->status != RICOH619_SOCA_UNSTABLE) {
+               if (info->soca->displayed_soc <= 0) {
+                       val = 1;
                } else {
                        val = (info->soca->displayed_soc + 50)/100;
                        val &= 0x7f;
@@ -3220,7 +4537,8 @@ static int __devexit ricoh619_battery_remove(struct platform_device *pdev)
 
                g_soc = val;
 
-               ret = calc_capacity_in_period(info, &cc_cap, &is_charging);
+               ret = calc_capacity_in_period(info, &cc_cap,
+                                                        &is_charging, true);
                if (ret < 0)
                        dev_err(info->dev, "Read cc_sum Error !!-----\n");
        }
@@ -3237,13 +4555,20 @@ static int __devexit ricoh619_battery_remove(struct platform_device *pdev)
        if (err < 0) {
                dev_err(info->dev, "Error in writing the control register\n");
        }
+
+       if(info->capacity == 100)
+       {
+               ret = ricoh619_write(info->dev->parent, PSWR_REG, 100);
+               if (ret < 0)
+                       dev_err(info->dev, "Error in writing PSWR_REG\n");
+       }
        
-       free_irq(charger_irq + RICOH619_IRQ_FONCHGINT, &info);
-       free_irq(charger_irq + RICOH619_IRQ_FCHGCMPINT, &info);
-       free_irq(charger_irq + RICOH619_IRQ_FVUSBDETSINT, &info);
-       free_irq(charger_irq + RICOH619_IRQ_FVADPDETSINT, &info);
+       free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FONCHGINT), &info);
+       free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FCHGCMPINT), &info);
+       free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVUSBDETSINT), &info);
+       free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_FVADPDETSINT) , &info);
 #ifdef ENABLE_LOW_BATTERY_DETECTION
-       free_irq(charger_irq + RICOH619_IRQ_VSYSLIR, &info);
+       free_irq(irq_create_mapping(ricoh619->irq_domain, RICOH619_IRQ_VSYSLIR), &info);
 #endif
 
        cancel_delayed_work(&info->monitor_work);
@@ -3256,8 +4581,14 @@ static int __devexit ricoh619_battery_remove(struct platform_device *pdev)
 #ifdef ENABLE_LOW_BATTERY_DETECTION
        cancel_delayed_work(&info->low_battery_work);
 #endif
+#ifdef RICOH619_VADP_DROP_WORK
+       cancel_delayed_work(&info->vadp_drop_work);
+#endif
+#ifdef ENABLE_FACTORY_MODE
        cancel_delayed_work(&info->factory_mode_work);
+#endif
        cancel_delayed_work(&info->jeita_work);
+       cancel_delayed_work(&info->charge_complete_ready);
        
        cancel_work_sync(&info->irq_work);
        cancel_work_sync(&info->usb_irq_work);
@@ -3265,20 +4596,23 @@ static int __devexit ricoh619_battery_remove(struct platform_device *pdev)
        flush_workqueue(info->monitor_wqueue);
        flush_workqueue(info->workqueue);
        flush_workqueue(info->usb_workqueue);
+#ifdef ENABLE_FACTORY_MODE
        flush_workqueue(info->factory_mode_wqueue);
-
+#endif
        destroy_workqueue(info->monitor_wqueue);
        destroy_workqueue(info->workqueue);
        destroy_workqueue(info->usb_workqueue);
+#ifdef ENABLE_FACTORY_MODE
        destroy_workqueue(info->factory_mode_wqueue);
+#endif
 
        power_supply_unregister(&info->battery);
-       kfree(info);
        platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
 #ifdef CONFIG_PM
+struct timeval  ts_suspend;
 static int ricoh619_battery_suspend(struct device *dev)
 {
        struct ricoh619_battery_info *info = dev_get_drvdata(dev);
@@ -3287,6 +4621,8 @@ static int ricoh619_battery_suspend(struct device *dev)
        int err;
        int cc_cap = 0;
        bool is_charging = true;
+       int displayed_soc_temp;
+       do_gettimeofday(&ts_suspend);
 
        if (g_fg_on_mode
                 && (info->soca->status == RICOH619_SOCA_STABLE)) {
@@ -3294,10 +4630,16 @@ static int ricoh619_battery_suspend(struct device *dev)
                if (err < 0)
                        dev_err(info->dev, "Error in writing PSWR_REG\n");
                 g_soc = 0x7F;
-               info->soca->suspend_soc = (info->soca->displayed_soc + 50)/100;
-       } else {
-               if (info->soca->displayed_soc < 0) {
-                       val = 0;
+               info->soca->suspend_soc = info->soca->displayed_soc;
+               ret = calc_capacity_in_period(info, &cc_cap,
+                                                        &is_charging, true);
+               if (ret < 0)
+                       dev_err(info->dev, "Read cc_sum Error !!-----\n");
+
+       } else if (info->soca->status != RICOH619_SOCA_START
+               && info->soca->status != RICOH619_SOCA_UNSTABLE) {
+               if (info->soca->displayed_soc <= 0) {
+                       val = 1;
                } else {
                        val = (info->soca->displayed_soc + 50)/100;
                        val &= 0x7f;
@@ -3308,17 +4650,48 @@ static int ricoh619_battery_suspend(struct device *dev)
 
                g_soc = val;
 
-               info->soca->suspend_soc = (info->soca->displayed_soc + 50)/100;
-
-               ret = calc_capacity_in_period(info, &cc_cap, &is_charging);
+               ret = calc_capacity_in_period(info, &cc_cap,
+                                                        &is_charging, true);
                if (ret < 0)
                        dev_err(info->dev, "Read cc_sum Error !!-----\n");
+                       
+               if (info->soca->status != RICOH619_SOCA_STABLE) {
+                       info->soca->cc_delta
+                                = (is_charging == true) ? cc_cap : -cc_cap;
+
+                       displayed_soc_temp
+                              = info->soca->displayed_soc + info->soca->cc_delta;
+                       displayed_soc_temp = min(10000, displayed_soc_temp);
+                       displayed_soc_temp = max(0, displayed_soc_temp);
+                       info->soca->displayed_soc = displayed_soc_temp;
+               }
+               info->soca->suspend_soc = info->soca->displayed_soc;
+                                       
+       } else if (info->soca->status == RICOH619_SOCA_START
+               || info->soca->status == RICOH619_SOCA_UNSTABLE) {
+
+               ret = ricoh619_read(info->dev->parent, PSWR_REG, &val);
+               if (ret < 0)
+                       dev_err(info->dev, "Error in reading the pswr register\n");
+               val &= 0x7f;
+
+               info->soca->suspend_soc = val * 100;
+       }
+
+       if (info->soca->status == RICOH619_SOCA_DISP
+               || info->soca->status == RICOH619_SOCA_STABLE
+               || info->soca->status == RICOH619_SOCA_FULL) {
+               info->soca->soc = calc_capacity_2(info);
+               info->soca->soc_delta =
+                       info->soca->soc_delta + (info->soca->soc - info->soca->last_soc);
+
+       } else {
+               info->soca->soc_delta = 0;
        }
 
        if (info->soca->status == RICOH619_SOCA_STABLE
                || info->soca->status == RICOH619_SOCA_FULL)
                info->soca->status = RICOH619_SOCA_DISP;
-               
        /* set rapid timer 300 min */
        err = ricoh619_set_bits(info->dev->parent, TIMSET_REG, 0x03);
        if (err < 0) {
@@ -3332,7 +4705,7 @@ static int ricoh619_battery_suspend(struct device *dev)
 #ifdef ENABLE_LOW_BATTERY_DETECTION
 //     disable_irq(charger_irq + RICOH619_IRQ_VSYSLIR);
 #endif
-
+#if 0
        flush_delayed_work(&info->monitor_work);
        flush_delayed_work(&info->displayed_work);
        flush_delayed_work(&info->charge_stable_work);
@@ -3344,10 +4717,47 @@ static int ricoh619_battery_suspend(struct device *dev)
 #endif
        flush_delayed_work(&info->factory_mode_work);
        flush_delayed_work(&info->jeita_work);
+#ifdef RICOH619_VADP_DROP_WORK
+       flush_delayed_work(&info->vadp_drop_work);
+#endif
        
 //     flush_work(&info->irq_work);
 //     flush_work(&info->usb_irq_work);
-       
+#else
+       cancel_delayed_work(&info->monitor_work);
+       cancel_delayed_work(&info->displayed_work);
+       cancel_delayed_work(&info->charge_stable_work);
+       cancel_delayed_work(&info->charge_monitor_work);
+       cancel_delayed_work(&info->get_charge_work);
+       cancel_delayed_work(&info->changed_work);
+#ifdef ENABLE_LOW_BATTERY_DETECTION
+       cancel_delayed_work(&info->low_battery_work);
+#endif
+/*     cancel_delayed_work(&info->charge_complete_ready);*/
+#ifdef ENABLE_FACTORY_MODE
+       cancel_delayed_work(&info->factory_mode_work);
+#endif
+       cancel_delayed_work(&info->jeita_work);
+#ifdef RICOH619_VADP_DROP_WORK
+       cancel_delayed_work(&info->vadp_drop_work);
+#endif
+/*     info->chg_complete_rd_cnt = 0;*/
+/*     info->chg_complete_rd_flag = 0;*/
+
+       if(info->capacity == 100)
+       {
+               ret = ricoh619_write(info->dev->parent, PSWR_REG, 100);
+               if (ret < 0)
+                       dev_err(info->dev, "Error in writing PSWR_REG\n");
+               if(info->chg_complete_tm_ov_flag != 1)
+               {
+                       info->chg_complete_tm_ov_flag = 0;
+                       info->chg_complete_sleep_flag = 1;
+               }
+       }
+//     flush_work(&info->irq_work);
+//     flush_work(&info->usb_irq_work);
+#endif
 
        return 0;
 }
@@ -3362,6 +4772,36 @@ static int ricoh619_battery_resume(struct device *dev)
        bool is_charging = true;
        bool is_jeita_updated;
        int i;
+       int err;
+       struct rtc_time tm;
+       struct timespec tv = {
+                       .tv_nsec = NSEC_PER_SEC >> 1,
+       };
+       struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
+
+       err = rtc_read_time(rtc, &tm);
+       if (err) {
+                       dev_err(rtc->dev.parent,
+                                       "hctosys: unable to read the hardware clock\n");        
+       }
+
+       err = rtc_valid_tm(&tm);
+       if (err) {
+                       dev_err(rtc->dev.parent,
+                                       "hctosys: invalid date/time\n");
+       }
+
+       rtc_tm_to_time(&tm, &tv.tv_sec);
+       
+       /*printk("suspend time: %d sec\n", ts_suspend.tv_sec);*/
+       /*printk("resume  time: %d sec\n", tv.tv_sec);*/
+
+       if(info->chg_complete_rd_flag == 2){
+               printk("chg_complete_rd_cnt suspend: %d\n", info->chg_complete_rd_cnt);
+               info->chg_complete_rd_cnt += (tv.tv_sec - ts_suspend.tv_sec);
+               printk("chg_complete_rd_cnt resume: %d\n", info->chg_complete_rd_cnt);
+               flush_work(&info->charge_complete_ready.work);
+       }
 
        RICOH_FG_DBG(KERN_INFO "PMU: %s: \n", __func__);
 
@@ -3374,6 +4814,7 @@ static int ricoh619_battery_resume(struct device *dev)
                info->soca->displayed_soc = -EINVAL;
        } else if (RICOH619_SOCA_ZERO == info->soca->status) {
                if (calc_ocv(info) > get_OCV_voltage(info, 0)) {
+                       RICOH_FG_DBG(KERN_INFO "PMU: %s: RICOH619_SOCA_ZERO if ()...\n", __func__);
                        ret = ricoh619_read(info->dev->parent, PSWR_REG, &val);
                        val &= 0x7f;
                        info->soca->soc = val * 100;
@@ -3385,7 +4826,7 @@ static int ricoh619_battery_resume(struct device *dev)
                        }
 
                        ret = calc_capacity_in_period(info, &cc_cap,
-                                                                &is_charging);
+                                                        &is_charging, true);
                        if (ret < 0)
                                dev_err(info->dev, "Read cc_sum Error !!-----\n");
 
@@ -3400,27 +4841,55 @@ static int ricoh619_battery_resume(struct device *dev)
                        displayed_soc_temp = max(0, displayed_soc_temp);
                        info->soca->displayed_soc = displayed_soc_temp;
 
-                       ret = ricoh619_write(info->dev->parent,
-                                                        FG_CTRL_REG, 0x51);
+                       ret = reset_FG_process(info);
+
                        if (ret < 0)
                                dev_err(info->dev, "Error in writing the control register\n");
-                       info->soca->ready_fg = 0;
                        info->soca->status = RICOH619_SOCA_FG_RESET;
 
-               } else
-                       info->soca->displayed_soc = 0;
+               } else {
+                       RICOH_FG_DBG(KERN_INFO "PMU: %s: RICOH619_SOCA_ZERO else()...\n", __func__);
+                       /*info->soca->displayed_soc = 0;*/
+                       info->soca->displayed_soc  = info->soca->suspend_soc;
+               }
        } else {
-               info->soca->soc = info->soca->suspend_soc * 100;
+               info->soca->soc = info->soca->suspend_soc;
+
+               if (RICOH619_SOCA_START == info->soca->status
+                       || RICOH619_SOCA_UNSTABLE == info->soca->status) {
+                       ret = calc_capacity_in_period(info, &cc_cap,
+                                                        &is_charging, false);
+               } else { 
+                       ret = calc_capacity_in_period(info, &cc_cap,
+                                                        &is_charging, true);
+               }
 
-               ret = calc_capacity_in_period(info, &cc_cap, &is_charging);
                if (ret < 0)
                        dev_err(info->dev, "Read cc_sum Error !!-----\n");
 
                info->soca->cc_delta = (is_charging == true) ? cc_cap : -cc_cap;
 
                displayed_soc_temp = info->soca->soc + info->soca->cc_delta;
-               if (displayed_soc_temp < 0)
+               if (info->soca->zero_flg == 1) {
+                       if((info->soca->Ibat_ave >= 0) 
+                       || (displayed_soc_temp >= 100)){
+                               info->soca->zero_flg = 0;
+                       } else {
                                displayed_soc_temp = 0;
+                       }
+               } else if (displayed_soc_temp < 100) {
+                       /* keep DSOC = 1 when Vbat is over 3.4V*/
+                       if( info->fg_poff_vbat != 0) {
+                               if (info->soca->Vbat_ave < 2000*1000) { /* error value */
+                                       displayed_soc_temp = 100;
+                               } else if (info->soca->Vbat_ave < info->fg_poff_vbat*1000) {
+                                       displayed_soc_temp = 0;
+                                       info->soca->zero_flg = 1;
+                               } else {
+                                       displayed_soc_temp = 100;
+                               }
+                       }
+               }
                displayed_soc_temp = min(10000, displayed_soc_temp);
                displayed_soc_temp = max(0, displayed_soc_temp);
 
@@ -3431,16 +4900,20 @@ static int ricoh619_battery_resume(struct device *dev)
                }
 
                if (RICOH619_SOCA_DISP == info->soca->status) {
-                       info->soca->last_soc = calc_capacity(info) * 100;
-                       info->soca->soc_delta = 0;
+                       info->soca->last_soc = calc_capacity_2(info);
                }
        }
-       info->soca->update_count = 0;
 
        ret = measure_vbatt_FG(info, &info->soca->Vbat_ave);
        ret = measure_vsys_ADC(info, &info->soca->Vsys_ave);
        ret = measure_Ibatt_FG(info, &info->soca->Ibat_ave);
 
+       if(info->chg_complete_sleep_flag == 1)
+       {
+               info->chg_complete_tm_ov_flag = 1;
+               info->chg_complete_sleep_flag = 0;
+       }
+
        power_supply_changed(&info->battery);
        queue_delayed_work(info->monitor_wqueue, &info->displayed_work, HZ);
 
@@ -3470,13 +4943,16 @@ static int ricoh619_battery_resume(struct device *dev)
        info->soca->chg_count = 0;
        queue_delayed_work(info->monitor_wqueue, &info->get_charge_work,
                                         RICOH619_CHARGE_RESUME_TIME * HZ);
+       #ifdef RICOH619_VADP_DROP_WORK
+       queue_delayed_work(info->monitor_wqueue, &info->vadp_drop_work,1 * HZ);
+       #endif
        if (info->jt_en) {
                if (!info->jt_hw_sw) {
                        queue_delayed_work(info->monitor_wqueue, &info->jeita_work,
                                         RICOH619_JEITA_UPDATE_TIME * HZ);
                }
        }
-       ricoh619_write(info->dev->parent, 0x9d, 0x00);
+//     ricoh619_write(info->dev->parent, 0x9d, 0x00);
 //     enable_irq(charger_irq + RICOH619_IRQ_FONCHGINT);
 //     enable_irq(charger_irq + RICOH619_IRQ_FCHGCMPINT);
 //     enable_irq(charger_irq + RICOH619_IRQ_FVUSBDETSINT);
@@ -3488,6 +4964,15 @@ static int ricoh619_battery_resume(struct device *dev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id ricoh619_battery_dt_match[] = {
+       { .compatible = "ricoh,ricoh619-battery", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ricoh619_battery_dt_match);
+#endif
+
+
 static const struct dev_pm_ops ricoh619_battery_pm_ops = {
        .suspend        = ricoh619_battery_suspend,
        .resume         = ricoh619_battery_resume,
@@ -3498,12 +4983,13 @@ static struct platform_driver ricoh619_battery_driver = {
        .driver = {
                                .name   = "ricoh619-battery",
                                .owner  = THIS_MODULE,
+                               .of_match_table = of_match_ptr(ricoh619_battery_dt_match),
 #ifdef CONFIG_PM
                                .pm     = &ricoh619_battery_pm_ops,
 #endif
        },
        .probe  = ricoh619_battery_probe,
-       .remove = __devexit_p(ricoh619_battery_remove),
+       .remove = ricoh619_battery_remove,
 };
 
 static int __init ricoh619_battery_init(void)
@@ -3511,7 +4997,7 @@ static int __init ricoh619_battery_init(void)
        RICOH_FG_DBG("PMU: %s\n", __func__);
        return platform_driver_register(&ricoh619_battery_driver);
 }
-subsys_initcall_sync(ricoh619_battery_init);
+fs_initcall_sync(ricoh619_battery_init);
 
 static void __exit ricoh619_battery_exit(void)
 {