From: 许盛飞 Date: Tue, 15 May 2012 07:54:00 +0000 (+0800) Subject: rk29: modify the bug of adc_charge X-Git-Tag: firefly_0821_release~9183 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=904428e6ee06bfa7b406069664531eb7858c9efe;p=firefly-linux-kernel-4.4.55.git rk29: modify the bug of adc_charge --- diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index fb797b949ef0..9ba570d708a4 100755 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -311,6 +311,12 @@ config BATTERY_RK29_AC_CHARGE help say Y to enable suspport for the AC battery charge +config BATTERY_RK29_VOL3V8 + tristate "the battery voltage is 3.8V" + depends on BATTERY_RK29_ADC + help + say Y to enable suspport for the battery voltage 3.8V + config BATTERY_RK30_ADC tristate "RK30 ADC Battery" depends on ADC_RK30 diff --git a/drivers/power/rk29_adc_battery.c b/drivers/power/rk29_adc_battery.c index f4abd3ccd160..bda652fda48a 100755 --- a/drivers/power/rk29_adc_battery.c +++ b/drivers/power/rk29_adc_battery.c @@ -1,6 +1,6 @@ /* drivers/power/rk29_adc_battery.c * - * battery detect driver for the rk2918 + * battery detect driver for the rk29 * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -33,64 +33,97 @@ #include #include #include - +#include #include -static struct wake_lock batt_wake_lock; - #if 0 #define DBG(x...) printk(x) #else #define DBG(x...) #endif -int rk29_battery_dbg_level = 0; +static int rk29_battery_dbg_level = 0; module_param_named(dbg_level, rk29_battery_dbg_level, int, 0644); /*******************ÒÔϲÎÊý¿ÉÒÔÐÞ¸Ä******************************/ -#define TIMER_MS_COUNTS 50 //¶¨Ê±Æ÷µÄ³¤¶Èms +#define TIMER_MS_COUNTS 1000 //¶¨Ê±Æ÷µÄ³¤¶Èms //ÒÔϲÎÊýÐèÒª¸ù¾Ýʵ¼Ê²âÊÔµ÷Õû -#define SLOPE_SECOND_COUNTS 15 //ͳ¼ÆµçѹбÂʵÄʱ¼ä¼ä¸ôs -#define DISCHARGE_MIN_SECOND 45 //×î¿ì·Åµçµç1%ʱ¼ä -#define CHARGE_MIN_SECOND 45 //×î¿ì³äµçµç1%ʱ¼ä -#define CHARGE_MID_SECOND 90 //ÆÕͨ³äµçµç1%ʱ¼ä -#define CHARGE_MAX_SECOND 250 //×³äµçµç1%ʱ¼ä -#define CHARGE_FULL_DELAY_TIMES 10 //³äµçÂú¼ì²â·À¶¶Ê±¼ä -#define USBCHARGE_IDENTIFY_TIMES 5 //²åÈëUSB»ìÁ÷£¬pcʶ±ð¼ì²âʱ¼ä - -#define NUM_VOLTAGE_SAMPLE ((SLOPE_SECOND_COUNTS * 1000) / TIMER_MS_COUNTS) //´æ´¢µÄ²ÉÑùµã¸öÊý -#define NUM_DISCHARGE_MIN_SAMPLE ((DISCHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS) //´æ´¢µÄ²ÉÑùµã¸öÊý -#define NUM_CHARGE_MIN_SAMPLE ((CHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS) //´æ´¢µÄ²ÉÑùµã¸öÊý -#define NUM_CHARGE_MID_SAMPLE ((CHARGE_MID_SECOND * 1000) / TIMER_MS_COUNTS) //´æ´¢µÄ²ÉÑùµã¸öÊý -#define NUM_CHARGE_MAX_SAMPLE ((CHARGE_MAX_SECOND * 1000) / TIMER_MS_COUNTS) //´æ´¢µÄ²ÉÑùµã¸öÊý -#define NUM_CHARGE_FULL_DELAY_TIMES ((CHARGE_FULL_DELAY_TIMES * 1000) / TIMER_MS_COUNTS) //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È -#define NUM_USBCHARGE_IDENTIFY_TIMES ((USBCHARGE_IDENTIFY_TIMES * 1000) / TIMER_MS_COUNTS) //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È - -#define BAT_2V5_VALUE 2500 -#define BATT_MAX_VOL_VALUE 8284 // 4180 //ÂúµçʱµÄµç³Øµçѹ FOR A7 -#define BATT_ZERO_VOL_VALUE 6800 // 3500 //¹Ø»úʱµÄµç³Øµçѹ -#define BATT_NOMAL_VOL_VALUE 7600 // 3800 +#define SLOPE_SECOND_COUNTS 15 //ͳ¼ÆµçѹбÂʵÄʱ¼ä¼ä¸ôs +#define DISCHARGE_MIN_SECOND 45 //×î¿ì·Åµçµç1%ʱ¼ä +#define CHARGE_MIN_SECOND 45 //×î¿ì³äµçµç1%ʱ¼ä +#define CHARGE_MID_SECOND 90 //ÆÕͨ³äµçµç1%ʱ¼ä +#define CHARGE_MAX_SECOND 250 //×³äµçµç1%ʱ¼ä +#define CHARGE_FULL_DELAY_TIMES 10 //³äµçÂú¼ì²â·À¶¶Ê±¼ä +#define USBCHARGE_IDENTIFY_TIMES 5 //²åÈëUSB»ìÁ÷£¬pcʶ±ð¼ì²âʱ¼ä + +#define NUM_VOLTAGE_SAMPLE ((SLOPE_SECOND_COUNTS * 1000) / TIMER_MS_COUNTS) +#define NUM_DISCHARGE_MIN_SAMPLE ((DISCHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS) +#define NUM_CHARGE_MIN_SAMPLE ((CHARGE_MIN_SECOND * 1000) / TIMER_MS_COUNTS) +#define NUM_CHARGE_MID_SAMPLE ((CHARGE_MID_SECOND * 1000) / TIMER_MS_COUNTS) +#define NUM_CHARGE_MAX_SAMPLE ((CHARGE_MAX_SECOND * 1000) / TIMER_MS_COUNTS) +#define NUM_CHARGE_FULL_DELAY_TIMES ((CHARGE_FULL_DELAY_TIMES * 1000) / TIMER_MS_COUNTS) //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È +#define NUM_USBCHARGE_IDENTIFY_TIMES ((USBCHARGE_IDENTIFY_TIMES * 1000) / TIMER_MS_COUNTS) //³äµçÂú״̬³ÖÐøʱ¼ä³¤¶È + +#define BAT_2V5_VALUE 2500 //¶¨ÒåADC²ÉÑù·Öѹµç×裬ÒÔʵ¼ÊֵΪ׼£¬µ¥Î»K -#define BAT_PULL_UP_R 300 ////200 +#define BAT_PULL_UP_R 300 ////200 -#define BAT_PULL_DOWN_R 100// 200 -#define BAT_ADC_TABLE_LEN 11 -#define adc_to_voltage(adc_val) ((adc_val * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R)) +#define BAT_PULL_DOWN_R 100// 200 +#define adc_to_voltage(adc_val) ((adc_val * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R)) +#define BATT_NUM 11 +#define BATT_FILENAME "/data/bat_last_capacity.dat" + +static struct wake_lock batt_wake_lock; -static int adc_raw_table_bat[BAT_ADC_TABLE_LEN] = -{ -// 3490, 3597, 3628, 3641, 3660, 3697, 3747, 3809, 3879, 3945, 4165 - 6800,7242,7332,7404,7470,7520,7610,7744,7848,8016,8284 +struct batt_vol_cal{ +// u32 disp_cal; + u32 dis_charge_vol; + u32 charge_vol; }; -static int adc_raw_table_ac[BAT_ADC_TABLE_LEN] = -{ - // 3600, 3760, 3800, 3827, 3845, 3885, 3950, 4007, 4078, 4140, 4200 - 7630, 7754, 7852, 7908, 7956, 8024, 8112, 8220, 8306, 8318, 8328 +#ifdef CONFIG_BATTERY_RK29_VOL3V8 + +#define BATT_MAX_VOL_VALUE 4200 //ÂúµçʱµÄµç³Øµçѹ +#define BATT_ZERO_VOL_VALUE 3400 //¹Ø»úʱµÄµç³Øµçѹ +#define BATT_NOMAL_VOL_VALUE 3800 +static struct batt_vol_cal batt_table[BATT_NUM] = { + {3400,3520}, + {3610,3715}, + {3672,3790}, + {3705,3825}, + {3734,3841}, + {3764,3864}, + {3808,3930}, + {3845,3997}, + {3964,4047}, + {4034,4144}, + {4120,4200}, +}; +/*******************************************************************************/ + +#else + +#define BATT_MAX_VOL_VALUE 8200 //ÂúµçʱµÄµç³Øµçѹ +#define BATT_ZERO_VOL_VALUE 6800 //¹Ø»úʱµÄµç³Øµçѹ +#define BATT_NOMAL_VOL_VALUE 7600 +static struct batt_vol_cal batt_table[BATT_NUM] = { + {6800,7400}, + {7220,7720}, + {7344,7844}, + {7410,7910},//500 + {7468,7975}, + {7528,8044}, + {7618,8075}, + {7744,8100}, //400 + {7900,8180}, + {8110,8260}, + {8200 ,8310},//110 }; +#endif +/********************************************************************************/ extern int dwc_vbus_status(void); extern int get_msc_connect_flag(void); @@ -98,10 +131,12 @@ extern int get_msc_connect_flag(void); struct rk29_adc_battery_data { int irq; - struct timer_list timer; - struct work_struct timer_work; + //struct timer_list timer; + struct workqueue_struct *wq; + struct delayed_work delay_work; struct work_struct dcwakeup_work; - struct work_struct resume_work; + struct work_struct lowerpower_work; + bool resume; struct rk29_adc_battery_platform_data *pdata; @@ -118,6 +153,15 @@ struct rk29_adc_battery_data { int bat_voltage; int bat_capacity; int bat_change; + + int old_charge_level; + int *pSamples; + int gBatCapacityDisChargeCnt; + int gBatCapacityChargeCnt; + int capacitytmp; + int poweron_check; + int suspend_capacity; + }; static struct rk29_adc_battery_data *gBatteryData; @@ -140,483 +184,433 @@ typedef enum { } charger_type_t; -#define BATT_FILENAME "/data/bat_last_capacity.dat" -#include -static void rk29_adc_battery_capacity_samples(struct rk29_adc_battery_data *bat); -static int rk29_adc_battery_voltage_to_capacity(struct rk29_adc_battery_data *bat, int BatVoltage); -static struct power_supply rk29_battery_supply; + static int rk29_adc_battery_load_capacity(void) { - char value[4]; + char value[4]; int* p = (int *)value; - long fd = sys_open(BATT_FILENAME,O_RDONLY,0); - - if(fd < 0) - { + long fd = sys_open(BATT_FILENAME,O_RDONLY,0); + + if(fd < 0){ printk("rk29_adc_battery_load_capacity: open file /data/bat_last_capacity.dat failed\n"); return -1; } - + sys_read(fd,(char __user *)value,4); - - sys_close(fd); - + sys_close(fd); + return (*p); } static void rk29_adc_battery_put_capacity(int loadcapacity) { - char value[4]; + char value[4]; int* p = (int *)value; - long fd = sys_open(BATT_FILENAME,O_CREAT | O_RDWR,0); - - if(fd < 0) - { + long fd = sys_open(BATT_FILENAME,O_CREAT | O_RDWR,0); + + if(fd < 0){ printk("rk29_adc_battery_put_capacity: open file /data/bat_last_capacity.dat failed\n"); return; } - *p = loadcapacity; - sys_write(fd, (const char __user *)value, 4); - sys_close(fd); + *p = loadcapacity; + sys_write(fd, (const char __user *)value, 4); + + sys_close(fd); } static void rk29_adc_battery_charge_enable(struct rk29_adc_battery_data *bat) { - struct rk29_adc_battery_platform_data *pdata = bat->pdata; - - if (pdata->charge_set_pin != INVALID_GPIO) - { - gpio_direction_output(pdata->charge_set_pin, pdata->charge_set_level); - } + struct rk29_adc_battery_platform_data *pdata = bat->pdata; + + if (pdata->charge_set_pin != INVALID_GPIO){ + gpio_direction_output(pdata->charge_set_pin, pdata->charge_set_level); + } } static void rk29_adc_battery_charge_disable(struct rk29_adc_battery_data *bat) { - struct rk29_adc_battery_platform_data *pdata = bat->pdata; - - if (pdata->charge_set_pin != INVALID_GPIO) - { - gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level); - } + struct rk29_adc_battery_platform_data *pdata = bat->pdata; + + if (pdata->charge_set_pin != INVALID_GPIO){ + gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level); + } } -extern int suspend_flag; +//extern int suspend_flag; static int rk29_adc_battery_get_charge_level(struct rk29_adc_battery_data *bat) { - int charge_on = 0; - struct rk29_adc_battery_platform_data *pdata = bat->pdata; - -#if defined(CONFIG_BATTERY_RK29_AC_CHARGE) - if (pdata->dc_det_pin != INVALID_GPIO) - { - if (gpio_get_value (pdata->dc_det_pin) == pdata->dc_det_level) - { - charge_on = 1; - } - } -#endif - -#if defined(CONFIG_BATTERY_RK29_USB_CHARGE) - if (charge_on == 0) - { - if (suspend_flag) return; - - if (1 == dwc_vbus_status()) //¼ì²âµ½USB²åÈ룬µ«ÊÇÎÞ·¨Ê¶±ðÊÇ·ñÊdzäµçÆ÷ - { //ͨ¹ýÑÓʱ¼ì²âPCʶ±ð±êÖ¾£¬Èç¹û³¬Ê±¼ì²â²»µ½£¬ËµÃ÷Êdzäµç - if (0 == get_msc_connect_flag()) - { //²åÈë³äµçÆ÷ʱ¼ä´óÓÚÒ»¶¨Ê±¼äÖ®ºó£¬¿ªÊ¼½øÈë³äµç״̬ - if (++gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES) - { - gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1; - charge_on = 1; - } - } //·ñÔò£¬²»½øÈë³äµçģʽ - } - else - { - gBatUsbChargeCnt = 0; - if (2 == dwc_vbus_status()) - { - charge_on = 1; - } - } - } + int charge_on = 0; +// struct rk29_adc_battery_platform_data *pdata = bat->pdata; + +#if defined (CONFIG_BATTERY_RK29_AC_CHARGE) + if (pdata->dc_det_pin != INVALID_GPIO){ + if (gpio_get_value (pdata->dc_det_pin) == pdata->dc_det_level){ + charge_on = 1; + } + } #endif - return charge_on; +#if defined (CONFIG_BATTERY_RK29_USB_CHARGE) + if (charge_on == 0){ + if (suspend_flag) + return; + if (1 == dwc_vbus_status()) { //¼ì²âµ½USB²åÈ룬µ«ÊÇÎÞ·¨Ê¶±ðÊÇ·ñÊdzäµçÆ÷ + //ͨ¹ýÑÓʱ¼ì²âPCʶ±ð±êÖ¾£¬Èç¹û³¬Ê±¼ì²â²»µ½£¬ËµÃ÷Êdzäµç + if (0 == get_msc_connect_flag()){ //²åÈë³äµçÆ÷ʱ¼ä´óÓÚÒ»¶¨Ê±¼äÖ®ºó£¬¿ªÊ¼½øÈë³äµç״̬ + if (++gBatUsbChargeCnt >= NUM_USBCHARGE_IDENTIFY_TIMES){ + gBatUsbChargeCnt = NUM_USBCHARGE_IDENTIFY_TIMES + 1; + charge_on = 1; + } + } //·ñÔò£¬²»½øÈë³äµçģʽ + } + else{ + gBatUsbChargeCnt = 0; + if (2 == dwc_vbus_status()) { + charge_on = 1; + } + } + } +#endif + return charge_on; } -int old_charge_level; +//int old_charge_level; static int rk29_adc_battery_status_samples(struct rk29_adc_battery_data *bat) { - int charge_level; - struct rk29_adc_battery_platform_data *pdata = bat->pdata; - - charge_level = rk29_adc_battery_get_charge_level(bat); - - //¼ì²â³äµç״̬±ä»¯Çé¿ö - if (charge_level != old_charge_level) - { - old_charge_level = charge_level; - bat->bat_change = 1; - if(charge_level) - { - rk29_adc_battery_charge_enable(bat); - } - else - { - rk29_adc_battery_charge_disable(bat); - } - bat->bat_status_cnt = 0; //״̬±ä»¯¿ªÊ¼¼ÆÊý - } - - //»ñÈ¡Îȶ¨µÄ³äµç״̬ - if(charge_level == 0) - { - //δ³äµç - bat->full_times = 0; - bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + int charge_level; + + struct rk29_adc_battery_platform_data *pdata = bat->pdata; + + charge_level = rk29_adc_battery_get_charge_level(bat); + + //¼ì²â³äµç״̬±ä»¯Çé¿ö + if (charge_level != bat->old_charge_level){ + bat->old_charge_level = charge_level; + bat->bat_change = 1; + + if(charge_level) { + rk29_adc_battery_charge_enable(bat); + } + else{ + rk29_adc_battery_charge_disable(bat); + } + bat->bat_status_cnt = 0; //״̬±ä»¯¿ªÊ¼¼ÆÊý } - else - { - //³äµç - if (pdata->charge_ok_pin == INVALID_GPIO) - { - //ûÓÐcharge_ok_pin£¬¼ì²âÈÝÁ¿ - if (bat->bat_capacity == 100) - { - if (bat->bat_status != POWER_SUPPLY_STATUS_FULL) - { - bat->bat_status = POWER_SUPPLY_STATUS_FULL; - bat->bat_change = 1; - } - } - else - { - bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; - } - } - else - { - //Óгäµç¼ì²â½Ì - if (gpio_get_value(pdata->charge_ok_pin) != pdata->charge_ok_level) - { - //ûÓмì²âµ½³äµçÂúµçƽ±êÖ¾ - bat->full_times = 0; - bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; - } - else - { - //¼ì²âµ½³äµçÂúµçƽ±êÖ¾ - bat->full_times++; - if (bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) - { - bat->full_times = NUM_CHARGE_FULL_DELAY_TIMES + 1; - } - - if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 99)) - { - if (bat->bat_status != POWER_SUPPLY_STATUS_FULL) - { - bat->bat_status = POWER_SUPPLY_STATUS_FULL; - bat->bat_capacity = 100; - bat->bat_change = 1; - } - } - else - { - bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; - } - } - } - } - + + if(charge_level == 0){ + //discharge + bat->full_times = 0; + bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + } + else{ + //CHARGE + if (pdata->charge_ok_pin == INVALID_GPIO){ //no charge_ok_pin + + if (bat->bat_capacity == 100){ + if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){ + bat->bat_status = POWER_SUPPLY_STATUS_FULL; + bat->bat_change = 1; + } + } + else{ + bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; + } + } + else{ // pin of charge_ok_pin + if (gpio_get_value(pdata->charge_ok_pin) != pdata->charge_ok_level){ + + bat->full_times = 0; + bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; + } + else{ + //¼ì²âµ½³äµçÂúµçƽ±êÖ¾ + bat->full_times++; + + if (bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) { + bat->full_times = NUM_CHARGE_FULL_DELAY_TIMES + 1; + } + + if ((bat->full_times >= NUM_CHARGE_FULL_DELAY_TIMES) && (bat->bat_capacity >= 99)){ + if (bat->bat_status != POWER_SUPPLY_STATUS_FULL){ + bat->bat_status = POWER_SUPPLY_STATUS_FULL; + bat->bat_capacity = 100; + bat->bat_change = 1; + } + } + else{ + bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; + } + } + } + } + return charge_level; } -int AdcTestvalue = 0; -static int gFlagLoop = 0; static int *pSamples; static void rk29_adc_battery_voltage_samples(struct rk29_adc_battery_data *bat) { int value; int i,*pStart = bat->adc_samples, num = 0; - + int level = rk29_adc_battery_get_charge_level(bat); + + value = bat->adc_val; - AdcTestvalue = value; - adc_async_read(bat->client); - + adc_async_read(bat->client); + *pSamples++ = adc_to_voltage(value); - + bat->bat_status_cnt++; if (bat->bat_status_cnt > NUM_VOLTAGE_SAMPLE) bat->bat_status_cnt = NUM_VOLTAGE_SAMPLE + 1; - + num = pSamples - pStart; - if (num >= NUM_VOLTAGE_SAMPLE) - { - pSamples = pStart; - gFlagLoop = 1; - } - if (gFlagLoop == 1) - { - num = NUM_VOLTAGE_SAMPLE; + + if (num >= NUM_VOLTAGE_SAMPLE){ + pSamples = pStart; + num = NUM_VOLTAGE_SAMPLE; + } + value = 0; - for (i = 0; i < num; i++) - { - value += bat->adc_samples[i]; + for (i = 0; i < num; i++){ + value += bat->adc_samples[i]; } bat->bat_voltage = value / num; - + /*Ïû³ýë´Ìµçѹ*/ - if(bat->bat_voltage >= BATT_MAX_VOL_VALUE + 10) - bat->bat_voltage = BATT_MAX_VOL_VALUE + 10; - else if(bat->bat_voltage <= BATT_ZERO_VOL_VALUE - 10) - bat->bat_voltage = BATT_ZERO_VOL_VALUE - 10; -} + if(1 == level){ + if(bat->bat_voltage >= batt_table[BATT_NUM-1].charge_vol+ 10) + bat->bat_voltage = batt_table[BATT_NUM-1].charge_vol + 10; + else if(bat->bat_voltage <= batt_table[0].charge_vol - 10) + bat->bat_voltage = batt_table[0].charge_vol - 10; + } + else{ + if(bat->bat_voltage >= batt_table[BATT_NUM-1].dis_charge_vol+ 10) + bat->bat_voltage = batt_table[BATT_NUM-1].dis_charge_vol + 10; + else if(bat->bat_voltage <= batt_table[0].dis_charge_vol - 10) + bat->bat_voltage = batt_table[0].dis_charge_vol - 10; -int capacitytmp = 0; + } +} static int rk29_adc_battery_voltage_to_capacity(struct rk29_adc_battery_data *bat, int BatVoltage) { - int i = 0; + int i = 0; int capacity = 0; - int *p = adc_raw_table_bat; - - if (rk29_adc_battery_get_charge_level(bat)) - { - p = adc_raw_table_ac; - } - - if(BatVoltage >= p[BAT_ADC_TABLE_LEN - 1]) - { - //µ±µçѹ³¬¹ý×î´óÖµ - capacity = 100; - } - else if(BatVoltage <= p[0]) - { - //µ±µçѹµÍÓÚ×îСֵ - capacity = 0; + + struct batt_vol_cal *p; + p = batt_table; + + if (rk29_adc_battery_get_charge_level(bat)){ //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 = 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 = i * 10 + ((BatVoltage - p[i].dis_charge_vol) * 10) / (p[i+1].dis_charge_vol- p[i].dis_charge_vol); ; + break; + } + } + } + + } + + } - else - { - //¼ÆËãÈÝÁ¿ - for(i = 0; i < BAT_ADC_TABLE_LEN - 1; i++) - { - - if((p[i] <= BatVoltage) && (BatVoltage < p[i+1])) - { - capacity = i * 10 + ((BatVoltage - p[i]) * 10) / (p[i+1] - p[i]); - break; - } - } - } return capacity; } -static int gBatCapacityDisChargeCnt = 0; -static int gBatCapacityChargeCnt = 0; -//static int rk29_adc_battery_get_capacity_ext(int BatVoltage) static void rk29_adc_battery_capacity_samples(struct rk29_adc_battery_data *bat) { int capacity = 0; struct rk29_adc_battery_platform_data *pdata = bat->pdata; - - //³ä·Åµç״̬±ä»¯ºó£¬BufferÌîÂú֮ǰ£¬²»¸üР- if (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE) - { - gBatCapacityDisChargeCnt = 0; - gBatCapacityChargeCnt = 0; - return; + + //³ä·Åµç״̬±ä»¯ºó£¬BufferÌîÂú֮ǰ£¬²»¸üР+ if (bat->bat_status_cnt < NUM_VOLTAGE_SAMPLE) { + bat->gBatCapacityDisChargeCnt = 0; + bat->gBatCapacityChargeCnt = 0; + return; } - capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); + capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); - if (rk29_adc_battery_get_charge_level(bat)) - { - if (capacity > bat->bat_capacity) - { - //ʵ¼Ê²ÉÑùµ½µÄµçѹ±ÈÏÔʾµÄµçѹ´ó£¬Öð¼¶ÉÏÉý - if (++gBatCapacityDisChargeCnt >= NUM_CHARGE_MIN_SAMPLE) - { - gBatCapacityDisChargeCnt = 0; - if (bat->bat_capacity < 99) - { - bat->bat_capacity++; - bat->bat_change = 1; - } - } - gBatCapacityChargeCnt = 0; - } - else - { - gBatCapacityDisChargeCnt = 0; - gBatCapacityChargeCnt++; + if (rk29_adc_battery_get_charge_level(bat)){ + if (capacity > bat->bat_capacity){ + //ʵ¼Ê²ÉÑùµ½µÄÈÝÁ¿±ÈÏÔʾµÄÈÝÁ¿´ó£¬Öð¼¶ÉÏÉý + if (++(bat->gBatCapacityDisChargeCnt) >= NUM_CHARGE_MIN_SAMPLE){ + bat->gBatCapacityDisChargeCnt = 0; + if (bat->bat_capacity < 99){ + bat->bat_capacity++; + bat->bat_change = 1; + } + } + bat->gBatCapacityChargeCnt = 0; + } + else{ // ʵ¼ÊµÄÈÝÁ¿±È²ÉÑù±È ÏÔʾµÄÈÝÁ¿Ð¡ + bat->gBatCapacityDisChargeCnt = 0; + (bat->gBatCapacityChargeCnt)++; - if (pdata->charge_ok_pin != INVALID_GPIO) - { - if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level) - { - //¼ì²âµ½µç³Ø³äÂú±êÖ¾£¬Í¬Ê±³¤Ê±¼äÄÚ³äµçµçѹÎޱ仯£¬¿ªÊ¼Æô¶¯¼Æʱ³äµç£¬¿ìËÙÉÏÉýÈÝÁ¿ - if (gBatCapacityChargeCnt >= NUM_CHARGE_MIN_SAMPLE) - { - gBatCapacityChargeCnt = 0; - if (bat->bat_capacity < 99) - { - bat->bat_capacity++; - bat->bat_change = 1; - } - } - } - else - { - if (capacity > capacitytmp) - { - //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì - gBatCapacityChargeCnt = 0; - } - if (/*(bat->bat_capacity >= 80) && */(gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE)) - { - gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE); - if (bat->bat_capacity < 99) - { - bat->bat_capacity++; - bat->bat_change = 1; - } - } - } - } - else - { - //ûÓгäµçÂú¼ì²â½Å£¬³¤Ê±¼äÄÚµçѹÎޱ仯£¬¶¨Ê±Æ÷Ä£Äâ³äµç - if (capacity > capacitytmp) - { - //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì - gBatCapacityChargeCnt = 0; - } - if (gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE) - { - gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE); - if (bat->bat_capacity < 100) - { - bat->bat_capacity++; - bat->bat_change = 1; - } - } - } - } - } - else - { - //·Åµçʱ,Ö»ÔÊÐíµçѹϽµ - if (capacity < bat->bat_capacity) - { - if (++gBatCapacityDisChargeCnt >= NUM_DISCHARGE_MIN_SAMPLE) - { - gBatCapacityDisChargeCnt = 0; - if (bat->bat_capacity > 0) - { - bat->bat_capacity-- ; - bat->bat_change = 1; - } - } - } - else - { - gBatCapacityDisChargeCnt = 0; - } - - gBatCapacityChargeCnt = 0; - } - capacitytmp = capacity; + if (pdata->charge_ok_pin != INVALID_GPIO){ + if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){ + //¼ì²âµ½µç³Ø³äÂú±êÖ¾£¬Í¬Ê±³¤Ê±¼äÄÚ³äµçµçѹÎޱ仯£¬¿ªÊ¼Æô¶¯¼Æʱ³äµç£¬¿ìËÙÉÏÉýÈÝÁ¿ + if (bat->gBatCapacityChargeCnt >= NUM_CHARGE_MIN_SAMPLE){ + bat->gBatCapacityChargeCnt = 0; + if (bat->bat_capacity < 99){ + bat->bat_capacity++; + bat->bat_change = 1; + } + } + } + else{ +#if 0 + if (capacity > capacitytmp){ + //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì + gBatCapacityChargeCnt = 0; + } + else if (/*bat->bat_capacity >= 85) &&*/ (gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE)){ + gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE); + + if (bat->bat_capacity < 99){ + bat->bat_capacity++; + bat->bat_change = 1; + } + } + } +#else // ·ÀÖ¹µç³ØÀÏ»¯ºó³öÏֳ岻ÂúµÄÇé¿ö£¬ + if (capacity > bat->capacitytmp){ + //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì + bat->gBatCapacityChargeCnt = 0; + } + else{ + + if ((bat->bat_capacity >= 85) &&((bat->gBatCapacityChargeCnt) > NUM_CHARGE_MAX_SAMPLE)){ + bat->gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE); + + if (bat->bat_capacity < 99){ + bat->bat_capacity++; + bat->bat_change = 1; + } + } + } + } +#endif + + } + else{ + //ûÓгäµçÂú¼ì²â½Å£¬³¤Ê±¼äÄÚµçѹÎޱ仯£¬¶¨Ê±Æ÷Ä£Äâ³äµç + if (capacity > bat->capacitytmp){ + //¹ý³ÌÖÐÈç¹ûµçѹÓÐÔö³¤£¬¶¨Ê±Æ÷¸´Î»£¬·ÀÖ¹¶¨Ê±Æ÷Ä£Äâ³äµç±Èʵ¼Ê³äµç¿ì + bat->gBatCapacityChargeCnt = 0; + } + else{ + + if ((bat->bat_capacity >= 85) &&(bat->gBatCapacityChargeCnt > NUM_CHARGE_MAX_SAMPLE)){ + bat->gBatCapacityChargeCnt = (NUM_CHARGE_MAX_SAMPLE - NUM_CHARGE_MID_SAMPLE); + + if (bat->bat_capacity < 99){ + bat->bat_capacity++; + bat->bat_change = 1; + } + } + } + + + } + } + } + else{ + //·Åµçʱ,Ö»ÔÊÐíµçѹϽµ + if (capacity < bat->bat_capacity){ + if (++(bat->gBatCapacityDisChargeCnt) >= NUM_DISCHARGE_MIN_SAMPLE){ + bat->gBatCapacityDisChargeCnt = 0; + if (bat->bat_capacity > 0){ + bat->bat_capacity-- ; + bat->bat_change = 1; + } + } + } + else{ + bat->gBatCapacityDisChargeCnt = 0; + } + bat->gBatCapacityChargeCnt = 0; + } + bat->capacitytmp = capacity; } -static int poweron_check = 0; +//static int poweron_check = 0; static void rk29_adc_battery_poweron_capacity_check(void) { - int new_capacity, old_capacity; - - new_capacity = gBatteryData->bat_capacity; - old_capacity = rk29_adc_battery_load_capacity(); - if ((old_capacity <= 0) || (old_capacity >= 100)) - { - old_capacity = new_capacity; - } - - if (gBatteryData->bat_status == POWER_SUPPLY_STATUS_FULL) - { - if (new_capacity > 80) - { - gBatteryData->bat_capacity = 100; - } - } - else if (gBatteryData->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING) - { - //chargeing state - //ÎÊÌ⣺ - //1£©³¤Ê±¼ä¹Ø»ú·ÅÖú󣬿ª»úºó¶ÁÈ¡µÄÈÝÁ¿Ô¶Ô¶´óÓÚʵ¼ÊÈÝÁ¿Ôõô°ì£¿ - //2£©Èç¹û²»ÕâÑù×ö£¬¶Ìʱ¼ä¹Ø»úÔÙ¿ª»ú£¬Ç°ºóÈÝÁ¿²»Ò»ÖÂÓÖ¸ÃÔõô°ì£¿ - //3£©Ò»ÏÂÄÇÖÖ·½Ê½ºÏÊÊ£¿ - //gBatteryData->bat_capacity = new_capacity; - gBatteryData->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity; - } - else - { - gBatteryData->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity; - } - - - printk("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity); - - gBatteryData->bat_change = 1; -} -unsigned long AdcTestCnt = 0; -static void rk29_adc_battery_timer_work(struct work_struct *work) -{ - rk29_adc_battery_status_samples(gBatteryData); - - if (poweron_check) - { - poweron_check = 0; - rk29_adc_battery_poweron_capacity_check(); + int new_capacity, old_capacity; + + new_capacity = gBatteryData->bat_capacity; + old_capacity = rk29_adc_battery_load_capacity(); + if ((old_capacity <= 0) || (old_capacity >= 100)){ + old_capacity = new_capacity; + } + + if (gBatteryData->bat_status == POWER_SUPPLY_STATUS_FULL){ + if (new_capacity > 80){ + gBatteryData->bat_capacity = 100; + } } - - rk29_adc_battery_voltage_samples(gBatteryData); - rk29_adc_battery_capacity_samples(gBatteryData); - - /*update battery parameter after adc and capacity has been changed*/ - if(gBatteryData->bat_change) - { - gBatteryData->bat_change = 0; - rk29_adc_battery_put_capacity(gBatteryData->bat_capacity); - power_supply_changed(&rk29_battery_supply); + else if (gBatteryData->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){ + //chargeing state + //ÎÊÌ⣺ +// //1£©³¤Ê±¼ä¹Ø»ú·ÅÖú󣬿ª»úºó¶ÁÈ¡µÄÈÝÁ¿Ô¶Ô¶´óÓÚʵ¼ÊÈÝÁ¿Ôõô°ì£¿ +// //2£©Èç¹û²»ÕâÑù×ö£¬¶Ìʱ¼ä¹Ø»úÔÙ¿ª»ú£¬Ç°ºóÈÝÁ¿²»Ò»ÖÂÓÖ¸ÃÔõô°ì£¿ +// //3£©Ò»ÏÂÄÇÖÖ·½Ê½ºÏÊÊ£¿ + //gBatteryData->bat_capacity = new_capacity; + gBatteryData->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity; + }else{ + + if(new_capacity > old_capacity + 50 ) + gBatteryData->bat_capacity = new_capacity; + else + gBatteryData->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity; //avoid the value of capacity increase } - if (rk29_battery_dbg_level) - { - if (++AdcTestCnt >= 20) - { - AdcTestCnt = 0; - printk("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", - gBatteryData->bat_status, AdcTestvalue, adc_to_voltage(AdcTestvalue), - gBatteryData->bat_voltage, gBatteryData->bat_capacity, capacitytmp, gBatCapacityDisChargeCnt, gBatCapacityChargeCnt); - } - } - + //printk("capacity = %d, new_capacity = %d, old_capacity = %d\n",gBatteryData->bat_capacity, new_capacity, old_capacity); + gBatteryData->bat_change = 1; } - +#if 0 static void rk29_adc_battery_scan_timer(unsigned long data) { - gBatteryData->timer.expires = jiffies + msecs_to_jiffies(TIMER_MS_COUNTS); + gBatteryData->timer.expires = jiffies + msecs_to_jiffies(TIMER_MS_COUNTS); add_timer(&gBatteryData->timer); - + schedule_work(&gBatteryData->timer_work); } +#endif #if defined(CONFIG_BATTERY_RK29_USB_CHARGE) static int rk29_adc_battery_get_usb_property(struct power_supply *psy, @@ -653,7 +647,7 @@ static struct power_supply rk29_usb_supply = .get_property = rk29_adc_battery_get_usb_property, - .properties = rk29_adc_battery_usb_props, + .properties = rk29_adc_battery_usb_props, .num_properties = ARRAY_SIZE(rk29_adc_battery_usb_props), }; #endif @@ -661,8 +655,8 @@ static struct power_supply rk29_usb_supply = #if defined(CONFIG_BATTERY_RK29_AC_CHARGE) static irqreturn_t rk29_adc_battery_dc_wakeup(int irq, void *dev_id) { - schedule_work(&gBatteryData->dcwakeup_work); - return IRQ_HANDLED; + queue_work(gBatteryData->wq, &gBatteryData->dcwakeup_work); + return IRQ_HANDLED; } @@ -677,7 +671,7 @@ static int rk29_adc_battery_get_ac_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: if (psy->type == POWER_SUPPLY_TYPE_MAINS) { - printk("POWER_SUPPLY_TYPE_MAINS\n"); + // printk("POWER_SUPPLY_TYPE_MAINS\n"); if (rk29_adc_battery_get_charge_level(gBatteryData)) { val->intval = 1; @@ -710,30 +704,34 @@ static struct power_supply rk29_ac_supply = .get_property = rk29_adc_battery_get_ac_property, - .properties = rk29_adc_battery_ac_props, + .properties = rk29_adc_battery_ac_props, .num_properties = ARRAY_SIZE(rk29_adc_battery_ac_props), }; static void rk29_adc_battery_dcdet_delaywork(struct work_struct *work) { - int ret; - struct rk29_adc_battery_platform_data *pdata = gBatteryData->pdata; - int irq = gpio_to_irq(pdata->dc_det_pin); - int irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; - - rk28_send_wakeup_key(); - - free_irq(irq, NULL); - ret = request_irq(irq, rk29_adc_battery_dc_wakeup, irq_flag, "rk29_adc_battery", NULL); + int ret; + struct rk29_adc_battery_platform_data *pdata; + int irq; + int irq_flag; + //printk("DC_WAKEUP\n"); + pdata = gBatteryData->pdata; + irq = gpio_to_irq(pdata->dc_det_pin); + irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; + + rk28_send_wakeup_key(); // wake up the system + + free_irq(irq, NULL); + ret = request_irq(irq, rk29_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL);// reinitialize the DC irq if (ret) { free_irq(irq, NULL); } - + power_supply_changed(&rk29_ac_supply); - gBatteryData->bat_status_cnt = 0; //״̬±ä»¯¿ªÊ¼¼ÆÊý + gBatteryData->bat_status_cnt = 0; //the state of battery is change - wake_lock_timeout(&batt_wake_lock, 30 * HZ); + wake_lock_timeout(&batt_wake_lock, 29 * HZ); } @@ -772,41 +770,41 @@ static int rk29_adc_battery_get_property(struct power_supply *psy, int ret = 0; switch (psp) { - case POWER_SUPPLY_PROP_STATUS: - val->intval = rk29_adc_battery_get_status(gBatteryData); - DBG("gBatStatus=%d\n",val->intval); - break; - case POWER_SUPPLY_PROP_HEALTH: - val->intval = rk29_adc_battery_get_health(gBatteryData); - DBG("gBatHealth=%d\n",val->intval); - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = rk29_adc_battery_get_present(gBatteryData); - DBG("gBatPresent=%d\n",val->intval); - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val ->intval = rk29_adc_battery_get_voltage(gBatteryData); - DBG("gBatVoltage=%d\n",val->intval); - break; -// case POWER_SUPPLY_PROP_CURRENT_NOW: -// val->intval = 1100; -// break; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = rk29_adc_battery_get_capacity(gBatteryData); - DBG("gBatCapacity=%d%%\n",val->intval); - break; - case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: - val->intval = BATT_MAX_VOL_VALUE; - break; - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - val->intval = BATT_ZERO_VOL_VALUE; - break; - default: - ret = -EINVAL; - break; + case POWER_SUPPLY_PROP_STATUS: + val->intval = rk29_adc_battery_get_status(gBatteryData); + DBG("gBatStatus=%d\n",val->intval); + break; + case POWER_SUPPLY_PROP_HEALTH: + val->intval = rk29_adc_battery_get_health(gBatteryData); + DBG("gBatHealth=%d\n",val->intval); + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = rk29_adc_battery_get_present(gBatteryData); + DBG("gBatPresent=%d\n",val->intval); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val ->intval = rk29_adc_battery_get_voltage(gBatteryData); + DBG("gBatVoltage=%d\n",val->intval); + break; + // case POWER_SUPPLY_PROP_CURRENT_NOW: + // val->intval = 1100; + // break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = rk29_adc_battery_get_capacity(gBatteryData); + DBG("gBatCapacity=%d%%\n",val->intval); + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = BATT_MAX_VOL_VALUE; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = BATT_ZERO_VOL_VALUE; + break; + default: + ret = -EINVAL; + break; } return ret; @@ -831,73 +829,62 @@ static struct power_supply rk29_battery_supply = .type = POWER_SUPPLY_TYPE_BATTERY, .get_property = rk29_adc_battery_get_property, - - .properties = rk29_adc_battery_props, + + .properties = rk29_adc_battery_props, .num_properties = ARRAY_SIZE(rk29_adc_battery_props), }; - #ifdef CONFIG_PM -int suspend_capacity = 0; -static void rk29_adc_battery_resume_check(struct work_struct *work) +//int suspend_capacity = 0; +static void rk29_adc_battery_resume_check(void) { - int i; - int level,oldlevel; - int new_capacity, old_capacity; - struct rk29_adc_battery_data *bat = gBatteryData; - - old_charge_level = -1; - pSamples = bat->adc_samples; - - adc_sync_read(bat->client); //start adc sample - level = oldlevel = rk29_adc_battery_status_samples(bat);//init charge status - - for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) //0.3 s - { - mdelay(1); - rk29_adc_battery_voltage_samples(bat); //get voltage - level = rk29_adc_battery_status_samples(bat); //check charge status - if (oldlevel != level) - { - oldlevel = level; //if charge status changed, reset sample - i = 0; - } - } - new_capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); - old_capacity = suspend_capacity; - - if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING) - { - //chargeing state - bat->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity; - } - else - { - bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity; - } - - printk("rk29_adc_battery_resume: status = %d, voltage = %d, capacity = %d, new_capacity = %d, old_capacity = %d\n", - bat->bat_status, bat->bat_voltage, bat->bat_capacity, new_capacity, old_capacity); - - //start timer scan - schedule_work(&bat->timer_work); - bat->timer.expires = jiffies + 10; - add_timer(&bat->timer); + int i; + int level,oldlevel; + int new_capacity, old_capacity; + struct rk29_adc_battery_data *bat = gBatteryData; + + bat->old_charge_level = -1; + pSamples = bat->adc_samples; + + adc_sync_read(bat->client); //start adc sample + level = oldlevel = rk29_adc_battery_status_samples(bat);//init charge status + + for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) { //0.3 s + + mdelay(1); + rk29_adc_battery_voltage_samples(bat); //get voltage + level = rk29_adc_battery_status_samples(bat); //check charge status + if (oldlevel != level){ + oldlevel = level; //if charge status changed, reset sample + i = 0; + } + } + new_capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); + old_capacity =gBatteryData-> suspend_capacity; + + if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING){ + //chargeing state + 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 + } + + //printk("rk29_adc_battery_resume: status = %d, voltage = %d, capacity = %d, new_capacity = %d, old_capacity = %d\n", + // bat->bat_status, bat->bat_voltage, bat->bat_capacity, new_capacity, old_capacity); //xsf + +// wake_lock_timeout(&batt_wake_lock, 5 * HZ); //5s } static int rk29_adc_battery_suspend(struct platform_device *dev, pm_message_t state) { - /* flush all pending status updates */ - suspend_capacity = gBatteryData->bat_capacity; - del_timer(&gBatteryData->timer); - //flush_scheduled_work(); + gBatteryData->suspend_capacity = gBatteryData->bat_capacity; return 0; } static int rk29_adc_battery_resume(struct platform_device *dev) { - /* things may have changed while we were away */ - schedule_work(&gBatteryData->resume_work); + gBatteryData->resume = true; return 0; } #else @@ -906,280 +893,370 @@ static int rk29_adc_battery_resume(struct platform_device *dev) #endif -static int rk29_adc_battery_io_init(struct rk29_adc_battery_data *data, struct rk29_adc_battery_platform_data *pdata) +unsigned long AdcTestCnt = 0; +static void rk29_adc_battery_timer_work(struct work_struct *work) { - int ret = 0; - - data->pdata = pdata; +#ifdef CONFIG_PM + if (gBatteryData->resume) { + rk29_adc_battery_resume_check(); + gBatteryData->resume = false; + } +#endif + + rk29_adc_battery_status_samples(gBatteryData); + + if (gBatteryData->poweron_check){ + gBatteryData->poweron_check = 0; + rk29_adc_battery_poweron_capacity_check(); + } + + rk29_adc_battery_voltage_samples(gBatteryData); - if (pdata->io_init) + rk29_adc_battery_capacity_samples(gBatteryData); + + + /*update battery parameter after adc and capacity has been changed*/ + if(gBatteryData->bat_change){ + gBatteryData->bat_change = 0; + rk29_adc_battery_put_capacity(gBatteryData->bat_capacity); + power_supply_changed(&rk29_battery_supply); + } + + if (rk29_battery_dbg_level) { + if (++AdcTestCnt >= 2) + { + AdcTestCnt = 0; + + printk("Status = %d, RealAdcVal = %d, RealVol = %d,gBatVol = %d, gBatCap = %d, RealCapacity = %d, dischargecnt = %d, chargecnt = %d\n", + gBatteryData->bat_status, gBatteryData->adc_val, adc_to_voltage(gBatteryData->adc_val), + gBatteryData->bat_voltage, gBatteryData->bat_capacity, gBatteryData->capacitytmp, gBatteryData->gBatCapacityDisChargeCnt,gBatteryData-> gBatCapacityChargeCnt); + + } + } + queue_delayed_work(gBatteryData->wq, &gBatteryData->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS)); + +} + + +static int rk29_adc_battery_io_init(struct rk29_adc_battery_platform_data *pdata) +{ + int ret = 0; + + if (pdata->io_init) { pdata->io_init(); } //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); - } + 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) - { - ret = gpio_request(pdata->dc_det_pin, NULL); - if (ret) { - printk("failed to request dc_det gpio\n"); - goto error; - } + if (pdata->dc_det_pin != INVALID_GPIO){ + ret = gpio_request(pdata->dc_det_pin, NULL); + if (ret) { + printk("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"); - 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"); + goto error; + } + } //charge ok detect - if (pdata->charge_ok_pin != INVALID_GPIO) - { - ret = gpio_request(pdata->charge_ok_pin, NULL); - if (ret) { - printk("failed to request charge_ok gpio\n"); - goto error; - } + if (pdata->charge_ok_pin != INVALID_GPIO){ + ret = gpio_request(pdata->charge_ok_pin, NULL); + if (ret) { + printk("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"); - 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"); + goto error; + } + } + //batt low pin + if( pdata->batt_low_pin != INVALID_GPIO){ + ret = gpio_request(pdata->batt_low_pin, NULL); + if (ret) { + printk("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"); + goto error; + } + } - return 0; + return 0; error: - return -1; + return -1; } - #define POWER_ON_PIN RK29_PIN4_PA4 -static void rk29_adc_battery_lowpower_check(struct rk29_adc_battery_data *bat) +#define LOOP(loops) do { unsigned int i = loops; barrier(); while (--i) barrier(); } while (0) + +//extern void kernel_power_off(void); +static void rk29_adc_battery_check(struct rk29_adc_battery_data *bat) { - int i; - int tmp = 0; - int level,oldlevel; - struct rk29_adc_battery_platform_data *pdata = bat->pdata; - - printk("%s--%d:\n",__FUNCTION__,__LINE__); - - old_charge_level = -1; - pSamples = bat->adc_samples; - - adc_sync_read(bat->client); //start adc sample - level = oldlevel = rk29_adc_battery_status_samples(bat);//init charge status - - bat->full_times = 0; - for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) //0.3 s - { - mdelay(1); - rk29_adc_battery_voltage_samples(bat); //get voltage - //level = rk29_adc_battery_status_samples(bat); //check charge status - level = rk29_adc_battery_get_charge_level(bat); - if (oldlevel != level) - { - oldlevel = level; //if charge status changed, reset sample - i = 0; - } - } - - bat->bat_capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); - bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; - if (rk29_adc_battery_get_charge_level(bat)) - { - bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; - if (pdata->charge_ok_pin != INVALID_GPIO) - { - if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level) - { - bat->bat_status = POWER_SUPPLY_STATUS_FULL; - bat->bat_capacity = 100; - } - } - } - -#if 0 - rk29_adc_battery_poweron_capacity_check(); + int i; + int tmp = 0; + int level,oldlevel; + struct rk29_adc_battery_platform_data *pdata = bat->pdata; + //printk("%s--%d:\n",__FUNCTION__,__LINE__); + + bat->old_charge_level = -1; + bat->capacitytmp = 0; + bat->suspend_capacity = 0; + + pSamples = bat->adc_samples; + + adc_sync_read(bat->client); //start adc sample + level = oldlevel = rk29_adc_battery_status_samples(bat);//init charge status + + bat->full_times = 0; + for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++){ //0.3 s + mdelay(1); + rk29_adc_battery_voltage_samples(bat); //get voltage + //level = rk29_adc_battery_status_samples(bat); //check charge status + level = rk29_adc_battery_get_charge_level(bat); + + if (oldlevel != level){ + oldlevel = level; //if charge status changed, reset sample + i = 0; + } + } + + bat->bat_capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltage); //init bat_capacity + + bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + if (rk29_adc_battery_get_charge_level(bat)){ + bat->bat_status = POWER_SUPPLY_STATUS_CHARGING; + + if (pdata->charge_ok_pin != INVALID_GPIO){ + if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level){ + bat->bat_status = POWER_SUPPLY_STATUS_FULL; + bat->bat_capacity = 100; + } + } + } + +#if 1 + rk29_adc_battery_poweron_capacity_check(); #else - poweron_check = 1; + gBatteryData->poweron_check = 1; #endif + gBatteryData->poweron_check = 0; - - /******************************************* - //¿ª»ú²ÉÑùµ½µÄµçѹºÍÉϴιػú±£´æµçѹÏà²î½Ï´ó£¬Ôõô´¦Àí£¿ - if (bat->bat_capacity > old_capacity) - { - if ((bat->bat_capacity - old_capacity) > 20) - { - - } - } - else if (bat->bat_capacity < old_capacity) - { - if ((old_capacity > bat->bat_capacity) > 20) - { - - } - } - *********************************************/ - if (bat->bat_capacity == 0) bat->bat_capacity = 1; - - if (bat->bat_voltage <= BATT_ZERO_VOL_VALUE + 50) - { - printk("low battery: powerdown\n"); - gpio_direction_output(POWER_ON_PIN, GPIO_LOW); - tmp = 0; - while(1) - { - if(gpio_get_value(POWER_ON_PIN) == GPIO_HIGH) - { - gpio_set_value(POWER_ON_PIN,GPIO_LOW); - } - mdelay(5); - if (++tmp > 50) break; +/******************************************* +//¿ª»ú²ÉÑùµ½µÄµçѹºÍÉϴιػú±£´æµçѹÏà²î½Ï´ó£¬Ôõô´¦Àí£¿ +if (bat->bat_capacity > old_capacity) +{ +if ((bat->bat_capacity - old_capacity) > 20) +{ + +} +} +else if (bat->bat_capacity < old_capacity) +{ +if ((old_capacity > bat->bat_capacity) > 20) +{ + +} +} +*********************************************/ + if (bat->bat_capacity == 0) bat->bat_capacity = 1; + + if (bat->bat_voltage <= BATT_ZERO_VOL_VALUE + 500){ + printk("low battery: powerdown\n"); + gpio_direction_output(POWER_ON_PIN, GPIO_LOW); + tmp = 0; + while(1){ + if(gpio_get_value(POWER_ON_PIN) == GPIO_HIGH){ + gpio_set_value(POWER_ON_PIN,GPIO_LOW); + } + mdelay(500); + if (++tmp > 50) + break; } - } - gpio_direction_output(POWER_ON_PIN, GPIO_HIGH); + + } + gpio_direction_output(POWER_ON_PIN, GPIO_HIGH); + } static void rk29_adc_battery_callback(struct adc_client *client, void *param, int result) { - gBatteryData->adc_val = result; +#if 0 + struct rk29_adc_battery_data *info = container_of(client, struct rk29_adc_battery_data, + client); + info->adc_val = result; +#endif + gBatteryData->adc_val = result; + return; +} + +#if 0 +static void rk29_adc_battery_lowerpower_delaywork(struct work_struct *work) +{ + struct rk29_adc_battery_platform_data *pdata; + int irq; + printk("lowerpower\n"); + pdata = gBatteryData->pdata; + irq = gpio_to_irq(pdata->dc_det_pin); + rk28_send_wakeup_key(); // wake up the system + free_irq(irq, NULL); return; } + +static irqreturn_t rk29_adc_battery_low_wakeup(int irq,void *dev_id) +{ + + schedule_work(&gBatteryData->lowerpower_work); + return IRQ_HANDLED; +} + +#endif + static int rk29_adc_battery_probe(struct platform_device *pdev) { int ret; - int irq; - int irq_flag; struct adc_client *client; struct rk29_adc_battery_data *data; struct rk29_adc_battery_platform_data *pdata = pdev->dev.platform_data; - printk("%s--%d:\n",__FUNCTION__,__LINE__); - + //printk("%s--%d:\n",__FUNCTION__,__LINE__); data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) { ret = -ENOMEM; goto err_data_alloc_failed; } gBatteryData = data; + platform_set_drvdata(pdev, data); - ret = rk29_adc_battery_io_init(data, pdata); - if (ret) - { - goto err_io_init; - } + data->pdata = pdata; + + ret = rk29_adc_battery_io_init(pdata); + if (ret) { + goto err_io_init; + } - //register adc for battery sample memset(data->adc_samples, 0, sizeof(int)*(NUM_VOLTAGE_SAMPLE + 2)); - client = adc_register(0, rk29_adc_battery_callback, NULL); - if(!client) + + //register adc for battery sample + client = adc_register(0, rk29_adc_battery_callback, NULL); //pdata->adc_channel = ani0 + if(!client) goto err_adc_register_failed; - - //variable init + + //variable init data->client = client; data->adc_val = adc_sync_read(client); ret = power_supply_register(&pdev->dev, &rk29_battery_supply); - if (ret) - { + if (ret){ printk(KERN_INFO "fail to battery power_supply_register\n"); goto err_battery_failed; } - + -#if defined(CONFIG_BATTERY_RK29_USB_CHARGE) +#if defined (CONFIG_BATTERY_RK29_USB_CHARGE) ret = power_supply_register(&pdev->dev, &rk29_usb_supply); - if (ret) - { + if (ret){ printk(KERN_INFO "fail to usb power_supply_register\n"); goto err_usb_failed; } #endif - - INIT_WORK(&data->timer_work, rk29_adc_battery_timer_work); - INIT_WORK(&data->resume_work, rk29_adc_battery_resume_check); - - //init a timer for adc sample - //init a delay work for adc timer work - setup_timer(&data->timer, rk29_adc_battery_scan_timer, (unsigned long)data); - data->timer.expires = jiffies + 2000; - add_timer(&data->timer); - - wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock"); -#if defined(CONFIG_BATTERY_RK29_AC_CHARGE) + data->wq = create_singlethread_workqueue("adc_battd"); + INIT_DELAYED_WORK(&data->delay_work, rk29_adc_battery_timer_work); + //Power on Battery detect + rk29_adc_battery_check(data); + queue_delayed_work(data->wq, &data->delay_work, msecs_to_jiffies(TIMER_MS_COUNTS)); +#if defined (CONFIG_BATTERY_RK29_AC_CHARGE) ret = power_supply_register(&pdev->dev, &rk29_ac_supply); if (ret) { printk(KERN_INFO "fail to ac power_supply_register\n"); goto err_ac_failed; } //init dc dectet irq & delay work - if (pdata->dc_det_pin != INVALID_GPIO) - { + if (pdata->dc_det_pin != INVALID_GPIO){ INIT_WORK(&data->dcwakeup_work, rk29_adc_battery_dcdet_delaywork); - irq = gpio_to_irq(pdata->dc_det_pin); - + + irq = gpio_to_irq(pdata->dc_det_pin); irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; - ret = request_irq(irq, rk29_adc_battery_dc_wakeup, irq_flag, "rk29_adc_battery", NULL); + ret = request_irq(irq, rk29_adc_battery_dc_wakeup, irq_flag, "ac_charge_irq", NULL); if (ret) { printk("failed to request dc det irq\n"); goto err_dcirq_failed; } - enable_irq_wake(irq); + enable_irq_wake(irq); } #endif - - //Power on Battery detect - rk29_adc_battery_lowpower_check(data); - +#if 0 + // batt low irq lowerpower_work + if( pdata->batt_low_pin != INVALID_GPIO){ + INIT_WORK(&data->lowerpower_work, rk29_adc_battery_lowerpower_delaywork); + + irq = gpio_to_irq(pdata->batt_low_pin); + ret = request_irq(irq, rk29_adc_battery_low_wakeup, IRQF_TRIGGER_LOW, "batt_low_irq", NULL); + + if (ret) { + printk("failed to request batt_low_irq irq\n"); + goto err_lowpowerirq_failed; + } + enable_irq_wake(irq); + } +#endif - printk(KERN_INFO "rk29_adc_battery: driver initialized\n"); +// printk(KERN_INFO "rk29_adc_battery: driver initialized\n"); return 0; -#if defined(CONFIG_BATTERY_RK29_USB_CHARGE) +#if defined (CONFIG_BATTERY_RK29_USB_CHARGE) err_usb_failed: power_supply_unregister(&rk29_usb_supply); #endif +#if defined (CONFIG_BATTERY_RK29_AC_CHARGE) err_ac_failed: -#if defined(CONFIG_BATTERY_RK29_AC_CHARGE) power_supply_unregister(&rk29_ac_supply); +err_dcirq_failed: + free_irq(gpio_to_irq(pdata->dc_det_pin), data); #endif err_battery_failed: power_supply_unregister(&rk29_battery_supply); -err_dcirq_failed: - free_irq(gpio_to_irq(pdata->dc_det_pin), data); - +#if 0 + 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); - printk("rk29_adc_battery: error!\n"); + printk("rk29_adc_battery: error!\n"); return ret; } @@ -1188,7 +1265,8 @@ static int rk29_adc_battery_remove(struct platform_device *pdev) { struct rk29_adc_battery_data *data = platform_get_drvdata(pdev); struct rk29_adc_battery_platform_data *pdata = pdev->dev.platform_data; - + + cancel_delayed_work(&gBatteryData->delay_work); #if defined(CONFIG_BATTERY_RK29_USB_CHARGE) power_supply_unregister(&rk29_usb_supply); #endif @@ -1207,7 +1285,7 @@ static int rk29_adc_battery_remove(struct platform_device *pdev) static struct platform_driver rk29_adc_battery_driver = { .probe = rk29_adc_battery_probe, .remove = rk29_adc_battery_remove, - .suspend = rk29_adc_battery_suspend, + .suspend = rk29_adc_battery_suspend, .resume = rk29_adc_battery_resume, .driver = { .name = "rk2918-battery", @@ -1225,9 +1303,9 @@ static void __exit rk29_adc_battery_exit(void) platform_driver_unregister(&rk29_adc_battery_driver); } -subsys_initcall(rk29_adc_battery_init); +subsys_initcall(rk29_adc_battery_init);//subsys_initcall(rk29_adc_battery_init); module_exit(rk29_adc_battery_exit); -MODULE_DESCRIPTION("Battery detect driver for the rk2918"); +MODULE_DESCRIPTION("Battery detect driver for the rk29"); MODULE_AUTHOR("luowei lw@rock-chips.com"); MODULE_LICENSE("GPL");