arm64: dts: rockchip: enable mbox related for rk3368-tb
[firefly-linux-kernel-4.4.55.git] / drivers / power / rk30_factory_adc_battery.c
old mode 100644 (file)
new mode 100755 (executable)
index fc52769..6979066
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/gpio.h>
 #include <linux/adc.h>
-#include <mach/iomux.h>
-#include <mach/board.h>
 #include <linux/delay.h>
 #include <linux/ktime.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/earlysuspend.h>
 #include <linux/suspend.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/power/rockchip-adc-battery.h>
+#include <linux/rk_keys.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/iio/consumer.h>
+
 #ifdef CONFIG_EARLYSUSPEND
 /* kernel/power/earlysuspend.c */
 extern suspend_state_t get_suspend_state(void);
 #endif
 
-static int rk30_battery_dbg_level = 0;
+static int rk30_battery_dbg_level;
 module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
 #define DBG( args...) \
-       do { \
-               if (rk30_battery_dbg_level) { \
-                       pr_info(args); \
-               } \
-       } while (0)
+do {\
+       if (rk30_battery_dbg_level) {\
+               pr_info(args);\
+       } \
+} while (0)
 
 #define        TIMER_MS_COUNTS          1000   
 #define        SLOPE_SECOND_COUNTS                    15       
-#define        DISCHARGE_MIN_SECOND                   45       
+#define        DISCHARGE_MIN_SECOND                   30
 #define        CHARGE_MIN_SECOND                      45       
 #define        CHARGE_MID_SECOND                      90       
 #define        CHARGE_MAX_SECOND                      250
 #define   CHARGE_FULL_DELAY_TIMES          10     
-#define   USBCHARGE_IDENTIFY_TIMES                
+#define   USBCHARGE_IDENTIFY_TIMES        2        
 
 #define        NUM_VOLTAGE_SAMPLE                             ((SLOPE_SECOND_COUNTS * 1000) / TIMER_MS_COUNTS)  
 #define        NUM_DISCHARGE_MIN_SAMPLE                 ((DISCHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS)       
@@ -79,11 +81,15 @@ module_param_named(dbg_level, rk30_battery_dbg_level, int, 0644);
 #elif defined(CONFIG_ARCH_RK2928)
 #define  BAT_DEFINE_VALUE                                         3300
 #else
-#define  BAT_DEFINE_VALUE                                           2500
+#define  BAT_DEFINE_VALUE                                        3300  /*2500*/
 #endif
 
+#define RK30_GPIO_LOW 0
+#define RK30_GPIO_HIGH 1
+
+
 
-#define BATT_FILENAME "/data/bat_last_capacity.dat"
+//#define BATT_FILENAME "/data/bat_last_capacity.dat"
 
 
 #define BATTERY_APK 
@@ -94,12 +100,13 @@ int    battery_test_flag = 0;
 int    gVoltageCnt = 3400;
 int    gDoubleVoltageCnt = 6800;
 unsigned long gSecondsCnt = 0;
-char gDischargeFlag[3] = {"on "};
+char gDischargeFlag[4] = {"on "};
+static int    g_old_cap = -1;
+static int g_uboot_incre = 0;
 
-
-#ifdef CONFIG_BATTERY_RK30_VOL3V8
-#define BATT_MAX_VOL_VALUE                             4120                    //Full  charge volate    
-#define BATT_ZERO_VOL_VALUE                            3500                    //power down voltage
+#if 1
+#define BATT_MAX_VOL_VALUE     4250/*Full  charge volatge*/
+#define BATT_ZERO_VOL_VALUE    3500/*power down voltage*/
 #define BATT_NOMAL_VOL_VALUE                         3800            
 
 static int batt_table[2*BATT_NUM+6] =
@@ -111,7 +118,7 @@ static int batt_table[2*BATT_NUM+6] =
 #define adc_to_voltage(adc_val) ((adc_val * BAT_DEFINE_VALUE * (batt_table[4] +batt_table[5])) / (1024 *batt_table[5]))
 #else
 #define BATT_MAX_VOL_VALUE                              8284                   //Full charge voltage
-#define BATT_ZERO_VOL_VALUE                             6800                   // power down voltage 
+#define BATT_ZERO_VOL_VALUE                             6900                   // power down voltage 
 #define BATT_NOMAL_VOL_VALUE                          7600                
 
 
@@ -157,6 +164,7 @@ struct rk30_adc_battery_data {
        //struct timer_list       timer;
        struct workqueue_struct *wq;
        struct delayed_work         delay_work;
+       struct delayed_work     check_work;
        struct work_struct          dcwakeup_work;
        struct work_struct                   lowerpower_work;
        bool                    resume;
@@ -205,26 +213,35 @@ struct rk30_adc_battery_data {
        int                     start_voltage_status;
        int                     charge_up_proprotion;
        int                     charge_down_proportion;
+       int                     voltage_to_local;
        unsigned long          suspend_time;
        unsigned long           resume_time;
+       int                      adc_value;
        
        int                     full_times;
        int                         charge_full_flag;
+       int                     stop_check;
+       struct notifier_block battery_nb;
 
+       int                         lower_power_flag;
+       int                         time_to_full;
 
 };
 static struct rk30_adc_battery_data *gBatteryData;
 static struct wake_lock batt_wake_lock;
+static struct wake_lock batt_wake_lock_detect_lowpower;
 static struct wake_lock charge_display_lock;
 int system_lowerpower = 0;
-
+extern void kernel_power_off(void);
 extern int dwc_vbus_status(void);
 extern int get_gadget_connect_flag(void);
 extern int dwc_otg_check_dpdm(void);
 static int  is_charge_ok(struct rk30_adc_battery_data *bat);
 static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat);
-
-
+static  bool batt_gpio_is_valid(int number)
+{
+       return number > 0 && number < 256;
+}
 #ifdef  BATTERY_APK
 //#define BAT_ADC_TABLE_LEN               11
 static ssize_t bat_param_read(struct device *dev,struct device_attribute *attr, char *buf)
@@ -237,7 +254,7 @@ static ssize_t bat_param_read(struct device *dev,struct device_attribute *attr,
                printk("i=%d batt_table=%d\n",i+17,batt_table[i+17]);
        return 0;
 }
-DEVICE_ATTR(batparam, 0664, bat_param_read,NULL);
+DEVICE_ATTR(batparam, 0444, bat_param_read, NULL);
 
 
 static ssize_t rkbatt_show_debug_attrs(struct device *dev,
@@ -323,13 +340,63 @@ static ssize_t rkbatt_restore_flag_attrs(struct device *dev,
        }
        return size;
 }
+
+static int __init adc_bootloader_setup(char *str)
+{
+
+       if(str) {
+               printk("adc.incre is %s\n", str);
+               sscanf(str, "%d", &g_uboot_incre);
+       }
+       return 0;
+}
+early_param("adc.incre", adc_bootloader_setup);
+
+static ssize_t rkbatt_show_oldcap_attrs(struct device *dev, struct device_attribute *attr, char *buf) 
+{                               
+       return sprintf(buf, "%d\n", g_old_cap);
+}
+
+static ssize_t rkbatt_restore_oldcap_attrs(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+       int old_cap;
+       
+       sscanf(buf, "%d", &old_cap);
+       
+       if(old_cap >= 0 && old_cap <= 100)
+       {
+               g_old_cap = old_cap;
+       }
+       else
+       {
+               dev_err(dev, "rk29adc_restore_oldcap_attrs err\n");
+       }
+       return size;
+}
+
+
 static struct device_attribute rkbatt_attrs[] = {
        __ATTR(state, 0664, rkbatt_show_state_attrs, rkbatt_restore_state_attrs),
        __ATTR(debug, 0664, rkbatt_show_debug_attrs, rkbatt_restore_debug_attrs),
-       __ATTR(value, 0666, rkbatt_show_value_attrs, rkbatt_restore_value_attrs),
-       __ATTR(flag,  0666, rkbatt_show_flag_attrs,  rkbatt_restore_flag_attrs),
+       __ATTR(value, 0555, rkbatt_show_value_attrs, rkbatt_restore_value_attrs),
+       __ATTR(flag,  0555, rkbatt_show_flag_attrs,  rkbatt_restore_flag_attrs),
+       __ATTR(oldcap, 0664, rkbatt_show_oldcap_attrs, rkbatt_restore_oldcap_attrs),
 };
 
