UPSTREAM: clk: rockchip: release io resource when failing to init clk
[firefly-linux-kernel-4.4.55.git] / drivers / power / twl6030_bci_battery.c
old mode 100755 (executable)
new mode 100644 (file)
index 15c6511..4441fe2
 #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
 extern unsigned int twl6030_get_usb_max_power(struct otg_transceiver *x);
@@ -326,6 +334,14 @@ struct twl6030_bci_device_info {
        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);
@@ -616,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);
@@ -646,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);
@@ -757,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)
@@ -832,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;
@@ -975,7 +997,7 @@ static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
                di->bat_health = POWER_SUPPLY_HEALTH_OVERHEAT;
        }
        if (stat_reset & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) {
-               dev_err(di->dev, "Battery temperature within range\n");
+               dev_dbg(di->dev, "Battery temperature within range\n");
                di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
        }
        if (di->features & TWL6032_SUBCLASS)
@@ -984,7 +1006,7 @@ 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)
@@ -1062,7 +1084,7 @@ 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_info(di->dev, "Charger fault detected STS, INT1, INT2 %x %x %x\n",
            usb_charge_sts, usb_charge_sts1, usb_charge_sts2);
@@ -1084,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);
@@ -1098,15 +1121,20 @@ 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");
                }
        }
 
@@ -1122,7 +1150,7 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
        }
        if (stat1 & CONTROLLER_STAT1_BAT_TEMP_OVRANGE) {
                charger_stop = 1;
-                dev_err(di->dev,
+                dev_dbg(di->dev,
                        "Charger error : Battery temperature overrange\n");
                di->bat_health = POWER_SUPPLY_HEALTH_OVERHEAT;
        }
@@ -1134,24 +1162,24 @@ 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_err(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) {
                        end_of_charge = 1;
                        di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
-                       dev_info(di->dev, "Charger: Full charge\n");
+                       dev_dbg(di->dev, "Charger: Full charge\n");
                }
 
                if (linear & LINEAR_CHRG_STS_VBATOV) {
                        di->bat_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
-                        dev_err(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_err(di->dev,
+                        dev_dbg(di->dev,
                                "Charger error : Linear Status: VSYSOV\n");
                }
        }
@@ -1168,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);
 
@@ -1213,7 +1242,7 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
 
                if (sts_int2 & CURRENT_TERM) {
                        charger_stop = 1;
-                        dev_err(di->dev, "Charger error: CURRENT_TERM\n");
+                        dev_dbg(di->dev, "Charger error: CURRENT_TERM\n");
                }
        }
 
@@ -1221,14 +1250,14 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
                dev_dbg(di->dev, "Charger: CHARGEUSB_STAT\n");
 
                if (sts_int2 & ANTICOLLAPSE)
-                        dev_err(di->dev, "Charger error: ANTICOLLAPSE\n");
+                        dev_dbg(di->dev, "Charger error: ANTICOLLAPSE\n");
        }
 
        if (sts & CHARGERUSB_THMREG) {
                dev_dbg(di->dev, "Charger: CHARGERUSB_THMREG\n");
 
                if (sts_int1 & CHARGERUSB_STATUS_INT1_TMREG)
-                       dev_err(di->dev, "Charger error: TMREG\n");
+                       dev_dbg(di->dev, "Charger error: TMREG\n");
        }
 
        if (sts & CHARGERUSB_FAULT) {
@@ -1245,7 +1274,7 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
                        if (sts_int1 & CHARGERUSB_STATUS_INT1_BAT_OVP) {
                                di->bat_health =
                                        POWER_SUPPLY_HEALTH_OVERVOLTAGE;
-                               dev_err(di->dev, "Charger error : BAT_OVP\n");
+                               dev_dbg(di->dev, "Charger error : BAT_OVP\n");
                        }
                }
 
@@ -1262,7 +1291,7 @@ static irqreturn_t twl6032charger_fault_interrupt_hw(int irq, void *_di)
                        printk(KERN_ERR "Charger error : POOR_SRC\n");
                }
                if (sts_int1 & CHARGERUSB_STATUS_INT1_SLP_MODE)
