UPSTREAM: clk: rockchip: release io resource when failing to init clk
[firefly-linux-kernel-4.4.55.git] / drivers / power / twl6030_bci_battery.c
index cbfd2f0c752246a65056f2ee7636194975fa3f8d..4441fe252dbc6a9851f55734dafcbb943a4e760f 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/wakelock.h>
 #include <linux/usb/otg.h>
 
+#include <mach/gpio.h>
+
 #define CONTROLLER_INT_MASK    0x00
 #define CONTROLLER_CTRL1       0x01
 #define CONTROLLER_WDG         0x02
 
 #define BATTERY_RESISTOR       10000
 #define SIMULATOR_RESISTOR     5000
-#define BATTERY_DETECT_THRESHOLD       ((BATTERY_RESISTOR + SIMULATOR_RESISTOR) / 2)
-#define CHARGING_CAPACITY_UPDATE_PERIOD        (1000 * 60 * 10)
+#define BATTERY_DETECT_THRESHOLD       ((BATTERY_RESISTOR + SIMULATOR_RESISTOR) / 2)   //battery voltage threshold divided by 22uA
+#define CHARGING_CAPACITY_UPDATE_PERIOD        (1000 * 60 * 1)
+
+
+
+/************************************************************/
+#define TIMER_MS_COUNTS     1000
+#define  NUM_DISCHARGE_MIN_SAMPLE   30
+#define NUM_CHARGE_MIN_SAMPLE   30
+/**************************************************************/
 
 /* To get VBUS input limit from twl6030_usb */
 #if CONFIG_TWL6030_USB