+static int rk_adc_battery_iio_read(struct rk30_adc_battery_platform_data *data)
+{
+       struct iio_channel *channel = data->chan;
+       int val, ret;
+
+       ret = iio_read_channel_raw(channel, &val);
+       if (ret < 0) {
+               pr_err("read channel() error: %d\n", ret);
+               return ret;
+       }
+       return val;
+}
+
+
 static int create_sysfs_interfaces(struct device *dev)
 {
        int liTmep;
@@ -353,7 +420,7 @@ error:
 
 #endif
 
-
+#if 0
 static int rk30_adc_battery_load_capacity(void)
 {
        char value[4];
@@ -386,30 +453,49 @@ static void rk30_adc_battery_put_capacity(int loadcapacity)
        sys_write(fd, (const char __user *)value, 4);
        sys_close(fd);
 }
+#endif
+static BLOCKING_NOTIFIER_HEAD(adc_battery_chain_head);
+
+int register_adc_battery_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&adc_battery_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(register_adc_battery_notifier);
+
+int unregister_adc_battery_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&adc_battery_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_adc_battery_notifier);
+
+int adc_battery_notifier_call_chain(unsigned long val)
+{
+       return (blocking_notifier_call_chain(&adc_battery_chain_head, val, NULL)
+                       == NOTIFY_BAD) ? -EINVAL : 0;
+}
+EXPORT_SYMBOL_GPL(adc_battery_notifier_call_chain);
 
 static void rk_start_charge(struct rk30_adc_battery_data *bat)
 {
        struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
-       if (pdata->charge_set_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(pdata->charge_set_pin))
                gpio_direction_output(pdata->charge_set_pin, pdata->charge_set_level);
-       }
 }
 
 static void rk_stop_charge(struct rk30_adc_battery_data *bat)
 {
        struct rk30_adc_battery_platform_data *pdata = bat->pdata;
 
-       if (pdata->charge_set_pin != INVALID_GPIO){
+
+       if (batt_gpio_is_valid(pdata->charge_set_pin))
                gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
-       }
 }
 
 static int  get_ac_status(struct rk30_adc_battery_data *bat){
        
        struct rk30_adc_battery_platform_data *pdata = bat->pdata;
        int status = 0;
-       if (pdata->dc_det_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(pdata->dc_det_pin)) {
                if (gpio_get_value (pdata->dc_det_pin) == pdata->dc_det_level){
                                status = 1;
                        }else{
@@ -423,23 +509,26 @@ static int  get_ac_status(struct rk30_adc_battery_data *bat){
 
        return status;
 }
-// state of charge  --- charge-display
-static int  get_usb_status1(struct rk30_adc_battery_data *bat){
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 
-}
 //state of charge ----running
 static int  get_usb_status2(struct rk30_adc_battery_data *bat){
 
 //     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
        int usb_status = 0; // 0--dischage ,1 ---usb charge, 2 ---ac charge
+       int vbus_status =  dwc_vbus_status();
        
-       if (1 == dwc_vbus_status()) {
+       if (1 == vbus_status) {
                if (0 == get_gadget_connect_flag()){ 
                        if (++bat->gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){
                                bat->gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1;
                                usb_status = 2; // non-standard AC charger
                                if(bat ->pdata ->control_usb_charging)
                                        bat ->pdata ->control_usb_charging(1);
+                       }else{
+                               usb_status = 1; // connect to pc        
+                               if(bat ->pdata ->control_usb_charging)
+                                       bat ->pdata ->control_usb_charging(0);
                        }
                }else{
                                
@@ -451,7 +540,7 @@ static int  get_usb_status2(struct rk30_adc_battery_data *bat){
                
        }else{
                bat->gBatUsbChargeCnt = 0;
-               if (2 == dwc_vbus_status()) {
+               if (2 == vbus_status) {
                        usb_status = 2; //standard AC charger
                        
                        if(bat ->pdata ->control_usb_charging)
@@ -465,24 +554,22 @@ static int  get_usb_status2(struct rk30_adc_battery_data *bat){
        return usb_status;
 
 }
-
+#endif
 static int rk_battery_get_status(struct rk30_adc_battery_data *bat)
 {
        int charge_on = 0;
-       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+/*     struct rk30_adc_battery_platform_data *pdata = bat->pdata;*/
        int ac_ac_charging = 0, usb_ac_charging = 0;
        int i=0;
 
-#if defined (CONFIG_BATTERY_RK30_AC_CHARGE)
        ac_ac_charging = get_ac_status(bat);
        if(1 == ac_ac_charging)
                charge_on = 1;
-#endif
 
 #if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)  
                if (strstr(saved_command_line,"charger")){
                        wake_lock(&charge_display_lock);  //lock
-                       if( bat->pdata->usb_det_pin  != INVALID_GPIO ){
+                       if (batt_gpio_is_valid(bat->pdata->usb_det_pin)) {
                                if( gpio_get_value(bat->pdata->usb_det_pin)== bat->pdata->usb_det_level){
                                        if(( 1 == usb_ac_charging )||( 1 == ac_ac_charging ))
                                                bat -> ac_charging = 1;
@@ -579,10 +666,11 @@ static int  is_charge_ok(struct rk30_adc_battery_data *bat)
        if( 1 != bat->charge_level)
                return -1;
        
-       if((pdata->charge_ok_pin == INVALID_GPIO)&& ( pdata->charging_ok == NULL))
+       if ((!(batt_gpio_is_valid(pdata->charge_ok_pin))) && (
+               pdata->charging_ok == NULL))
                return -1;
        
-       if (pdata->charge_ok_pin != INVALID_GPIO){              
+       if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
                if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){
                        charge_is_ok =1;
                }
@@ -593,7 +681,6 @@ static int  is_charge_ok(struct rk30_adc_battery_data *bat)
        
        return charge_is_ok;
 
-
 }
 
 
@@ -633,6 +720,7 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
        //discharge
                bat->charge_full_flag = 0;
                bat->full_times = 0;
+               bat->time_to_full = 0;
                bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
        }else{
        //charging          
@@ -649,6 +737,17 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
                                }
                        }else{
                                bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                               if((bat->bat_capacity == 99)&&(bat->time_to_full == 0)){
+                                       bat->time_to_full = get_seconds();
+                               }else if(bat->bat_capacity == 99)
+                               {
+                                       if(get_seconds() - bat->time_to_full > 1800){
+                                               bat->bat_capacity = 100;
+                                               bat->time_to_full = 0;
+                                       }
+
+                               }
+
                                if(bat->pdata->ctrl_charge_led != NULL)
                                                bat->pdata->ctrl_charge_led(0);
                        }
@@ -657,6 +756,19 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
 
                                bat->full_times = 0;
                                bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+
+                               if((bat->bat_capacity == 99)&&(bat->time_to_full == 0)){
+                               bat->time_to_full = get_seconds();
+                               }else if(bat->bat_capacity == 99)
+                               {
+                                       if(get_seconds() - bat->time_to_full > 1800){
+                                               bat->bat_capacity = 100;
+                                               bat->time_to_full = 0;
+                                       }
+
+                               }
+
+
                        }else{
                                bat->full_times++;
 
@@ -681,27 +793,50 @@ static int rk30_adc_battery_status_samples(struct rk30_adc_battery_data *bat)
 
        return charge_level;
 }
+
+static int rk_adc_battery_iio_read_refvol(struct rk30_adc_battery_platform_data *data)
+{
+       struct iio_channel *channel = data->ref_voltage_chan;
+       int val, ret;
+
+       ret = iio_read_channel_raw(channel, &val);
+       if (ret < 0) {
+               pr_err("read channel() error: %d\n", ret);
+               return ret;
+       }
+       return val;
+}
+
+static int get_ref_voltage(struct rk30_adc_battery_data *bat)
+{
+       int data_value;
+       struct regulator *logic;
+       int voltage, ref_voltage;
+
+       logic = regulator_get(NULL, "vdd_arm");
+       voltage = regulator_get_voltage(logic);
+       data_value = rk_adc_battery_iio_read_refvol(bat->pdata);
+       ref_voltage = voltage*1024/data_value/1000;
+
+       return ref_voltage;
+}
 static int rk_adc_voltage(struct rk30_adc_battery_data *bat, int value)
 {
        int voltage;
-
-       int ref_voltage; //reference_voltage
-       int pullup_res;
-       int pulldown_res;
+       int ref_voltage;
 
        ref_voltage = bat ->pdata->reference_voltage;
-       pullup_res = bat ->pdata->pull_up_res;
-       pulldown_res = bat ->pdata->pull_down_res;
 
-       if(ref_voltage && pullup_res && pulldown_res){
-               
-               voltage =  ((value * ref_voltage * (pullup_res + pulldown_res)) / (1024 * pulldown_res));
+       if (ref_voltage) {
+               if (bat->pdata->auto_calibration == 1)
+                       ref_voltage = get_ref_voltage(bat);
+               voltage = (value * ref_voltage * (batt_table[4] + batt_table[5])) / (1024 * batt_table[5]);
+               DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
                
        }else{
-               voltage = adc_to_voltage(value);        
+               voltage = adc_to_voltage(value);
        }
-               
-               
+       DBG("ref_voltage =%d, voltage=%d\n", ref_voltage, voltage);
        return voltage;
 
 }
@@ -738,7 +873,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
 
 
        value = bat->adc_val;
-       adc_async_read(bat->client);
+       bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
 
        *(bat->pSamples++) = rk_adc_voltage(bat,value);
 
@@ -786,7 +921,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
                                if((get_seconds() - gSecondsCnt) > 30){
                                        gSecondsCnt = get_seconds();
                                        if((gVoltageCnt - bat->bat_voltage) > 15){
-                                               strncpy(gDischargeFlag, "off" ,3);      
+                                               strncpy(gDischargeFlag, "off" ,4);      
                                        }
                                        gVoltageCnt = bat->bat_voltage;
 
@@ -802,7 +937,7 @@ static void rk30_adc_battery_voltage_samples(struct rk30_adc_battery_data *bat)
                                if((get_seconds() - gSecondsCnt) > 30){
                                        gSecondsCnt = get_seconds();
                                        if((gDoubleVoltageCnt - bat->bat_voltage) > 30){
-                                               strncpy(gDischargeFlag, "off" ,3);      
+                                               strncpy(gDischargeFlag, "off" ,4);      
                                        }
                                        gDoubleVoltageCnt =bat->bat_voltage;
                                }
@@ -820,11 +955,15 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
        int capacity = 0;
 
        int  *p;
+
        if (bat->pdata->use_board_table)
-               p = bat->pdata->board_batt_table;       
+               p = bat->pdata->board_batt_table;
+       else if (bat->pdata->dts_batt_table)
+               p = bat->pdata->dts_batt_table;
        else 
                p = batt_table;
 
+
        if (1 == bat->charge_level){  //charge
                if(0 == bat->start_voltage_status ){
                        if(BatVoltage >= (p[2*BATT_NUM +5])){
@@ -850,6 +989,9 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 
                        DBG("start_voltage=%d,start_capacity =%d\n", bat->charge_start_voltage, bat->charge_start_capacity);
                        DBG("charge_down_proportion =%d,charge_up_proprotion=%d\n",bat ->charge_down_proportion,bat ->charge_up_proprotion);
+                       for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
+                               if(((p[i]) <= bat->charge_start_voltage) && (bat->charge_start_voltage <  (p[i+1])))    
+                                       bat->voltage_to_local = i;
                                if(BatVoltage >= (p[2*BATT_NUM +5])){
                                        capacity = 100;
                                }else{  
@@ -862,10 +1004,13 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
                                                                for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
                                                                        if(((p[i]) <= BatVoltage) && (BatVoltage <  (p[i+1]))){
                                                                                if( p[i+1] < bat->charge_start_voltage ){
-                                                                                       capacity =(i-(BATT_NUM +6))*(bat ->charge_down_proportion) + ((BatVoltage - p[i]) *  bat ->charge_down_proportion)/ (p[i+1]- p[i]);
+                                                                                       capacity =bat->charge_start_capacity - ((p[i+1] -BatVoltage) * bat->charge_start_capacity/(bat->voltage_to_local -17+1))/ (p[i+1]- p[i]) - (bat->voltage_to_local- (i ))*bat->charge_start_capacity/(bat->voltage_to_local -17+1);
+                                                                                        DBG("1<<<<<<< %d  bat->voltage_to_local =%d capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i, bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+                                                               
                                                                                }
                                                                                else {
-                                                                                       capacity = (i-(BATT_NUM +6))*(bat ->charge_down_proportion) + ((BatVoltage - p[i]) *  bat ->charge_down_proportion)/ (bat->charge_start_voltage - p[i]);
+                                                                                       capacity =bat->charge_start_capacity - ((bat->charge_start_voltage -BatVoltage) * bat->charge_start_capacity/(bat->voltage_to_local -17+1) )/ (bat->charge_start_voltage - p[i]);
+                                                                                       DBG("2<<<<<< %d   capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i,capacity,BatVoltage,p[i], p[i+1]);
                                                                                }
                                                                                break;
                                                                        }
@@ -877,11 +1022,13 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
                                                                                for(i = BATT_NUM +6; i <2*BATT_NUM +5; i++)
                                                                                        if(((p[i]) <= BatVoltage) && (BatVoltage <  (p[i+1]))){
                                                                                                if( p[i] > bat->charge_start_voltage ){
-                                                                                                       capacity = bat->charge_start_capacity + (i - (BATT_NUM +6)-bat->charge_start_capacity/10)*(bat ->charge_up_proprotion) + ((BatVoltage - p[i]) *  bat ->charge_up_proprotion)/ (p[i+1]- p[i]);
+                                                                                                       capacity = bat->charge_start_capacity + (i +1- (bat->voltage_to_local))*(100- bat->charge_start_capacity )/( 10 -  (bat->voltage_to_local  - 17)) + (BatVoltage - p[i]) * (100- bat->charge_start_capacity )/( 10 -  (bat->voltage_to_local -17))/ (p[i+1]- p[i]);
+                                                                                                       DBG("3<<<<<<<< %d bat->voltage_to_local =%d  capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i, bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
                                                                                                }
                                                                                                else {
-                                                                                                      capacity = bat->charge_start_capacity + (i - (BATT_NUM +6)-bat->charge_start_capacity/10)*(bat ->charge_up_proprotion) + ((BatVoltage - p[i]) *  bat ->charge_up_proprotion)/ (p[i+1] - bat->charge_start_voltage );
-                                                                                                       }
+                                                                                                      capacity = bat->charge_start_capacity + (BatVoltage - bat->charge_start_voltage) * (100- bat->charge_start_capacity )/( 10 -  (bat->voltage_to_local-17 )) /(p[i+1] - bat->charge_start_voltage );
+                                                                                                       DBG(" 4<<<<<<<<<%d bat->voltage_to_local =%d  capacity = %d BatVoltage =%d  p[i] = %d,p[i+1] = %d  \n", i,bat->voltage_to_local,capacity,BatVoltage,p[i], p[i+1]);
+                                                                                               }
                                                                                                break;
                                                                                        }
 
@@ -919,14 +1066,15 @@ static int rk30_adc_battery_voltage_to_capacity(struct rk30_adc_battery_data *ba
 
                }
 
+       DBG("real_voltage_to_capacity =%d\n" ,capacity);
+
     return capacity;
 }
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 
 static void rk_usb_charger(struct rk30_adc_battery_data *bat)
 {
-
        int capacity = 0;
-//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
        int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
        int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
 
@@ -934,8 +1082,15 @@ static void rk_usb_charger(struct rk30_adc_battery_data *bat)
                        bat ->charge_start_voltage = bat ->bat_voltage;
                        bat ->start_voltage_status = 1;
                        bat ->charge_start_capacity = bat ->bat_capacity;
-                       bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
-                       bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+                       if(bat ->charge_start_capacity%10 != 0){
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+                       }else{
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10;
+
+
+                       }
        }
 
        capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
@@ -949,22 +1104,40 @@ static void rk_usb_charger(struct rk30_adc_battery_data *bat)
                                        timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
                        if (++(bat->gBatCapacityusbChargeCnt) >= timer_of_charge_sample){
                                bat->gBatCapacityusbChargeCnt  = 0;
-                               if (bat->bat_capacity <= 99){
+                               if (bat->bat_capacity < 99){
                                        bat->bat_capacity++;
                                        bat->bat_change  = 1;
                                }
                        }
                        bat->gBatCapacityChargeCnt = 0;
                        bat ->gBatCapacityusbdisChargeCnt = 0;//get_suspend_state(void)
-               }else if(( get_suspend_state() == PM_SUSPEND_MEM)&&(capacity < bat->bat_capacity)){
+               }else //if(( get_suspend_state() != PM_SUSPEND_MEM)&&(capacity < bat->bat_capacity)){
                // if((gpio_get_value (bat->pdata->back_light_pin) == 1)&&(capacity < bat->bat_capacity)){
-                       if (capacity < bat->bat_capacity){
-                               if(capacity + 10 > bat->bat_capacity  )
-                                       timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10;  //5s
-                               else if(capacity  + 7 > bat->bat_capacity )
-                                       timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5; //10s
-                                       else if(capacity  + 3> bat->bat_capacity )
-                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
+               if((capacity < bat->bat_capacity)){
+                               DBG("USB CHARGE DOWN\n");
+
+               //      if (capacity < bat->bat_capacity){
+                               if(capacity <10){
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 40; // 13
+                               }else if(capacity < 20){
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -25; // 13
+                                       else
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 35; // 13
+                               }else{
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 15; // 13
+                                       else
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 20; // 13
+                       }
                                
                                if (++(bat->gBatCapacityusbdisChargeCnt) >= timer_of_discharge_sample){
                                        bat->gBatCapacityusbdisChargeCnt = 0;
@@ -974,12 +1147,13 @@ static void rk_usb_charger(struct rk30_adc_battery_data *bat)
                                        }
                                }
                                
-                       }
+                       //}
                        bat->gBatCapacityusbChargeCnt  = 0;
 
                }
-               else if(get_suspend_state() == PM_SUSPEND_MEM){
+               else //if(get_suspend_state() == PM_SUSPEND_MEM){
                        //if(gpio_get_value (bat->pdata->back_light_pin) == 0){
+                       {
 
 
                        bat->gBatCapacityusbdisChargeCnt = 0;
@@ -1029,6 +1203,7 @@ static void rk_usb_charger(struct rk30_adc_battery_data *bat)
                bat->capacitytmp = capacity;
 
 }
+#endif
 static void rk_ac_charger(struct rk30_adc_battery_data *bat)
 {
        int capacity = 0;
@@ -1038,8 +1213,15 @@ static void rk_ac_charger(struct rk30_adc_battery_data *bat)
                bat->charge_start_voltage = bat->bat_voltage;
                bat->start_voltage_status = 1;
                bat->charge_start_capacity = bat->bat_capacity;
-               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
-               bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+                       if(bat ->charge_start_capacity%10 != 0){
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
+                       }else{
+                               bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10;
+                               bat ->charge_down_proportion = bat ->charge_start_capacity/10;
+
+
+                       }
        }
        capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
                if (capacity > bat->bat_capacity){
@@ -1051,7 +1233,7 @@ static void rk_ac_charger(struct rk30_adc_battery_data *bat)
                                        timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE - 2; // 13
                        if (++(bat->gBatCapacityacChargeCnt) >= timer_of_charge_sample){
                                bat->gBatCapacityacChargeCnt  = 0;
-                               if (bat->bat_capacity <= 99){
+                               if (bat->bat_capacity < 99){
                                        bat->bat_capacity++;
                                        bat->bat_change  = 1;
                                }
@@ -1112,18 +1294,36 @@ static void rk_battery_charger(struct rk30_adc_battery_data *bat)
 {
 
        int capacity = 0;
-       int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
+       int timer_of_discharge_sample = DISCHARGE_MIN_SECOND;
        
        capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);
 
                if (capacity < bat->bat_capacity){
-                       if(capacity + 3 > bat->bat_capacity  )
-                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -5;  //5s
-                       else if(capacity  + 7 > bat->bat_capacity )
-                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE -10; //10s
-                               else if(capacity  + 10> bat->bat_capacity )
-                                       timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 15; // 13
+                       #if 0
+                               if(capacity <10){
+                                               timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE - 40; // 13
+                               }else 
+                               #endif
+                               if(capacity < 20){
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -25; // 13
+                                       else
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 35; // 13
+                               }else{
+                                       if(capacity + 3 > bat->bat_capacity  )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -5;  //5s
+                                       else if(capacity  + 7 > bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND -10; //10s
+                                       else if(capacity  + 10> bat->bat_capacity )
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 15; // 13
+                                       else
+                                               timer_of_discharge_sample = DISCHARGE_MIN_SECOND - 20; // 13
 
+                       }
                        if (++(bat->gBatCapacityDisChargeCnt) >= timer_of_discharge_sample){
                                bat->gBatCapacityDisChargeCnt = 0;
                                if (bat->bat_capacity > 0){
@@ -1151,7 +1351,7 @@ static void rk30_adc_battery_capacity_samples(struct rk30_adc_battery_data *bat)
 {
 //     int capacity = 0;
 //     int timer_of_charge_sample = NUM_CHARGE_MIN_SAMPLE;
-       int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
+//     int timer_of_discharge_sample = NUM_CHARGE_MIN_SAMPLE;
 
        if (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE)  {
                bat->gBatCapacityDisChargeCnt = 0;
@@ -1184,18 +1384,18 @@ static void rk30_adc_battery_poweron_capacity_check(struct rk30_adc_battery_data
         int cnt = 50 ;
 
        new_capacity = bat ->bat_capacity;
-#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
-       if(dwc_otg_check_dpdm() != 0)
-               bat ->bat_status = POWER_SUPPLY_STATUS_CHARGING; // add for charging.
-#endif
                
        while( cnt -- ){
-           old_capacity = rk30_adc_battery_load_capacity();
-           if( old_capacity >= 0 ){
+               g_old_cap = g_old_cap + g_uboot_incre;
+               if(g_old_cap > 100)
+                       g_old_cap = 100;
+           old_capacity = g_old_cap;   // rk30_adc_battery_load_capacity();
+           if( old_capacity != -1 ){
                break ;
            }
            msleep(100);
        }
+        printk("func:%s; line:%d; old_capacity = %d; new_capacity = %d; g_uboot_incre = %d\n", __func__, __LINE__, old_capacity, new_capacity,g_uboot_incre);
 
        if ((old_capacity < 0) || (old_capacity > 100)){
                old_capacity = new_capacity;
@@ -1208,21 +1408,20 @@ static void rk30_adc_battery_poweron_capacity_check(struct rk30_adc_battery_data
        }
        else if (bat ->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
        //chargeing state
-
-               if( bat  ->pdata->is_reboot_charging == 1)
-                       bat ->bat_capacity = (old_capacity < 10) ?(old_capacity+2):old_capacity;
-               else
-                       bat ->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+               bat->bat_capacity = (old_capacity < 10) ? (old_capacity + 2) : old_capacity;
        }else{
-               if(new_capacity > old_capacity + 50 )
-                       bat ->bat_capacity = new_capacity;
-               else
-                       bat ->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;  //avoid the value of capacity increase 
+                       bat ->bat_capacity = old_capacity;
+               if(bat->bat_capacity == 100)
+                       bat->bat_capacity = 99;
+               if(bat->bat_capacity == 0)
+                       bat->bat_capacity =1;
        }
-
+       DBG("oldcapacity %d,newcapacity %d,capacity %d\n", old_capacity
+               , new_capacity, bat->bat_capacity);
 
        bat ->bat_change = 1;
 }
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
 #define to_battery_usb_device_info(x) container_of((x), \
                struct rk30_adc_battery_data, usb);
 
@@ -1236,9 +1435,10 @@ static int rk30_adc_battery_get_usb_property(struct power_supply *psy,
                case POWER_SUPPLY_PROP_ONLINE:
                        if (psy->type == POWER_SUPPLY_TYPE_USB){
                                val->intval = bat ->usb_charging;
-                               if( 1 == bat->charge_full_flag)
-                                       val->intval = 0;
-
+                               if (strstr(saved_command_line,"charger") == NULL){                                      
+                                       if( 1 == bat->charge_full_flag)
+                                               val->intval = 0;
+                               }
                        }
                        break;
 
@@ -1265,7 +1465,7 @@ static struct power_supply rk30_usb_supply =
        .properties     = rk30_adc_battery_usb_props,
        .num_properties = ARRAY_SIZE(rk30_adc_battery_usb_props),
 };
-
+#endif
 static irqreturn_t rk30_adc_battery_dc_wakeup(int irq, void *dev_id)
 {   
        disable_irq_nosync(irq);
@@ -1288,9 +1488,10 @@ static int rk30_adc_battery_get_ac_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_ONLINE:
                if (psy->type == POWER_SUPPLY_TYPE_MAINS){
                        val->intval = bat ->ac_charging;
-                       if( 1 == bat->charge_full_flag)
-                               val->intval = 0;
-
+                       if (strstr(saved_command_line,"charger")  == NULL ){
+                               if( 1 == bat->charge_full_flag)
+                                       val->intval = 0;
+                       }
                }
                break;
                
@@ -1327,9 +1528,6 @@ static void rk30_adc_battery_dcdet_delaywork(struct work_struct *work)
        struct rk30_adc_battery_data  *bat = container_of((work), \
                struct rk30_adc_battery_data, dcwakeup_work);
 
-       rk28_send_wakeup_key(); // wake up the system
-
-       
        pdata    = bat->pdata;
        irq        = gpio_to_irq(pdata->dc_det_pin);
        free_irq(irq, NULL);
@@ -1341,6 +1539,7 @@ static void rk30_adc_battery_dcdet_delaywork(struct work_struct *work)
        }
 
        power_supply_changed(&bat ->ac);
+       rk_send_wakeup_key();
 
        bat ->bat_status_cnt = 0;        //the state of battery is change
 
@@ -1377,6 +1576,7 @@ static int rk30_adc_battery_get_property(struct power_supply *psy,
                                 union power_supply_propval *val)
 {              
        int ret = 0;
+       int voltage;
        struct rk30_adc_battery_data  *bat = container_of((psy), \
                        struct rk30_adc_battery_data, bat);
        switch (psp) {
@@ -1393,7 +1593,9 @@ static int rk30_adc_battery_get_property(struct power_supply *psy,
                        DBG("gBatPresent=%d\n",val->intval);
                        break;
                case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-                       val ->intval = rk30_adc_battery_get_voltage(bat);
+               //      val ->intval = rk30_adc_battery_get_voltage(bat);
+                       voltage = rk30_adc_battery_get_voltage(bat);
+                       val->intval = voltage*1000;
                        DBG("gBatVoltage=%d\n",val->intval);
                        break;
                case POWER_SUPPLY_PROP_CAPACITY:
@@ -1454,7 +1656,8 @@ static void rk30_adc_battery_resume_check(struct rk30_adc_battery_data *bat)
        bat ->old_charge_level = -1;
        bat ->pSamples = bat->adc_samples;
 
-       adc_sync_read(bat->client);                             //start adc sample
+       bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
        level = oldlevel =  rk_battery_get_status(bat);//rk30_adc_battery_status_samples(bat);//init charge status
 
        for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) {               //0.3 s   
@@ -1473,12 +1676,18 @@ static void rk30_adc_battery_resume_check(struct rk30_adc_battery_data *bat)
        //if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){
        if( 1 == level ){
        //chargeing state
-               bat->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
+               bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;
        }
        else{
                bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;  // aviod the value of capacity increase    dicharge
        }
 
+               if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
+                       if (gpio_get_value(bat ->pdata->batt_low_pin) == bat ->pdata->batt_low_level)
+                               bat->bat_capacity = 0;
+
+               }
+       return;
 }
 
 static int rk30_adc_battery_suspend(struct platform_device *dev, pm_message_t state)
@@ -1490,7 +1699,7 @@ static int rk30_adc_battery_suspend(struct platform_device *dev, pm_message_t st
        data ->suspend_time = get_seconds();
        cancel_delayed_work(&data ->delay_work);
        
-       if( data ->pdata->batt_low_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
                
                irq = gpio_to_irq(data ->pdata->batt_low_pin);
                enable_irq(irq);
@@ -1504,10 +1713,14 @@ static int rk30_adc_battery_resume(struct platform_device *dev)
 {
        int irq;
        struct rk30_adc_battery_data *data = platform_get_drvdata(dev);
+        if( data->bat_capacity < 10 ){
+               wake_lock_timeout(&batt_wake_lock_detect_lowpower,15*HZ);
+               data->bat_change  = 1;
+       }
        data ->resume_time = get_seconds();
        data ->resume = true;
        queue_delayed_work(data->wq, &data ->delay_work, msecs_to_jiffies(100));
-       if( data ->pdata->batt_low_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
                
                irq = gpio_to_irq(data ->pdata ->batt_low_pin);
                disable_irq_wake(irq);
@@ -1524,25 +1737,31 @@ static int rk30_adc_battery_resume(struct platform_device *dev)
 unsigned long AdcTestCnt = 0;
 static void rk30_adc_battery_timer_work(struct work_struct *work)
 {
-struct rk30_adc_battery_data  *bat = container_of((work), \
-               struct rk30_adc_battery_data, delay_work);
+       struct rk30_adc_battery_data  *bat = container_of((work), struct
+               rk30_adc_battery_data, delay_work.work);
 
 #ifdef CONFIG_PM
        if (bat ->resume) {
-               if( (bat->resume_time - bat->suspend_time) >= 3600 )
+       //      if( (bat->resume_time - bat->suspend_time) >= 1800 )
                        rk30_adc_battery_resume_check(bat);
-               else
-                       bat->bat_capacity = bat->suspend_capacity;
+               //else
+                       //bat->bat_capacity = bat->suspend_capacity;
                bat ->resume = false;
+               bat ->bat_change =1;
        }
 #endif
-
+       bat->stop_check = 1;
+       if( 1 == bat ->lower_power_flag ){
+                       bat ->bat_capacity = 0;
+                       bat ->bat_change =1;
+       }
        if (bat ->poweron_check){   
                bat ->poweron_check = 0;
                rk30_adc_battery_poweron_capacity_check(bat);
        }
 
        bat ->charge_level = rk_battery_get_status(bat);
+       DBG("bat ->charge_level =%d\n", bat ->charge_level);
        rk30_adc_battery_status_samples(bat);
        rk30_adc_battery_voltage_samples(bat);
        rk30_adc_battery_capacity_samples(bat);
@@ -1566,12 +1785,14 @@ struct rk30_adc_battery_data  *bat = container_of((work), \
        /*update battery parameter after adc and capacity has been changed*/
        if(bat ->bat_change){
                bat ->bat_change= 0;
-               if(0 == bat ->bat_capacity){
-                       bat ->ac_charging = 0;
-                       bat ->usb_charging = 0;
+               if (strstr(saved_command_line,"charger") == NULL){       //when low charging-current,not in charging-displays   
+                       if(0 == bat ->bat_capacity){
+                               bat ->ac_charging = 0;
+                               bat ->usb_charging = 0;
 
+                       }
                }
-               rk30_adc_battery_put_capacity(bat ->bat_capacity);
+               // rk30_adc_battery_put_capacity(bat ->bat_capacity);
                power_supply_changed(&bat ->bat);
                power_supply_changed(&bat ->ac);
 #if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
@@ -1600,65 +1821,46 @@ struct rk30_adc_battery_data  *bat = container_of((work), \
 static int rk30_adc_battery_io_init(struct rk30_adc_battery_platform_data *pdata)
 {
        int ret = 0;
-       
-       if (pdata->io_init) {
-               pdata->io_init();
-               return 0;
-       }
-       
-       //charge control pin
-       if (pdata->charge_set_pin != INVALID_GPIO){
-               ret = gpio_request(pdata->charge_set_pin, NULL);
-               if (ret) {
-                       printk("failed to request dc_det gpio\n");
-                       goto error;
-                       }
-               gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
-       }
-       
-       //dc charge detect pin
-       if (pdata->dc_det_pin != INVALID_GPIO){
+
+       if (batt_gpio_is_valid(pdata->dc_det_pin)) {
                ret = gpio_request(pdata->dc_det_pin, NULL);
                if (ret) {
-                       printk("failed to request dc_det gpio\n");
+                       pr_info("failed to request dc_det gpio\n");
                        goto error;
                }
        
-               gpio_pull_updown(pdata->dc_det_pin, GPIOPullUp);//important
                ret = gpio_direction_input(pdata->dc_det_pin);
                if (ret) {
-                       printk("failed to set gpio dc_det input\n");
+                       pr_info("failed to set gpio dc_det input\n");
                        goto error;
                }
        }
        
        //charge ok detect
-       if (pdata->charge_ok_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(pdata->charge_ok_pin)) {
                ret = gpio_request(pdata->charge_ok_pin, NULL);
                if (ret) {
-                       printk("failed to request charge_ok gpio\n");
+                       pr_err("failed to request charge_ok gpio\n");
                        goto error;
                }
        
-               gpio_pull_updown(pdata->charge_ok_pin, GPIOPullUp);//important
                ret = gpio_direction_input(pdata->charge_ok_pin);
                if (ret) {
-                       printk("failed to set gpio charge_ok input\n");
+                       pr_err("failed to set gpio charge_ok input\n");
                        goto error;
                }
        }
        //batt low pin
-       if( pdata->batt_low_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(pdata->batt_low_pin)) {
                ret = gpio_request(pdata->batt_low_pin, NULL);
                if (ret) {
-                       printk("failed to request batt_low_pin gpio\n");
+                       pr_err("failed to request batt_low_pin gpio\n");
                        goto error;
                }
        
-               gpio_pull_updown(pdata->batt_low_pin, GPIOPullUp); 
                ret = gpio_direction_input(pdata->batt_low_pin);
                if (ret) {
-                       printk("failed to set gpio batt_low_pin input\n");
+                       pr_err("failed to set gpio batt_low_pin input\n");
                        goto error;
                }
        }
@@ -1672,34 +1874,107 @@ extern void kernel_power_off(void);
 int get_battery_status(void)
 {
        return system_lowerpower;
+}
+static int rk_adc_battery_poweron_status(struct rk30_adc_battery_data *bat)
+{
+       int status; 
+#if  defined CONFIG_BATTERY_RK30_USB_CHARGE
+       int otg_status = 0;
+#endif
+
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+
+       if (get_ac_status(bat) ){               
+                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                       bat -> ac_charging = 1;         
+                       if (is_charge_ok(bat)  == 1){
+                               bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                               bat->bat_capacity = 100;
+                       }
+                       power_supply_changed(&bat ->ac);
+
+       }
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       otg_status = dwc_otg_check_dpdm();
+       if( 0 != otg_status ){
+               bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+               if (is_charge_ok(bat)  == 1){
+                       bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                       bat->bat_capacity = 100;
+               }
+       }
+       
+       if(otg_status == 1){
+               bat->usb_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(0);
+       }else if(otg_status == 2){
+               bat->usb_charging = 0;
+               bat -> ac_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(1); 
+       }else{
+               bat->usb_charging = 0;
+       }
+       printk("charge_status = %d\n",otg_status);
+#endif
+       power_supply_changed(&bat ->ac);
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       power_supply_changed(&bat ->usb);
+#endif
+       if((bat -> ac_charging == 1)||(bat->usb_charging == 1)){
+               bat ->old_charge_level =1;
+               bat->charge_level = 1;
+               status =1;
+       }else{
+               bat ->old_charge_level =0;
+               bat->charge_level = 0;
+               status =0;
+       }
+       return status;  
+
+
 }
 static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 {
        int i;
        int level,oldlevel;
-       struct rk30_adc_battery_platform_data *pdata = bat->pdata;
-
+//     struct rk30_adc_battery_platform_data *pdata = bat->pdata;
+       int check_data[NUM_VOLTAGE_SAMPLE];
+       //bat ->old_charge_level
 //     pSamples = bat->adc_samples;
 
-       adc_sync_read(bat->client);                             //start adc sample
-       level = oldlevel =       rk_battery_get_status(bat);// rk30_adc_battery_status_samples(bat);//init charge status
+
+       bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+
+       DBG("first_adc_value is  %d\n", bat->adc_val);
+       level = oldlevel =       rk_adc_battery_poweron_status(bat);// rk30_adc_battery_status_samples(bat);//init charge status
 
        for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++){                //0.3 s
                mdelay(1);
                rk30_adc_battery_voltage_samples(bat);              //get voltage
                //level = rk30_adc_battery_status_samples(bat);       //check charge status
-               level = rk_battery_get_status(bat);
+#if 0
+               level = rk_adc_battery_poweron_status(bat);
 
                if (oldlevel != level){
                        oldlevel = level;                               //if charge status changed, reset sample
                        i = 0;
-               }    
-               bat->charge_level = level;
+               }  
+#endif
        }
-
-
+       for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
+               mdelay(10);
+               check_data[i] = bat->adc_val;
+               
+               bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+               bat->adc_value += check_data[i];
+       }
+       bat->adc_value  /=  NUM_VOLTAGE_SAMPLE;
+       
        bat->bat_capacity = rk30_adc_battery_voltage_to_capacity(bat, bat->bat_voltage);  //init bat_capacity
-
+       bat->capacitytmp = bat->bat_capacity;
+       level = rk_adc_battery_poweron_status(bat);
        if((1 == level)&&(0 == bat->start_voltage_status )){
                        bat->charge_start_voltage = bat->bat_voltage;
                        bat->start_voltage_status = 1;
@@ -1707,53 +1982,68 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
                        bat ->charge_up_proprotion = (100 - bat ->charge_start_capacity)/10+1;
                        bat ->charge_down_proportion = bat ->charge_start_capacity/10+1;
        }
-       
-       if (get_ac_status(bat) || dwc_otg_check_dpdm() ){
+#if 0  
+       if (get_ac_status(bat) ){               
+                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                       bat -> ac_charging = 1;         
+                       if (is_charge_ok(bat)  == 1){
+                               bat->bat_status = POWER_SUPPLY_STATUS_FULL;
+                               bat->bat_capacity = 100;
+                       }
+       }
+#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
+       if( 0 != dwc_otg_check_dpdm() ){
+               bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
                if (is_charge_ok(bat)  == 1){
                        bat->bat_status = POWER_SUPPLY_STATUS_FULL;
                        bat->bat_capacity = 100;
                }
-#if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
-               if( 0 != dwc_otg_check_dpdm() )
-                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
-               if(dwc_otg_check_dpdm() == 0){
-                       bat->usb_charging = 0;
-               }else if(dwc_otg_check_dpdm() == 1){
-                       bat->usb_charging = 1;
-                       if(bat -> pdata ->control_usb_charging)
-                               bat -> pdata ->control_usb_charging(0);
-               }else if(dwc_otg_check_dpdm() == 2){
-                       bat->usb_charging = 0;
-                       bat -> ac_charging = 1;
-                       if(bat -> pdata ->control_usb_charging)
-                               bat -> pdata ->control_usb_charging(1); 
-               }
+       }
+       
+       if(dwc_otg_check_dpdm() == 1){
+               bat->usb_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(0);
+       }else if(dwc_otg_check_dpdm() == 2){
+               bat->usb_charging = 0;
+               bat -> ac_charging = 1;
+               if(bat -> pdata ->control_usb_charging)
+                       bat -> pdata ->control_usb_charging(1); 
+       }else{
+               bat->usb_charging = 0;
+       }
 #endif
-               if(1 == get_ac_status(bat)){
-                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
-                       bat -> ac_charging = 1;
-               }
-               power_supply_changed(&bat ->ac);
+       power_supply_changed(&bat ->ac);
 #if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
-               power_supply_changed(&bat ->usb);
+       power_supply_changed(&bat ->usb);
 #endif
-
+       if((bat -> ac_charging == 1)||(bat->usb_charging == 1)){
+               bat ->old_charge_level =1;
+               bat->charge_level = 1;
        }
+
+#endif
 #if 0
        if (bat->bat_capacity == 0) {
                bat->bat_capacity = 1;
                system_lowerpower = 1;
        }
 #endif
+
        if(0 !=bat ->pdata->low_voltage_protection ){
-               if((bat->bat_voltage <=  bat ->pdata->low_voltage_protection)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING))
+               if (bat->bat_voltage <= bat->pdata->low_voltage_protection) {
                        system_lowerpower = 1;
+                       printk("protection lower power .....\n");
+                       }
        }else{
-               if((bat->bat_voltage <= BATT_ZERO_VOL_VALUE)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING))
+               if (bat->bat_voltage <= BATT_ZERO_VOL_VALUE) {
                        system_lowerpower = 1;
-
+                       pr_info("lower power bat->bat_voltage = %d\n"
+                               , bat->bat_voltage);
+                       }
        }       
-#if 1
+
+#if 0
                if ((bat->bat_voltage <= BATT_ZERO_VOL_VALUE)&&(bat->bat_status != POWER_SUPPLY_STATUS_CHARGING)){
                        kernel_power_off();
                }
@@ -1761,21 +2051,6 @@ static void rk30_adc_battery_check(struct rk30_adc_battery_data *bat)
 
 }
 
-static void rk30_adc_battery_callback(struct adc_client *client, void *param, int result)
-{
-       struct rk30_adc_battery_data  *bat = container_of((client), \
-                               struct rk30_adc_battery_data, client);
-
-       if (result < 0){
-               DBG("adc_battery_callback    resule < 0 , the value ");
-               return;
-       }else{
-               gBatteryData->adc_val = result;
-               DBG("result = %d, gBatteryData->adc_val = %d\n", result, gBatteryData->adc_val );
-       }
-       return;
-}
-
 static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
 {
        int irq;
@@ -1783,13 +2058,12 @@ static void rk30_adc_battery_lowerpower_delaywork(struct work_struct *work)
        struct rk30_adc_battery_data  *bat = container_of((work), \
                        struct rk30_adc_battery_data, lowerpower_work);
 
-       if( bat->pdata->batt_low_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(bat->pdata->batt_low_pin)) {
                irq = gpio_to_irq(bat ->pdata ->batt_low_pin);
                disable_irq(irq);
        }
 
        printk("lowerpower\n");
-       rk28_send_wakeup_key(); // wake up the system   
        return;
 }
 
@@ -1799,24 +2073,228 @@ static irqreturn_t rk30_adc_battery_low_wakeup(int irq,void *dev_id)
        queue_work(gBatteryData->wq, &gBatteryData->lowerpower_work);
        return IRQ_HANDLED;
 }
+static void rk_lowerpower_check(struct rk30_adc_battery_data *bat)
+{
+       int adc_val;
+       int i;
+       int check_data[NUM_VOLTAGE_SAMPLE];
+       
+       for(i=0; i< NUM_VOLTAGE_SAMPLE; i++){
+               mdelay(10);
+               bat->adc_val = rk_adc_battery_iio_read(bat->pdata);
+               check_data[i] = bat->adc_val;   
+
+               adc_val += check_data[i];
+       }
+       adc_val /=NUM_VOLTAGE_SAMPLE;
+
+       DBG(">>>>>>>>>>>one>>>%d, two<<<<<%d<<<<\n",bat->adc_value,adc_val);
+       DBG(">>>>>>>>>>>firset-value>>>%d, second-value<<<<<%d<<<<\n",rk_adc_voltage(bat, bat->adc_value),rk_adc_voltage(bat, adc_val));
+
+       if((adc_val >= bat->adc_value+5) &&(bat->bat_status == POWER_SUPPLY_STATUS_NOT_CHARGING ) )//
+       {
+               printk("%d,%d\n",adc_val,bat->adc_value);
+               printk("lower-power shutdown");
+               kernel_power_off();
+       }
+
+}
+static void rk_adc_battery_check_work(struct work_struct *work)
+{
+       struct rk30_adc_battery_data  *bat =
+               container_of((work), struct
+               rk30_adc_battery_data, check_work.work);
+       
+               if(1 == get_ac_status(bat)){
+                       bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
+                       bat -> ac_charging = 1;
+               }
+               
+               power_supply_changed(&bat ->ac);
+       if(bat->stop_check != 1)
+               queue_delayed_work(bat ->wq, &bat ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+
+}
+static void poweron_lowerpoer_handle(struct rk30_adc_battery_data *bat)
+{
+#ifdef CONFIG_LOGO_LOWERPOWER_WARNING
+       if((1 ==  get_battery_status())&&(bat->bat_status == POWER_SUPPLY_STATUS_NOT_CHARGING )){
+               mdelay (1500);
+               kernel_power_off();
+       }
+#endif
+
+}
+static int battery_notifier_call(struct notifier_block *nb,
+               unsigned long event, void *data)
+{
+       struct rk30_adc_battery_data *bat=
+               container_of(nb, struct rk30_adc_battery_data, battery_nb);
+
+       switch (event) {
+       case 1:
+               rk_lowerpower_check(bat);
+               break;
+
+       case 2:
+               poweron_lowerpoer_handle(bat);
+               break;
+       default:
+               return NOTIFY_OK;
+       }
+       return NOTIFY_OK;
+}
+
+#ifdef CONFIG_OF
+static int rk31_adcbat_parse_dt(struct platform_device *pdev, struct
+rk30_adc_battery_platform_data *data)
+{
+       struct device_node *node = pdev->dev.of_node;
+       enum of_gpio_flags flags;
+       struct property *prop;
+       int length;
+       u32 value;
+       int ret;
+       int i;
+       size_t size;
+
+       struct iio_channel *channels;
+       int num = 0;
+
+       channels = iio_channel_get_all(&pdev->dev);
+       if (IS_ERR(channels))
+               pr_err("get adc channels fails\n");
+       while (channels[num].indio_dev)
+               num++;
+       data->chan = &channels[0];
+       if (num > 1)
+               data->ref_voltage_chan = &channels[1];
+       ret = of_property_read_u32(node, "auto_calibration", &value);
+       if (ret < 0) {
+               pr_info("%s:unsupport auto_calibration\n", __func__);
+               value = 0;
+       }
+       data->auto_calibration = value;
+
+       ret = of_property_read_u32(node, "ref_voltage", &value);
+       if (ret < 0) {
+               pr_info("%s:unsupport ref_voltage\n", __func__);
+               value = 0;
+       }
+       data->reference_voltage = value;
+
+       /* determine the number of config info */
+       prop = of_find_property(node, "bat_table", &length);
+       if (!prop)
+               return -EINVAL;
+
+       length /= sizeof(u32);
+
+       if (length > 0) {
+               size = (sizeof(*data->dts_batt_table)) * length;
+               data->dts_batt_table =
+                       devm_kzalloc(&(pdev->dev), size, GFP_KERNEL);
+               if (!data->dts_batt_table)
+                       return -ENOMEM;
+
+               ret = of_property_read_u32_array(node
+                       , "bat_table", data->dts_batt_table, length);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 4; i < length; i++) {
+               batt_table[i] = data->dts_batt_table[i];
+
+               pr_info("data->dts_batt_table[ %d ] %d %d\n", i
+                       , data->dts_batt_table[i], batt_table[i]);
+       }
+       data->dc_det_pin = of_get_named_gpio_flags(node
+               , "dc_det_gpio", 0, &flags);
+       if (data->dc_det_pin == -EPROBE_DEFER)
+               pr_info("%s  dc_det_gpio error\n", __func__);
+
+       if (batt_gpio_is_valid(data->dc_det_pin))
+               data->dc_det_level = (flags & OF_GPIO_ACTIVE_LOW)
+               ?  RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+       data->batt_low_pin = of_get_named_gpio_flags(node
+               , "bat_low_gpio", 0, &flags);
+       if (data->batt_low_pin == -EPROBE_DEFER)
+               pr_info("%s  bat_low_gpio error\n", __func__);
+
+       if (batt_gpio_is_valid(data->batt_low_pin))
+               data->batt_low_level = (flags & OF_GPIO_ACTIVE_LOW)
+               ?  RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+       data->charge_ok_pin = of_get_named_gpio_flags(node
+               , "chg_ok_gpio", 0, &flags);
+       if (data->charge_ok_pin == -EPROBE_DEFER)
+               pr_info("%s  chg_ok_gpio error\n", __func__);
+
+       if (batt_gpio_is_valid(data->charge_ok_pin))
+               data->charge_ok_level = (flags & OF_GPIO_ACTIVE_LOW)
+               ? RK30_GPIO_LOW : RK30_GPIO_HIGH;
+
+       ret = of_property_read_u32(node, "is_dc_charge", &value);
+       if (ret < 0) {
+               pr_info("%s:hardware unsupport dc charge\n", __func__);
+               value = 0;
+       }
+       data->is_dc_charge = value;
+
+       ret = of_property_read_u32(node, "is_usb_charge"
+               , &value);
+       if (ret < 0) {
+               pr_err("%s:hardware unsupport usb charge\n", __func__);
+               value = 0;
+       }
+       data->is_usb_charge = value;
+
+       pr_info("rk30 battery:support %s %s charger\n",
+               data->is_dc_charge ? "DC" : ""
+               , data->is_usb_charge ? "USB" : "");
+
+       return 0;
+}
+#else
+static int rk31_adcbat_parse_dt(struct platform_device
+*dev, struct rk30_adc_battery_platform_data *data)
+{
+       return -ENODEV;
+}
+#endif
+
 
 static int rk30_adc_battery_probe(struct platform_device *pdev)
 {
+
        int    ret;
        int    irq;
        int    irq_flag;
-       struct adc_client                   *client;
        struct rk30_adc_battery_data          *data;
-       struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+       struct rk30_adc_battery_platform_data *pdata;
+#ifdef CONFIG_MACH_RK_FAC
+       int i;
+       for(i=0;i<BATT_NUM;i++)
+       {
+               batt_table[6+i]=pdata->chargeArray[i];
+               batt_table[BATT_NUM+6+i]=pdata->chargeArray[i];
+       }
+#endif         
        gSecondsCnt = get_seconds();
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (data == NULL) {
+       /*data = kzalloc(sizeof(*data), GFP_KERNEL);*/
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
                ret = -ENOMEM;
-               goto err_data_alloc_failed;
-       }
+
+       /*pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);*/
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (pdata == NULL)
+               ret = -ENOMEM;
+
        memset(data, 0, sizeof(struct rk30_adc_battery_data));
        gBatteryData = data;
-
        platform_set_drvdata(pdev, data);
 
        data->pdata = pdata;
@@ -1837,12 +2315,26 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
        data->start_voltage_status = 0;
        data->charge_full_flag =0;
        data->pSamples = data->adc_samples;
+       data->lower_power_flag = 0;
+       data->capacitytmp = 0;
+       data->time_to_full = 0;
+       data->stop_check = 0;
+       data->voltage_to_local = 0;
 
        data->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
        wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock");        
        wake_lock_init(&charge_display_lock, WAKE_LOCK_SUSPEND, "charge_display_lock"); //charge_display_lock
-       
-       ret = rk30_adc_battery_io_init(pdata);
+       wake_lock_init(&batt_wake_lock_detect_lowpower
+               , WAKE_LOCK_SUSPEND, "lowpower_lock");
+
+       ret = rk31_adcbat_parse_dt(pdev, data->pdata);
+       /*ret = rk31_adcbat_parse_dt(pdev, pdata);*/
+       if (ret < 0) {
+               pr_err("failed to find rk30 adc battery platform data\n");
+               goto err_io_init;
+       }
+
+       ret = rk30_adc_battery_io_init(data->pdata);
         if (ret) {
                ret = -EINVAL;
                goto err_io_init;
@@ -1851,18 +2343,10 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
        memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2));
 
         //register adc for battery sample
-        if(0 == pdata->adc_channel)
-               client = adc_register(0, rk30_adc_battery_callback, NULL);  //pdata->adc_channel = ani0
-       else
-               client = adc_register(pdata->adc_channel, rk30_adc_battery_callback, NULL);  
-       if(!client){
-               ret = -EINVAL;
-               goto err_adc_register_failed;
-       }
-           
+       data->wq = create_singlethread_workqueue("adc_battd");
         //variable init
-       data->client  = client;
-       data->adc_val = adc_sync_read(client);
+       /*data->client  = client;*/
+       data->adc_val = rk_adc_battery_iio_read(data->pdata);
 
        data ->bat = rk30_battery_supply;
        ret = power_supply_register(&pdev->dev,&data ->bat);
@@ -1888,13 +2372,13 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
                goto err_ac_failed;
        }
 
-#if  defined (CONFIG_BATTERY_RK30_AC_CHARGE)
        //init dc dectet irq & delay work
-       if (pdata->dc_det_pin != INVALID_GPIO){
+       if (batt_gpio_is_valid(data->pdata->dc_det_pin)) {
                INIT_WORK(&data->dcwakeup_work, rk30_adc_battery_dcdet_delaywork);
                
-               irq = gpio_to_irq(pdata->dc_det_pin);           
-               irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+               irq = gpio_to_irq(data->pdata->dc_det_pin);
+               irq_flag = gpio_get_value(data->pdata->dc_det_pin)
+                       ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
                ret = request_irq(irq, rk30_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL);
                if (ret) {
                        ret = -EINVAL;
@@ -1904,30 +2388,6 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
                enable_irq_wake(irq);  
        
        }
-#endif
-
-       // batt low irq lowerpower_work
-       if( pdata->batt_low_pin != INVALID_GPIO){
-               
-               if (gpio_get_value(pdata->batt_low_pin) ==0){
-                      mdelay(20);         
-                      if (gpio_get_value(pdata->batt_low_pin) ==0){
-                        printk("lower power\n");
-                              kernel_power_off(); 
-                      }
-               }
-               
-               INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);               
-               irq = gpio_to_irq(pdata->batt_low_pin);         
-               ret = request_irq(irq, rk30_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL);
-               if (ret) {
-                       ret = -EINVAL;
-                       printk("failed to request batt_low_irq irq\n");
-                       goto err_lowpowerirq_failed;
-               }
-               disable_irq(irq);
-
-       }
 
 #ifdef BATTERY_APK
        ret = device_create_file(&pdev->dev,&dev_attr_batparam);
@@ -1949,40 +2409,64 @@ static int rk30_adc_battery_probe(struct platform_device *pdev)
        //Power on Battery detect
        rk30_adc_battery_check(data);
 
-       data->wq = create_singlethread_workqueue("adc_battd");
+//     data->wq = create_singlethread_workqueue("adc_battd");
        INIT_DELAYED_WORK(&data->delay_work, rk30_adc_battery_timer_work);
 
-       if(1 == pdata->save_capacity ){
+       //if (1 == data->pdata->save_capacity) {
+       if (1) {
                queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS*10));
                data ->poweron_check = 1;
        }else{
                queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS));
                data ->poweron_check = 0;
        }
+       INIT_DELAYED_WORK(&data->check_work, rk_adc_battery_check_work);
+       queue_delayed_work(data ->wq, &data ->check_work, msecs_to_jiffies(TIMER_MS_COUNTS));
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin)) {
+               if (0 == gpio_get_value(data->pdata->batt_low_pin)) {
+                      mdelay(20);
+                       if (gpio_get_value(data->pdata->batt_low_pin) == 0) {
+                        printk("lower power\n");
+                              kernel_power_off(); 
+                      }
+               }
+               
+               INIT_WORK(&data->lowerpower_work, rk30_adc_battery_lowerpower_delaywork);               
+               irq = gpio_to_irq(data->pdata->batt_low_pin);
+               ret = request_irq(irq, rk30_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL);
+               if (ret) {
+                       ret = -EINVAL;
+                       printk("failed to request batt_low_irq irq\n");
+                       goto err_lowpowerirq_failed;
+               }
+               disable_irq(irq);
+
+       }
+       data->battery_nb.notifier_call = battery_notifier_call;
+       register_adc_battery_notifier(&data->battery_nb);
 
        printk(KERN_INFO "rk30_adc_battery: driver initialized\n");
        
        return 0;
 err_sysfs:     
-err_usb_failed:
        power_supply_unregister(&data ->usb);
 err_ac_failed:
        power_supply_unregister(&data ->ac);
 
+err_usb_failed:
 err_battery_failed:
        power_supply_unregister(&data ->bat);
     
 err_dcirq_failed:
-       free_irq(gpio_to_irq(pdata->dc_det_pin), data);
+       if (batt_gpio_is_valid(data->pdata->dc_det_pin))
+               free_irq(gpio_to_irq(data->pdata->dc_det_pin), data);
 #if 1
  err_lowpowerirq_failed:
-       free_irq(gpio_to_irq(pdata->batt_low_pin), data);
-#endif
-err_adc_register_failed:
-err_io_init:    
-err_data_alloc_failed:
-       kfree(data);
+       if (batt_gpio_is_valid(data->pdata->batt_low_pin))
+               free_irq(gpio_to_irq(data->pdata->batt_low_pin), data);
 
+#endif
+err_io_init:
        printk("rk30_adc_battery: error!\n");
     
        return ret;
@@ -1991,30 +2475,44 @@ err_data_alloc_failed:
 static int rk30_adc_battery_remove(struct platform_device *pdev)
 {
        struct rk30_adc_battery_data *data = platform_get_drvdata(pdev);
-       struct rk30_adc_battery_platform_data *pdata = pdev->dev.platform_data;
+       struct rk30_adc_battery_platform_data *pdata = data->pdata;
+
+       cancel_delayed_work_sync(&data->delay_work);    
+       if (batt_gpio_is_valid(pdata->dc_det_pin))
+               cancel_work_sync(&data->dcwakeup_work);
+        cancel_delayed_work_sync(&data->check_work);
 
-       cancel_delayed_work(&data->delay_work); 
+       if (batt_gpio_is_valid(pdata->batt_low_pin))
+               cancel_work_sync(&data->lowerpower_work);
 #if  defined (CONFIG_BATTERY_RK30_USB_CHARGE)
                power_supply_unregister(&data ->usb);
 #endif
        power_supply_unregister(&data ->ac);
        power_supply_unregister(&data ->bat);
-
-       free_irq(gpio_to_irq(pdata->dc_det_pin), data);
-
-       kfree(data);
+       if (batt_gpio_is_valid(pdata->dc_det_pin))
+               free_irq(gpio_to_irq(pdata->dc_det_pin), data);
        
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id rk30_adc_battery_dt_match[] = {
+       { .compatible = "rk30-adc-battery",},
+       {},
+};
+MODULE_DEVICE_TABLE(of, rk30_adc_battery_dt_match);
+#endif
+
+
 static struct platform_driver rk30_adc_battery_driver = {
        .probe          = rk30_adc_battery_probe,
        .remove         = rk30_adc_battery_remove,
        .suspend                = rk30_adc_battery_suspend,
        .resume         = rk30_adc_battery_resume,
        .driver = {
-               .name = "rk30-battery",
+               .name = "rk30-adc-battery",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(rk30_adc_battery_dt_match),
        }
 };
 
@@ -2027,11 +2525,13 @@ static void __exit rk30_adc_battery_exit(void)
 {
        platform_driver_unregister(&rk30_adc_battery_driver);
 }
-module_init(rk30_adc_battery_init);//module_init(rk30_adc_battery_init);//
-//subsys_initcall(rk30_adc_battery_init);
+//module_init(rk30_adc_battery_init);//module_init(rk30_adc_battery_init);//
+subsys_initcall(rk30_adc_battery_init);
 //fs_initcall(rk30_adc_battery_init);
 module_exit(rk30_adc_battery_exit);
 
+
+
 MODULE_DESCRIPTION("Battery detect driver for the rk30");
 MODULE_AUTHOR("luowei lw@rock-chips.com");
 MODULE_LICENSE("GPL");