-                       dev_err(di->dev, "Charger error: SLP_MODE\n");
+                       dev_dbg(di->dev, "Charger error: SLP_MODE\n");
 
                if (sts_int1 & CHARGERUSB_STATUS_INT1_VBUS_OVP) {
                        di->bat_health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
@@ -1453,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;
@@ -1517,13 +1548,35 @@ static void twl6030_current_avg(struct work_struct *work)
 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.
@@ -1535,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);
@@ -1550,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)
@@ -1571,7 +1665,10 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
                        curr_capacity = 90;
                else if (di->voltage_mV >= 3900)
                                curr_capacity = 100;
-//     }
+       }
+       
+*/
+
 
        /* if we disabled charging to check capacity,
         * enable it again after we read the
@@ -1589,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) {
@@ -1596,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;
@@ -1605,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)
@@ -1618,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.channels = (1 << di->gpadc_vbat_chnl);
        req.active = 0;
        req.func_cb = NULL;
        ret = twl6030_gpadc_conversion(&req);
 
        queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
-                       msecs_to_jiffies(1000 * di->monitoring_interval));
+                       msecs_to_jiffies(TIMER_MS_COUNTS)); //* di->monitoring_interval
+       
        if (ret < 0) {
-               dev_info(di->dev, "gpadc conversion failed: %d\n", ret);
+               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];
 
@@ -1661,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,
@@ -1697,6 +1986,8 @@ 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);
        queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
                msecs_to_jiffies(1000 * di->monitoring_interval));
@@ -1704,14 +1995,16 @@ static void twl6030_work_interval_changed(struct twl6030_bci_device_info *di)
 
 #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);
        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);
@@ -1720,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;
@@ -1743,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;
@@ -1767,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;
@@ -1839,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 */
@@ -1872,6 +2188,7 @@ static void twl6030_usb_charger_work(struct work_struct *work)
                return;
        }
        twl6030_start_usb_charger(di);
+
        power_supply_changed(&di->usb);
 }
 
@@ -1880,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:
@@ -2420,21 +2736,24 @@ 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, 0x29,CHARGERUSB_CINLIMIT);     //set vbus input current is 1A
-                       twl_i2c_write_u8(TWL6030_MODULE_CHARGER, 0x09,CHARGERUSB_VICHRG);       //set mos output current is 1A
+                       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, 0x09,CHARGERUSB_CINLIMIT);//set vbus input current is 500ma
-                       twl_i2c_write_u8(TWL6030_MODULE_CHARGER, 0x04,CHARGERUSB_VICHRG);       //set mos output current is 500ma
-               
+                       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);
@@ -2450,7 +2769,7 @@ 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__);
+       //printk("%s\n", __func__);
        if (!pdata) {
                dev_info(&pdev->dev, "platform_data not available\n");
                return -EINVAL;
@@ -2478,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)
@@ -2502,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);
@@ -2513,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);
@@ -2521,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";
@@ -2593,8 +2917,8 @@ 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_info(&pdev->dev, "could not request irq %d, status %d\n",
@@ -2629,15 +2953,41 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
        di->timer_n1 = 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);
        queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work, 500);
-
+#endif
+#if 0
        ret = twl6030battery_voltage_setup(di);
        if (ret)
                dev_info(&pdev->dev, "voltage measurement setup failed\n");
@@ -2645,7 +2995,9 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
        ret = twl6030battery_current_setup(true);
        if (ret)
                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);
@@ -2683,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);
@@ -2706,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)
@@ -2757,11 +3110,11 @@ 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_info(&pdev->dev, "Backup Bat charging setup failed\n");
@@ -2859,10 +3212,12 @@ static int twl6030_bci_battery_suspend(struct device *dev)
        if (ret)
                goto err;
 
-        //cancel_delayed_work(&di->work);
-       //cancel_delayed_work(&di->twl6030_bci_monitor_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.
         */
@@ -2903,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",
@@ -2927,7 +3283,7 @@ static int twl6030_bci_battery_resume(struct device *dev)
        if (ret)
                goto err;
 
-       //queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
+       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);