@@ -310,6 +320,8 @@ struct twl6030_bci_device_info {
        struct notifier_block   nb;
        struct work_struct      usb_work;
 
+       struct workqueue_struct *freezable_work;
+
        struct delayed_work     twl6030_bci_monitor_work;
        struct delayed_work     twl6030_current_avg_work;
 
@@ -320,6 +332,16 @@ struct twl6030_bci_device_info {
 
        /* max scale current based on sense resitor */
        int                     current_max_scale;
+       struct delayed_work work;
+       unsigned int interval;
+
+       int     gBatCapacityDisChargeCnt;
+       int           capacitytmp;
+       int           usb_status;
+       int           usb_old_satus;
+       int      gBatCapacityChargeCnt;
+       int            suspend_capacity;
+       int            resume_status;
 };
 
 static BLOCKING_NOTIFIER_HEAD(notifier_list);
@@ -336,7 +358,7 @@ static void twl6030_config_min_vbus_reg(struct twl6030_bci_device_info *di,
                return;
 
        if (value > 4760 || value < 4200) {
-               dev_dbg(di->dev, "invalid min vbus\n");
+               dev_err(di->dev, "invalid min vbus\n");
                return;
        }
 
@@ -361,7 +383,7 @@ static void twl6030_config_iterm_reg(struct twl6030_bci_device_info *di,
        int ret;
 
        if ((term_currentmA > 400) || (term_currentmA < 50)) {
-               dev_dbg(di->dev, "invalid termination current\n");
+               dev_err(di->dev, "invalid termination current\n");
                return;
        }
 
@@ -394,7 +416,7 @@ static void twl6030_config_voreg_reg(struct twl6030_bci_device_info *di,
        int ret;
 
        if ((voltagemV < 3500) || (voltagemV > 4760)) {
-               dev_dbg(di->dev, "invalid charger_voltagemV\n");
+               dev_err(di->dev, "invalid charger_voltagemV\n");
                return;
        }
 
@@ -431,7 +453,7 @@ static void twl6030_config_vichrg_reg(struct twl6030_bci_device_info *di,
        else if ((currentmA >= 500) && (currentmA <= 1500))
                currentmA = (currentmA - 500) / 100 + 4;
        else {
-               dev_dbg(di->dev, "invalid charger_currentmA\n");
+               dev_err(di->dev, "invalid charger_currentmA\n");
                return;
        }
 
@@ -453,7 +475,7 @@ static void twl6030_config_cinlimit_reg(struct twl6030_bci_device_info *di,
                        currentmA = ((currentmA % 100) ? 0x30 : 0x20) +
                                                ((currentmA - 100) / 100);
        } else if (currentmA < 50) {
-               dev_dbg(di->dev, "invalid input current limit\n");
+               dev_err(di->dev, "invalid input current limit\n");
                return;
        } else {
                /* This is no current limit */
@@ -472,7 +494,7 @@ static void twl6030_config_limit1_reg(struct twl6030_bci_device_info *di,
        int ret;
 
        if ((voltagemV < 3500) || (voltagemV > 4760)) {
-               dev_dbg(di->dev, "invalid max_charger_voltagemV\n");
+               dev_err(di->dev, "invalid max_charger_voltagemV\n");
                return;
        }
 
@@ -510,7 +532,7 @@ static void twl6030_config_limit2_reg(struct twl6030_bci_device_info *di,
        else if ((currentmA >= 500) && (currentmA <= 1500))
                currentmA = (currentmA - 500) / 100 + 4;
        else {
-               dev_dbg(di->dev, "invalid max_charger_currentmA\n");
+               dev_err(di->dev, "invalid max_charger_currentmA\n");
                return;
        }
 
@@ -577,7 +599,7 @@ static int is_battery_present(struct twl6030_bci_device_info *di)
         * Prevent charging on batteries were id resistor is
         * less than 5K.
         */
-       val = twl6030_get_gpadc_conversion(di, 0);
+       val = twl6030_get_gpadc_conversion(di,di->gpadc_vbat_chnl);
 
        /*
         * twl6030_get_gpadc_conversion for
@@ -610,7 +632,7 @@ static void twl6030_stop_usb_charger(struct twl6030_bci_device_info *di)
 {
        int ret;
        u8 reg;
-
+       //printk("*************twl6030_stop_usb_charger***************\n");
        if (di->use_hw_charger) {
                ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &reg,
                                CHARGERUSB_CTRL1);
@@ -640,6 +662,9 @@ static void twl6030_start_usb_charger(struct twl6030_bci_device_info *di)
        int ret;
        u8 reg;
 
+
+//printk("***************twl6030_start_usb_charger*****************************************\n");
+
        if (di->use_hw_charger) {
                ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &reg,
                                CHARGERUSB_CTRL1);
@@ -656,7 +681,7 @@ static void twl6030_start_usb_charger(struct twl6030_bci_device_info *di)
        }
 
        if (!is_battery_present(di)) {
-               dev_dbg(di->dev, "BATTERY NOT DETECTED!\n");
+               dev_info(di->dev, "BATTERY NOT DETECTED!\n");
                return;
        }
 
@@ -725,7 +750,7 @@ static void twl6030_start_ac_charger(struct twl6030_bci_device_info *di)
        int ret;
 
        if (!is_battery_present(di)) {
-               dev_dbg(di->dev, "BATTERY NOT DETECTED!\n");
+               dev_info(di->dev, "BATTERY NOT DETECTED!\n");
                return;
        }
        dev_dbg(di->dev, "AC charger detected\n");
@@ -751,6 +776,7 @@ static void twl6030_start_ac_charger(struct twl6030_bci_device_info *di)
 
 static void twl6030_stop_charger(struct twl6030_bci_device_info *di)
 {
+       //printk("$$$$$$$$$$$$twl6030_stop_charger$$$$$$$$$$$$\n");
        if (di->charger_source == POWER_SUPPLY_TYPE_MAINS)
                twl6030_stop_ac_charger(di);
        else if (di->charger_source == POWER_SUPPLY_TYPE_USB)
@@ -826,6 +852,8 @@ static void twl6032_charger_ctrl_interrupt(struct twl6030_bci_device_info *di)
  */
 static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
 {
+//     printk("%s\n", __func__);
+
        struct twl6030_bci_device_info *di = _di;
        int ret;
        int charger_fault = 0;
@@ -889,7 +917,7 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
                                goto err;
                }
                di->usb_online = 0;
-               dev_dbg(di->dev, "usb removed\n");
+               dev_info(di->dev, "usb removed\n");
                twl6030_stop_usb_charger(di);
                if (present_charge_state & VAC_DET)
                        twl6030_start_ac_charger(di);
@@ -920,7 +948,7 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
                        di->usb_online = POWER_SUPPLY_TYPE_USB;
                        if ((present_charge_state & VAC_DET) &&
                                        (di->vac_priority == 2))
-                               dev_dbg(di->dev, "USB charger detected"
+                               dev_info(di->dev, "USB charger detected"
                                                ", continue with VAC\n");
                        else {
                                di->charger_source =
@@ -928,13 +956,13 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
                                di->charge_status =
                                                POWER_SUPPLY_STATUS_CHARGING;
                        }
-                       dev_dbg(di->dev, "vbus detect\n");
+                       dev_info(di->dev, "vbus detect\n");
                }
        }
 
        if (stat_reset & VAC_DET) {
                di->ac_online = 0;
-               dev_dbg(di->dev, "vac removed\n");
+               dev_info(di->dev, "vac removed\n");
                twl6030_stop_ac_charger(di);
                if (present_charge_state & VBUS_DET) {
                        di->charger_source = POWER_SUPPLY_TYPE_USB;
@@ -947,7 +975,7 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
                di->ac_online = POWER_SUPPLY_TYPE_MAINS;
                if ((present_charge_state & VBUS_DET) &&
                                (di->vac_priority == 3))
-                       dev_dbg(di->dev,
+                       dev_info(di->dev,
                                        "AC charger detected"
                                        ", continue with VBUS\n");
                else
@@ -956,16 +984,16 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
 
        if (stat_set & CONTROLLER_STAT1_FAULT_WDG) {
                charger_fault = 1;
-               dev_dbg(di->dev, "Fault watchdog fired\n");
+               dev_info(di->dev, "Fault watchdog fired\n");
        }
        if (stat_reset & CONTROLLER_STAT1_FAULT_WDG)
-               dev_dbg(di->dev, "Fault watchdog recovered\n");
+               dev_err(di->dev, "Fault watchdog recovered\n");
        if (stat_set & CONTROLLER_STAT1_BAT_REMOVED)
-               dev_dbg(di->dev, "Battery removed\n");
+               dev_err(di->dev, "Battery removed\n");
        if (stat_reset & CONTROLLER_STAT1_BAT_REMOVED)
-               dev_dbg(di->dev, "Battery inserted\n");
+               dev_err(di->dev, "Battery inserted\n");
        if (stat_set & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) {
-               dev_dbg(di->dev, "Battery temperature overrange\n");
+               dev_err(di->dev, "Battery temperature overrange\n");
                di->bat_health = POWER_SUPPLY_HEALTH_OVERHEAT;
        }
        if (stat_reset & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) {
@@ -978,14 +1006,14 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
        if (charger_fault) {
                twl6030_stop_usb_charger(di);
                di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-               dev_err(di->dev, "Charger Fault stop charging\n");
+               dev_dbg(di->dev, "Charger Fault stop charging\n");
        }
 
        if (di->capacity != -1)
                power_supply_changed(&di->bat);
        else {
                cancel_delayed_work(&di->twl6030_bci_monitor_work);
-               schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
+               queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
        }
 err:
        return IRQ_HANDLED;
@@ -1056,9 +1084,9 @@ static irqreturn_t twl6030charger_fault_interrupt(int irq, void *_di)
        if (charger_fault) {
                twl6030_stop_usb_charger(di);
                di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-               dev_err(di->dev, "Charger Fault stop charging\n");
+               dev_dbg(di->dev, "Charger Fault stop charging\n");
        }
-       dev_dbg(di->dev, "Charger fault detected STS, INT1, INT2 %x %x %x\n",
+       dev_info(di->dev, "Charger fault detected STS, INT1, INT2 %x %x %x\n",
            usb_charge_sts, usb_charge_sts1, usb_charge_sts2);
 
        power_supply_changed(&di->bat);
@@ -1078,6 +1106,7 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
        int charger_stop = 0, end_of_charge = 0;
        int ret;
 
+       //printk("xxxxxxxxxxxxxxxxxxxxxxxx twl6032charger_ctrl_interrupt_hw   xxxxxxxxxxxxxx\n");
        /* read charger controller_stat1 */
        ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1,
                        CONTROLLER_STAT1);
@@ -1092,31 +1121,36 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
        if (!(stat1 & (VBUS_DET | VAC_DET))) {
                charger_stop = 1;
                di->ac_online = di->usb_online = 0;
+               //printk("%%%%%%%%%%%%%%charger_stop = 1%%%%%%%%%%%%%\n");
        }
 
        if (!(di->usb_online || di->ac_online)) {
                if (stat1 & VBUS_DET) {
                        di->usb_online = 1;
                        di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
+//                     printk("%%%%%%%%%%%%%%di->usb_online = 1%%%%%%%%%%%%%\n");
+
+                       //schedule_work(&di->usb_work);
                } else if (stat1 & VAC_DET) {
                        di->ac_online = 1;
                        di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
+//                     printk("%%%%%%%%%%%%%%di->ac_online = 1%%%%%%%%%%%%%\n");
                }
        }
 
        if (stat1 & CONTROLLER_STAT1_FAULT_WDG) {
                charger_stop = 1;
                di->bat_health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
-               dev_dbg(di->dev, "Charger error : Fault watchdog\n");
+                dev_err(di->dev, "Charger error : Fault watchdog\n");
        }
        if (stat1 & CONTROLLER_STAT1_BAT_REMOVED) {
                charger_stop = 1;
                di->bat_health = POWER_SUPPLY_HEALTH_DEAD;
-               dev_dbg(di->dev, "Battery removed\n");
+               dev_info(di->dev, "Battery removed\n");
        }
        if (stat1 & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) {
                charger_stop = 1;
-               dev_dbg(di->dev,
+                dev_dbg(di->dev,
                        "Charger error : Battery temperature overrange\n");
                di->bat_health = POWER_SUPPLY_HEALTH_OVERHEAT;
        }
@@ -1128,7 +1162,7 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
 
                if (linear & LINEAR_CHRG_STS_CRYSTL_OSC_OK) {
                        di->bat_health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
-                       dev_dbg(di->dev, "Charger error: CRYSTAL OSC OK\n");
+                        dev_dbg(di->dev, "Charger error: CRYSTAL OSC OK\n");
                }
 
                if (linear & LINEAR_CHRG_STS_END_OF_CHARGE) {
@@ -1139,13 +1173,13 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
 
                if (linear & LINEAR_CHRG_STS_VBATOV) {
                        di->bat_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
-                       dev_dbg(di->dev,
+                        dev_dbg(di->dev,
                                "Charger error : Linear Status: VBATOV\n");
                }
 
                if (linear & LINEAR_CHRG_STS_VSYSOV) {
                        di->bat_health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
-                       dev_dbg(di->dev,
+                        dev_dbg(di->dev,
                                "Charger error : Linear Status: VSYSOV\n");
                }
        }
@@ -1162,6 +1196,7 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
                                        POWER_SUPPLY_STATUS_NOT_CHARGING;
                }
        }
+       //printk("%%%%%%%%%%%%%%%%%%twl6032charger_ctrl_interrupt_hw  end  xxxxxxxxxxxxxx\n");
 
        power_supply_changed(&di->bat);
 
@@ -1207,7 +1242,7 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
 
                if (sts_int2 & CURRENT_TERM) {
                        charger_stop = 1;
-                       dev_dbg(di->dev, "Charger error: CURRENT_TERM\n");
+                        dev_dbg(di->dev, "Charger error: CURRENT_TERM\n");
                }
        }
 
@@ -1215,7 +1250,7 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
                dev_dbg(di->dev, "Charger: CHARGEUSB_STAT\n");
 
                if (sts_int2 & ANTICOLLAPSE)
-                       dev_dbg(di->dev, "Charger error: ANTICOLLAPSE\n");
+                        dev_dbg(di->dev, "Charger error: ANTICOLLAPSE\n");
        }
 
        if (sts & CHARGERUSB_THMREG) {
@@ -1233,7 +1268,7 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
                if (!di->use_power_path) {
                        if (sts_int1 & CHARGERUSB_STATUS_INT1_NO_BAT) {
                                di->bat_health = POWER_SUPPLY_HEALTH_DEAD;
-                               dev_dbg(di->dev,
+                               dev_err(di->dev,
                                        "Charger error : NO_BAT\n");
                        }
                        if (sts_int1 & CHARGERUSB_STATUS_INT1_BAT_OVP) {
@@ -1293,7 +1328,7 @@ static void twl6030battery_current(struct twl6030_bci_device_info *di)
        ret = twl_i2c_read(TWL6030_MODULE_GASGAUGE, (u8 *)&read_value,
                                                                FG_REG_10, 2);
        if (ret < 0) {
-               dev_dbg(di->dev, "failed to read FG_REG_10: current_now\n");
+               dev_info(di->dev, "failed to read FG_REG_10: current_now\n");
                return;
        }
 
@@ -1447,6 +1482,8 @@ static enum power_supply_property twl6030_bk_bci_battery_props[] = {
 
 static void twl6030_current_avg(struct work_struct *work)
 {
+//     printk("%s\n", __func__);
+
        s32 samples = 0;
        s16 cc_offset = 0;
        int current_avg_uA = 0;
@@ -1505,19 +1542,41 @@ static void twl6030_current_avg(struct work_struct *work)
                di->current_avg_uA = current_avg_uA * 1000;
        }
 
-       schedule_delayed_work(&di->twl6030_current_avg_work,
+       queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work,
                msecs_to_jiffies(1000 * di->current_avg_interval));
        return;
 err:
        pr_err("%s: Error access to TWL6030 (%d)\n", __func__, ret);
 }
-
+#define BATT_NUM  11
+struct batt_vol_cal{
+       u32 disp_cal;
+       u32 dis_charge_vol;
+       u32 charge_vol;
+};
+static struct batt_vol_cal  batt_table[BATT_NUM] = {
+       {0,3571,3730},//{1,3420,3525},{2,3420,3575},{3,3475,3600},{5,3505,3620},{7,3525,3644},
+       {9,3628,3770},//{11,3557,3670},{13,3570,3684},{15,3580,3700},{17,3610,3715},
+       {19,3670,3878},//{21,3640,3748},{23,3652,3756},{25,3662,3775},{27,3672,3790},
+       {29,3719,3895},//{31,3687,3814},{33,3693,3818},{35,3699,3822},{37,3705,3825},
+       {39,3770,3941},//{41,3714,3832},{43,3718,3834},{45,3722,3836},{47,3726,3837},
+       {49,3801,3980},//{51,3734,3841},{53,3738,3842},{55,3742,3844},{57,3746,3844},
+       {59,3849,4010},//{61,3756,3860},{63,3764,3864},{65,3774,3871},{67,3786,3890},
+       {69,3864,4024},//{71,3808,3930},{73,3817,3977},{75,3827,3977},{77,3845,3997},
+       {79,3884,4040},//{81,3964,4047},{83,3982,4064},{85,4002,4080},{87,4026,4096},
+       {89,4001,4050},//{91,4034,4144},{93,4055,4150},{95,4085,4195},{97,4085,4195},
+       {100,4070,4090},
+};
+#if 0
 static int capacity_changed(struct twl6030_bci_device_info *di)
 {
        int curr_capacity = di->capacity;
        int charger_source = di->charger_source;
        int charging_disabled = 0;
+       struct batt_vol_cal *p;
+       int i=0;
 
+       p = batt_table;
        /* Because system load is always greater than
         * termination current, we will never get a CHARGE DONE
         * int from BQ. And charging will alwys be in progress.
@@ -1529,10 +1588,8 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
        /* if it has been more than 10 minutes since our last update
         * and we are charging we force a update.
         */
-
        if (time_after(jiffies, di->ac_next_refresh)
                && (di->charger_source != POWER_SUPPLY_TYPE_BATTERY)) {
-
                charging_disabled = 1;
                di->ac_next_refresh = jiffies +
                        msecs_to_jiffies(CHARGING_CAPACITY_UPDATE_PERIOD);
@@ -1544,17 +1601,60 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
                twl6030_stop_charger(di);
                /*voltage setteling time*/
                msleep(200);
-
                di->voltage_mV = twl6030_get_gpadc_conversion(di,
                                                di->gpadc_vbat_chnl);
+               
        }
 
        /* Setting the capacity level only makes sense when on
         * the battery is powering the board.
         */
-       if (di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
-               if (di->voltage_mV < 3500)
-                       curr_capacity = 5;
+        if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING){  //charge
+               if(di->voltage_mV >= p[BATT_NUM - 1].charge_vol){
+                       curr_capacity = 100;
+               }       
+               else{
+                       if(di->voltage_mV <= p[0].charge_vol){
+                               curr_capacity = 0;
+                       }
+                       else{
+                               for(i = 0; i < BATT_NUM - 1; i++){
+
+                                       if((p[i].charge_vol <= di->voltage_mV) && (di->voltage_mV < (p[i+1].charge_vol))){
+                                               curr_capacity = p[i].disp_cal ;
+                                               break;
+                                       }
+                               }
+                       }  
+               }
+
+       }
+       else if (di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING){  //discharge
+               if(di->voltage_mV >= p[BATT_NUM - 1].dis_charge_vol){
+                       curr_capacity = 100;
+               }       
+               else{
+                       if(di->voltage_mV <= p[0].dis_charge_vol){
+                               curr_capacity = 0;
+                       }
+                       else{
+                               for(i = 0; i < BATT_NUM - 1; i++){
+                                       if(((p[i].dis_charge_vol) <= di->voltage_mV) && (di->voltage_mV < (p[i+1].dis_charge_vol))){
+                                               curr_capacity = p[i].disp_cal ;
+                                               break;
+                                       }
+                               }
+                       }  
+
+               }
+
+
+       }
+       
+       /*      
+       if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+               if (di->voltage_mV < 3520)
+                       curr_capacity = 0;
                else if (di->voltage_mV < 3600 && di->voltage_mV >= 3500)
                        curr_capacity = 20;
                else if (di->voltage_mV < 3700 && di->voltage_mV >= 3600)
@@ -1566,6 +1666,9 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
                else if (di->voltage_mV >= 3900)
                                curr_capacity = 100;
        }
+       
+*/
+
 
        /* if we disabled charging to check capacity,
         * enable it again after we read the
@@ -1583,6 +1686,7 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
         */
        if (!is_battery_present(di))
                curr_capacity = 100;
+        
 
        /* Debouncing of voltage change. */
        if (di->capacity == -1) {
@@ -1590,7 +1694,7 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
                di->capacity_debounce_count = 0;
                return 1;
        }
-
+/*
        if (curr_capacity != di->prev_capacity) {
                di->prev_capacity = curr_capacity;
                di->capacity_debounce_count = 0;
@@ -1599,8 +1703,149 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
                di->capacity_debounce_count = 0;
                return 1;
        }
+*/
+       return 1;
+}
+#endif
+static int  twl6030_batt_vol_to_capacity (struct twl6030_bci_device_info *di)
+
+{
+
+       int i = 0;
+       int capacity = 0;
+       int BatVoltage;
+
+       struct batt_vol_cal *p;
+       p = batt_table;
+
+       BatVoltage = di ->voltage_mV;
+
+       if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING){  //charge
+               if(BatVoltage >=  (p[BATT_NUM - 1].charge_vol)){
+                       capacity = 100;
+               }
+               else{
+                       if(BatVoltage <= (p[0].charge_vol)){
+                               capacity = 0;
+                       }
+                       else{
+                               for(i = 0; i < BATT_NUM - 1; i++){
+
+                                       if(((p[i].charge_vol) <= BatVoltage) && (BatVoltage < (p[i+1].charge_vol))){
+                                            //   capacity = p[i].disp_cal ;
+                       capacity = i * 10 + ((BatVoltage - p[i].charge_vol) * 10) / (p[i+1] .charge_vol- p[i].charge_vol);
+
+                                            
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+       }
+       else{  //discharge
+               if(BatVoltage >= (p[BATT_NUM - 1].dis_charge_vol)){
+                       capacity = 100;
+               }
+               else{
+                       if(BatVoltage <= (p[0].dis_charge_vol)){
+                               capacity = 0;
+                       }
+                       else{
+                               for(i = 0; i < BATT_NUM - 1; i++){
+                                       if(((p[i].dis_charge_vol) <= BatVoltage) && (BatVoltage < (p[i+1].dis_charge_vol))){
+                                       //        capacity = p[i].disp_cal ;
+                       capacity = i * 10 + ((BatVoltage - p[i].dis_charge_vol) * 10) / (p[i+1] .dis_charge_vol- p[i].dis_charge_vol);
+                                               break;
+                                       }
+                               }
+                       }
+
+               }
+
+
+       }
+
+       return capacity;
 
-       return 0;
+}
+
+
+                                       
+static void twl6030_batt_capacity_samples(struct twl6030_bci_device_info *di)
+{
+       int capacity = 0;
+       capacity = twl6030_batt_vol_to_capacity (di);
+       twl6030battery_current(di);
+
+       if( 1 == di->resume_status ){
+               di->resume_status = 0;
+               if  (di->charge_status == POWER_SUPPLY_STATUS_CHARGING){\
+                       if (di->suspend_capacity > capacity){
+
+                               di->capacity =  di->suspend_capacity;
+                       }else{
+                               di->capacity = capacity;
+                       }       
+               }else{
+                       if (di->suspend_capacity > capacity){
+                               di->capacity = capacity;
+                       }else{
+                               di->capacity =  di->suspend_capacity;
+                       }       
+               
+               }
+               return;
+               
+       }
+
+       if (di->charge_status == POWER_SUPPLY_STATUS_FULL){
+               if (capacity < di->capacity){
+                       if (di ->gBatCapacityChargeCnt >= NUM_CHARGE_MIN_SAMPLE){
+                               di ->gBatCapacityChargeCnt = 0;
+                               if (di -> capacity < 99){
+                                       di -> capacity++;
+                               }
+                       }
+                       
+               }
+               
+       }
+               
+         
+       if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING){
+               if (capacity > di->capacity){
+                       //ʵ¼Ê²ÉÑùµ½µÄÈÝÁ¿±ÈÏÔʾµÄÈÝÁ¿´ó£¬Öð¼¶ÉÏÉý
+                       if (++(di->gBatCapacityChargeCnt) >= NUM_CHARGE_MIN_SAMPLE){
+                               di ->gBatCapacityChargeCnt  = 0;
+                               if (di ->  capacity < 99){
+                                       di -> capacity++;
+                                       
+                               }
+                       }
+                       di->gBatCapacityDisChargeCnt = 0;  //·ÅµçµÄ¼ÆÊýֵΪ0
+               }
+
+       }
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+       if ((di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)||(di->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING)){
+
+       //·Åµçʱ,Ö»ÔÊÐíµçѹϽµ
+               if (capacity < di -> capacity){
+                       if (++(di->gBatCapacityDisChargeCnt) >= NUM_DISCHARGE_MIN_SAMPLE){
+                               di ->gBatCapacityDisChargeCnt = 0;
+                               if (di -> capacity > 0){
+                                       di -> capacity-- ;
+                                       //bat->bat_change  = 1;
+                               }
+                       }
+               }
+               else{
+                       di ->gBatCapacityDisChargeCnt = 0;
+               }
+               //di ->gBatCapacityChargeCnt = 0;
+       }
+               di ->capacitytmp = capacity;
 }
 
 static int twl6030_set_watchdog(struct twl6030_bci_device_info *di, int val)
@@ -1612,34 +1857,80 @@ static int twl6030_set_watchdog(struct twl6030_bci_device_info *di, int val)
        return twl_i2c_write_u8(TWL6030_MODULE_CHARGER, val, CONTROLLER_WDG);
 
 }
+#if 0
+static void twl6030_bci_adc_set(struct twl6030_bci_device_info *di)
+{
+       struct twl6030_gpadc_request req;
+       int adc_code;
+       int temp;
+       int ret;
+       //int level;
+
+       /* Kick the charger watchdog */
+       if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING)
+               twl6030_set_watchdog(di, di->watchdog_duration);
+       
+       req.method = TWL6030_GPADC_SW2;
+       req.channels = (1 << 1) | (1 << di->gpadc_vbat_chnl) | (1 << 8);
+       req.active = 0;
+       req.func_cb = NULL;
+       ret = twl6030_gpadc_conversion(&req);
+
+       
+       if (ret < 0) {
+               dev_dbg(di->dev, "gpadc conversion failed: %d\n", ret);
+               return;
+       }
+       
+       if (req.rbuf[di->gpadc_vbat_chnl] > 0)
+               di->voltage_mV = req.rbuf[di->gpadc_vbat_chnl];
+
+       if (req.rbuf[8] > 0)
+               di->bk_voltage_mV = req.rbuf[8];
+
+       if (di->platform_data->battery_tmp_tbl == NULL)
+               return;
 
+       adc_code = req.rbuf[1];
+       for (temp = 0; temp < di->platform_data->tblsize; temp++) {
+               if (adc_code >= di->platform_data->
+                               battery_tmp_tbl[temp])
+                       break;
+       }
+       //printk("twl6030_bci_adc_set---di->voltage_mV-=-%d,di->capacity = %d \n",di->voltage_mV,di->capacity);
+       /* first 2 values are for negative temperature */
+
+}
+#endif
 static void twl6030_bci_battery_work(struct work_struct *work)
 {
+
        struct twl6030_bci_device_info *di = container_of(work,
                struct twl6030_bci_device_info, twl6030_bci_monitor_work.work);
        struct twl6030_gpadc_request req;
        int adc_code;
        int temp;
        int ret;
+//     int level;
 
        /* Kick the charger watchdog */
        if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING)
                twl6030_set_watchdog(di, di->watchdog_duration);
-
+       
        req.method = TWL6030_GPADC_SW2;
        req.channels = (1 << 1) | (1 << di->gpadc_vbat_chnl) | (1 << 8);
-
        req.active = 0;
        req.func_cb = NULL;
        ret = twl6030_gpadc_conversion(&req);
 
-       schedule_delayed_work(&di->twl6030_bci_monitor_work,
-                       msecs_to_jiffies(1000 * di->monitoring_interval));
+       queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
+                       msecs_to_jiffies(TIMER_MS_COUNTS)); //* di->monitoring_interval
+       
        if (ret < 0) {
                dev_dbg(di->dev, "gpadc conversion failed: %d\n", ret);
                return;
        }
-
+       
        if (req.rbuf[di->gpadc_vbat_chnl] > 0)
                di->voltage_mV = req.rbuf[di->gpadc_vbat_chnl];
 
@@ -1655,17 +1946,21 @@ static void twl6030_bci_battery_work(struct work_struct *work)
                                battery_tmp_tbl[temp])
                        break;
        }
-
+       //printk("workxxxxx---di->voltage_mV-=-%d,di->capacity = %d \n",di->voltage_mV,di->capacity);
        /* first 2 values are for negative temperature */
        di->temp_C = (temp - 2); /* in degrees Celsius */
-
-       if (capacity_changed(di))
+//     if (capacity_changed(di))  //xsf
+       {
+               twl6030_batt_capacity_samples(di);
+               // di->capacity = level;
                power_supply_changed(&di->bat);
+       }
 }
 
 static void twl6030_current_mode_changed(struct twl6030_bci_device_info *di)
 {
        int ret;
+       //printk("%s\n", __func__);
 
        /* FG_REG_01, 02, 03 is 24 bit unsigned sample counter value */
        ret = twl_i2c_read(TWL6030_MODULE_GASGAUGE, (u8 *) &di->timer_n1,
@@ -1682,7 +1977,7 @@ static void twl6030_current_mode_changed(struct twl6030_bci_device_info *di)
                goto err;
 
        cancel_delayed_work(&di->twl6030_current_avg_work);
-       schedule_delayed_work(&di->twl6030_current_avg_work,
+       queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work,
                msecs_to_jiffies(1000 * di->current_avg_interval));
        return;
 err:
@@ -1691,21 +1986,25 @@ err:
 
 static void twl6030_work_interval_changed(struct twl6030_bci_device_info *di)
 {
+       //printk("%s\n", __func__);
+
        cancel_delayed_work(&di->twl6030_bci_monitor_work);
-       schedule_delayed_work(&di->twl6030_bci_monitor_work,
+       queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
                msecs_to_jiffies(1000 * di->monitoring_interval));
 }
 
 #define to_twl6030_bci_device_info(x) container_of((x), \
                        struct twl6030_bci_device_info, bat);
-
+#if 0
 static void twl6030_bci_battery_external_power_changed(struct power_supply *psy)
-{
+{//    printk("%s\n", __func__);
+
        struct twl6030_bci_device_info *di = to_twl6030_bci_device_info(psy);
 
        cancel_delayed_work(&di->twl6030_bci_monitor_work);
-       schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
+       queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
 }
+#endif
 
 #define to_twl6030_ac_device_info(x) container_of((x), \
                struct twl6030_bci_device_info, ac);
@@ -1714,14 +2013,25 @@ static int twl6030_ac_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
+       u8 stat1;
        struct twl6030_bci_device_info *di = to_twl6030_ac_device_info(psy);
-
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = di->ac_online;
+               twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1,
+                                       CONTROLLER_STAT1);
+               
+               if (stat1 & VAC_DET) {
+                       val->intval =  1;
+               }
+               else
+                       val->intval =  0;
+
+               ///printk("&&&&&&&&&&&&ac---charge  ac->intval = %d &&&&&&&&&&&&&&&\n" ,val->intval);
+
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                val->intval = twl6030_get_gpadc_conversion(di, 9) * 1000;
+
                break;
        default:
                return -EINVAL;
@@ -1737,14 +2047,27 @@ static int twl6030_usb_get_property(struct power_supply *psy,
                                        enum power_supply_property psp,
                                        union power_supply_propval *val)
 {
+       u8 stat1;
        struct twl6030_bci_device_info *di = to_twl6030_usb_device_info(psy);
-
        switch (psp) {
        case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = di->usb_online;
+
+               twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1,
+                                       CONTROLLER_STAT1);
+               
+               if (stat1 & VBUS_DET) {
+                       val->intval =  1;
+               }
+               else
+                       val->intval =  0;
+
+               //val->intval = di->usb_online; //xsf
+               
+               //printk("&&&&&&&&&&&&usb---charge  val->intval = %d &&&&&&&&&&&&&&&\n" ,val->intval);
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                val->intval = twl6030_get_gpadc_conversion(di, 10) * 1000;
+               //printk("&&&&&&&&&&&&usb-voltage = &&&&&&&&&&&&&&&%d\n", val->intval);
                break;
        default:
                return -EINVAL;
@@ -1761,7 +2084,7 @@ static int twl6030_bk_bci_battery_get_property(struct power_supply *psy,
                                        union power_supply_propval *val)
 {
        struct twl6030_bci_device_info *di = to_twl6030_bk_bci_device_info(psy);
-
+       val->intval = 0;        
        switch (psp) {
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                val->intval = di->bk_voltage_mV * 1000;
@@ -1833,7 +2156,6 @@ static void twl6030_usb_charger_work(struct work_struct *work)
 {
        struct twl6030_bci_device_info  *di =
                container_of(work, struct twl6030_bci_device_info, usb_work);
-
        switch (di->event) {
        case USB_EVENT_CHARGER:
                /* POWER_SUPPLY_TYPE_USB_DCP */
@@ -1866,6 +2188,7 @@ static void twl6030_usb_charger_work(struct work_struct *work)
                return;
        }
        twl6030_start_usb_charger(di);
+
        power_supply_changed(&di->usb);
 }
 
@@ -1874,7 +2197,6 @@ static int twl6030_usb_notifier_call(struct notifier_block *nb,
 {
        struct twl6030_bci_device_info *di =
                container_of(nb, struct twl6030_bci_device_info, nb);
-
        di->event = event;
        switch (event) {
        case USB_EVENT_VBUS:
@@ -2409,6 +2731,34 @@ static char *twl6030_bci_supplied_to[] = {
        "twl6030_battery",
 };
 
+extern int dwc_vbus_status(void);
+
+static void twl6030_battery_update_status(struct twl6030_bci_device_info *di)
+{
+       power_supply_changed(&di->bat);
+       power_supply_changed(&di->usb);
+       power_supply_changed(&di->ac);
+
+}
+static void twl6030_battery_work(struct work_struct *work)
+{      
+
+       struct twl6030_bci_device_info *di = container_of(work, struct twl6030_bci_device_info, work.work); 
+       twl6030_battery_update_status(di);
+       //set charging current
+               twl_i2c_write_u8(TWL6030_MODULE_CHARGER,0x00,CHARGERUSB_CTRL1);
+               if(2 == dwc_vbus_status()){
+                       twl_i2c_write_u8(TWL6030_MODULE_CHARGER, 0x2e,CHARGERUSB_CINLIMIT);     //set vbus input current is 1.5A
+                       twl_i2c_write_u8(TWL6030_MODULE_CHARGER, 0x0b,CHARGERUSB_VICHRG);       //set mos output current is 1A
+               }
+               else if(1 == dwc_vbus_status()){
+                       twl_i2c_write_u8(TWL6030_MODULE_CHARGER, 0x2e,CHARGERUSB_CINLIMIT);//set vbus input current is 500ma
+                       twl_i2c_write_u8(TWL6030_MODULE_CHARGER, 0x09,CHARGERUSB_VICHRG);       //set mos output current is 500ma
+               }
+       /* reschedule for the next time */
+       queue_delayed_work(di->freezable_work, &di->work, di->interval);
+}
+
 static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
 {
        struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
@@ -2419,9 +2769,9 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
        u8 chargerusb_ctrl1 = 0;
        u8 hw_state = 0;
        u8 reg = 0;
-
+       //printk("%s\n", __func__);
        if (!pdata) {
-               dev_dbg(&pdev->dev, "platform_data not available\n");
+               dev_info(&pdev->dev, "platform_data not available\n");
                return -EINVAL;
        }
 
@@ -2447,6 +2797,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
        di->features = pdata->features;
        di->dev = &pdev->dev;
 
+
+//     printk("di->feature = %d, TWL6032_SUBCLASS = %d\n",di->features,TWL6032_SUBCLASS);
        if (di->features & TWL6032_SUBCLASS) {
                ret = twl_i2c_read_u8(TWL_MODULE_RTC, &reg, CHARGER_MODE_REG);
                if (ret)
@@ -2471,7 +2823,9 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
                di->use_power_path = 0;
                di->use_hw_charger = 0;
        }
+//     printk("di->feature = %d, TWL6032_SUBCLASS = %d,di->use_hw_charger =%d \n",di->features,TWL6032_SUBCLASS,di->use_hw_charger );
 
+       
        if (di->use_hw_charger) {
                di->platform_data->max_charger_currentmA =
                                twl6030_get_limit2_reg(di);
@@ -2482,7 +2836,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
                di->platform_data->max_bat_voltagemV =
                                twl6030_get_voreg_reg(di);
        }
-
+//     printk("max_charger_currentmA = %d, max_charger_voltagemV = %d\n,termination_currentmA =%d, max_bat_voltagemV =%d \n",di->platform_data->max_charger_currentmA ,
+//             di->platform_data->max_charger_voltagemV,di->platform_data->termination_currentmA, di->platform_data->max_bat_voltagemV);
        di->bat.name = "twl6030_battery";
        di->bat.supplied_to = twl6030_bci_supplied_to;
        di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to);
@@ -2490,8 +2845,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
        di->bat.properties = twl6030_bci_battery_props;
        di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props);
        di->bat.get_property = twl6030_bci_battery_get_property;
-       di->bat.external_power_changed =
-                       twl6030_bci_battery_external_power_changed;
+       //di->bat.external_power_changed =
+       //              twl6030_bci_battery_external_power_changed;
        di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
 
        di->usb.name = "twl6030_usb";
@@ -2549,7 +2904,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
                                0, "twl_bci_fault", di);
 
        if (ret) {
-               dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+               dev_info(&pdev->dev, "could not request irq %d, status %d\n",
                        irq, ret);
                goto temp_setup_fail;
        }
@@ -2562,57 +2917,87 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
                                0, "twl_bci_ctrl", di);
        else
                ret = request_threaded_irq(irq, NULL,
-                               twl6032charger_ctrl_interrupt_hw,
-                               0, "twl_bci_ctrl", di);
+                               twl6032charger_ctrl_interrupt_hw,  
+                               0, "twl_bci_ctrl", di);  // Ò»Ö±ÔÚ¼ì²âµç³ØµÄ״̬
 
        if (ret) {
-               dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
+               dev_info(&pdev->dev, "could not request irq %d, status %d\n",
                        irq, ret);
                goto chg_irq_fail;
        }
 
        ret = power_supply_register(&pdev->dev, &di->bat);
        if (ret) {
-               dev_dbg(&pdev->dev, "failed to register main battery\n");
+               dev_info(&pdev->dev, "failed to register main battery\n");
                goto batt_failed;
        }
 
        ret = power_supply_register(&pdev->dev, &di->usb);
        if (ret) {
-               dev_dbg(&pdev->dev, "failed to register usb power supply\n");
+               dev_info(&pdev->dev, "failed to register usb power supply\n");
                goto usb_failed;
        }
 
        ret = power_supply_register(&pdev->dev, &di->ac);
        if (ret) {
-               dev_dbg(&pdev->dev, "failed to register ac power supply\n");
+               dev_info(&pdev->dev, "failed to register ac power supply\n");
                goto ac_failed;
        }
 
        ret = power_supply_register(&pdev->dev, &di->bk_bat);
        if (ret) {
-               dev_dbg(&pdev->dev, "failed to register backup battery\n");
+               dev_info(&pdev->dev, "failed to register backup battery\n");
                goto bk_batt_failed;
        }
        di->charge_n1 = 0;
        di->timer_n1 = 0;
 
-       INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bci_monitor_work,
-                               twl6030_bci_battery_work);
-       schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
+       //di->freezable_work = create_freezable_workqueue("battery");
+#if 1
+       if (di->features & TWL6032_SUBCLASS) {
+               di->charger_incurrentmA = 1000;
+               di->gpadc_vbat_chnl = TWL6032_GPADC_VBAT_CHNL;
+       } else {
+               di->charger_incurrentmA = twl6030_get_usb_max_power(di->otg);
+               di->gpadc_vbat_chnl = TWL6030_GPADC_VBAT_CHNL;
+       }
+#endif
+#if 1
+
+       ret = twl6030battery_voltage_setup(di);
+       if (ret)
+               dev_info(&pdev->dev, "voltage measurement setup failed\n");
 
+       ret = twl6030battery_current_setup(true);
+       if (ret)
+               dev_info(&pdev->dev, "current measurement setup failed\n");
+
+
+       di->voltage_mV = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
+       di->voltage_mV = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
+       di->capacity = twl6030_batt_vol_to_capacity( di);
+       twl6030battery_current(di);
+#endif
+       di->freezable_work = system_freezable_wq;
+       INIT_DELAYED_WORK(&di->twl6030_bci_monitor_work,
+                               twl6030_bci_battery_work);
+       queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
+#if 1
        INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_current_avg_work,
                                                twl6030_current_avg);
-       schedule_delayed_work(&di->twl6030_current_avg_work, 500);
-
+       queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work, 500);
+#endif
+#if 0
        ret = twl6030battery_voltage_setup(di);
        if (ret)
-               dev_dbg(&pdev->dev, "voltage measurement setup failed\n");
+               dev_info(&pdev->dev, "voltage measurement setup failed\n");
 
        ret = twl6030battery_current_setup(true);
        if (ret)
-               dev_dbg(&pdev->dev, "current measurement setup failed\n");
+               dev_info(&pdev->dev, "current measurement setup failed\n");
+#endif
 
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /* initialize for USB charging */
        if (!di->use_hw_charger) {
                twl6030_config_limit1_reg(di, pdata->max_charger_voltagemV);
@@ -2650,8 +3035,9 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
        } else
                dev_err(&pdev->dev, "otg_get_transceiver failed %d\n", ret);
 
+
        if (di->features & TWL6032_SUBCLASS) {
-               di->charger_incurrentmA = 100;
+               di->charger_incurrentmA = 1000;
                di->gpadc_vbat_chnl = TWL6032_GPADC_VBAT_CHNL;
        } else {
                di->charger_incurrentmA = twl6030_get_usb_max_power(di->otg);
@@ -2673,7 +3059,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
                        if (ret)
                                goto  bk_batt_failed;
 
-                       chargerusb_ctrl1 |= HZ_MODE;
+                       chargerusb_ctrl1 |= HZ_MODE;  // high-impedance
                        ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER,
                                         chargerusb_ctrl1, CHARGERUSB_CTRL1);
                        if (ret)
@@ -2724,10 +3110,14 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
                                        POWER_SUPPLY_STATUS_DISCHARGING;
                }
        }
-
+#if 1  
+       di->interval = msecs_to_jiffies(1 * 1000);
+       INIT_DELAYED_WORK(&di->work, twl6030_battery_work);
+       queue_delayed_work(di->freezable_work, &di->work, 1*HZ);
+#endif
        ret = twl6030backupbatt_setup();
        if (ret)
-               dev_dbg(&pdev->dev, "Backup Bat charging setup failed\n");
+               dev_info(&pdev->dev, "Backup Bat charging setup failed\n");
 
        twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
                                                REG_INT_MSK_LINE_C);
@@ -2740,7 +3130,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
 
        ret = sysfs_create_group(&pdev->dev.kobj, &twl6030_bci_attr_group);
        if (ret)
-               dev_dbg(&pdev->dev, "could not create sysfs files\n");
+               dev_info(&pdev->dev, "could not create sysfs files\n");
 
        return 0;
 
@@ -2822,16 +3212,19 @@ static int twl6030_bci_battery_suspend(struct device *dev)
        if (ret)
                goto err;
 
-       cancel_delayed_work(&di->twl6030_bci_monitor_work);
-       cancel_delayed_work(&di->twl6030_current_avg_work);
+              //cancel_delayed_work(&di->work);
+        cancel_delayed_work(&di->twl6030_bci_monitor_work);
+       //cancel_delayed_work(&di->twl6030_current_avg_work);
+
+       di->suspend_capacity = di->capacity;
 
        /* We cannot tolarate a sleep longer than 30 seconds
         * while on ac charging we have to reset the BQ watchdog timer.
         */
-       if ((di->charger_source == POWER_SUPPLY_TYPE_MAINS) &&
-               ((wakeup_timer_seconds > 25) || !wakeup_timer_seconds)) {
-               wakeup_timer_seconds = 25;
-       }
+//     if ((di->charger_source == POWER_SUPPLY_TYPE_MAINS) &&
+//             ((wakeup_timer_seconds > 25) || !wakeup_timer_seconds)) {
+//             wakeup_timer_seconds = 25;
+//     }
 
        /*reset the BQ watch dog*/
        events = BQ2415x_RESET_TIMER;
@@ -2865,6 +3258,7 @@ static int twl6030_bci_battery_resume(struct device *dev)
        u8 rd_reg = 0;
        int ret;
 
+       di->resume_status =1;
        ret = twl6030battery_temp_setup(true);
        if (ret) {
                pr_err("%s: Temp measurement setup failed (%d)!\n",
@@ -2889,8 +3283,9 @@ static int twl6030_bci_battery_resume(struct device *dev)
        if (ret)
                goto err;
 
-       schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);
-       schedule_delayed_work(&di->twl6030_current_avg_work, 50);
+       queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
+       //queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work, 50);
+       //queue_delayed_work(di->freezable_work, &di->work, di->interval);
 
        events = BQ2415x_RESET_TIMER;
        blocking_notifier_call_chain(&notifier_list, events, NULL);