/* 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
#include <linux/ktime.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
-
+#include <linux/fs.h>
#include <linux/wakelock.h>
-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);
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;
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;
} charger_type_t;
-#define BATT_FILENAME "/data/bat_last_capacity.dat"
-#include <linux/fs.h>
-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,
.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
#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;
}
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;
.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);
}
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;
.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
#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;
}
{
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
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",
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");