mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
phone :RK30:phone: the bug of battery indicator
This commit is contained in:
@@ -243,6 +243,14 @@
|
||||
#define BATTERY_DETECT_THRESHOLD ((BATTERY_RESISTOR + SIMULATOR_RESISTOR) / 2) //battery voltage threshold divided by 22uA
|
||||
#define CHARGING_CAPACITY_UPDATE_PERIOD (1000 * 60 * 1)
|
||||
|
||||
|
||||
|
||||
/************************************************************/
|
||||
#define TIMER_MS_COUNTS 1000
|
||||
#define NUM_DISCHARGE_MIN_SAMPLE 30
|
||||
#define NUM_CHARGE_MIN_SAMPLE 30
|
||||
/**************************************************************/
|
||||
|
||||
/* To get VBUS input limit from twl6030_usb */
|
||||
#if CONFIG_TWL6030_USB
|
||||
extern unsigned int twl6030_get_usb_max_power(struct otg_transceiver *x);
|
||||
@@ -326,6 +334,12 @@ struct twl6030_bci_device_info {
|
||||
int current_max_scale;
|
||||
struct delayed_work work;
|
||||
unsigned int interval;
|
||||
|
||||
int gBatCapacityDisChargeCnt;
|
||||
int capacitytmp;
|
||||
int usb_status;
|
||||
int usb_old_satus;
|
||||
int gBatCapacityChargeCnt;
|
||||
};
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(notifier_list);
|
||||
@@ -616,7 +630,7 @@ static void twl6030_stop_usb_charger(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
//printk("*************twl6030_stop_usb_charger***************\n");
|
||||
if (di->use_hw_charger) {
|
||||
ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, ®,
|
||||
CHARGERUSB_CTRL1);
|
||||
@@ -646,6 +660,9 @@ static void twl6030_start_usb_charger(struct twl6030_bci_device_info *di)
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
|
||||
//printk("***************twl6030_start_usb_charger*****************************************\n");
|
||||
|
||||
if (di->use_hw_charger) {
|
||||
ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, ®,
|
||||
CHARGERUSB_CTRL1);
|
||||
@@ -757,6 +774,7 @@ static void twl6030_start_ac_charger(struct twl6030_bci_device_info *di)
|
||||
|
||||
static void twl6030_stop_charger(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
//printk("$$$$$$$$$$$$twl6030_stop_charger$$$$$$$$$$$$\n");
|
||||
if (di->charger_source == POWER_SUPPLY_TYPE_MAINS)
|
||||
twl6030_stop_ac_charger(di);
|
||||
else if (di->charger_source == POWER_SUPPLY_TYPE_USB)
|
||||
@@ -832,6 +850,8 @@ static void twl6032_charger_ctrl_interrupt(struct twl6030_bci_device_info *di)
|
||||
*/
|
||||
static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
|
||||
{
|
||||
// printk("%s\n", __func__);
|
||||
|
||||
struct twl6030_bci_device_info *di = _di;
|
||||
int ret;
|
||||
int charger_fault = 0;
|
||||
@@ -1084,6 +1104,7 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
|
||||
int charger_stop = 0, end_of_charge = 0;
|
||||
int ret;
|
||||
|
||||
//printk("xxxxxxxxxxxxxxxxxxxxxxxx twl6032charger_ctrl_interrupt_hw xxxxxxxxxxxxxx\n");
|
||||
/* read charger controller_stat1 */
|
||||
ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1,
|
||||
CONTROLLER_STAT1);
|
||||
@@ -1098,15 +1119,20 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
|
||||
if (!(stat1 & (VBUS_DET | VAC_DET))) {
|
||||
charger_stop = 1;
|
||||
di->ac_online = di->usb_online = 0;
|
||||
//printk("%%%%%%%%%%%%%%charger_stop = 1%%%%%%%%%%%%%\n");
|
||||
}
|
||||
|
||||
if (!(di->usb_online || di->ac_online)) {
|
||||
if (stat1 & VBUS_DET) {
|
||||
di->usb_online = 1;
|
||||
di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
|
||||
// printk("%%%%%%%%%%%%%%di->usb_online = 1%%%%%%%%%%%%%\n");
|
||||
|
||||
//schedule_work(&di->usb_work);
|
||||
} else if (stat1 & VAC_DET) {
|
||||
di->ac_online = 1;
|
||||
di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
|
||||
// printk("%%%%%%%%%%%%%%di->ac_online = 1%%%%%%%%%%%%%\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1168,6 +1194,7 @@ static irqreturn_t twl6032charger_ctrl_interrupt_hw(int irq, void *_di)
|
||||
POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
}
|
||||
}
|
||||
//printk("%%%%%%%%%%%%%%%%%%twl6032charger_ctrl_interrupt_hw end xxxxxxxxxxxxxx\n");
|
||||
|
||||
power_supply_changed(&di->bat);
|
||||
|
||||
@@ -1453,6 +1480,8 @@ static enum power_supply_property twl6030_bk_bci_battery_props[] = {
|
||||
|
||||
static void twl6030_current_avg(struct work_struct *work)
|
||||
{
|
||||
// printk("%s\n", __func__);
|
||||
|
||||
s32 samples = 0;
|
||||
s16 cc_offset = 0;
|
||||
int current_avg_uA = 0;
|
||||
@@ -1517,32 +1546,35 @@ static void twl6030_current_avg(struct work_struct *work)
|
||||
err:
|
||||
pr_err("%s: Error access to TWL6030 (%d)\n", __func__, ret);
|
||||
}
|
||||
#define BATT_NUM 52
|
||||
#define BATT_NUM 11
|
||||
struct batt_vol_cal{
|
||||
u32 disp_cal;
|
||||
u32 dis_charge_vol;
|
||||
u32 charge_vol;
|
||||
};
|
||||
static struct batt_vol_cal batt_table[BATT_NUM] = {
|
||||
{0,3400,3520},{1,3420,3525},{2,3420,3575},{3,3475,3600},{5,3505,3620},{7,3525,3644},
|
||||
{9,3540,3662},{11,3557,3670},{13,3570,3684},{15,3580,3700},{17,3610,3715},
|
||||
{19,3630,3720},{21,3640,3748},{23,3652,3756},{25,3662,3775},{27,3672,3790},
|
||||
{29,3680,3810},{31,3687,3814},{33,3693,3818},{35,3699,3822},{37,3705,3825},
|
||||
{39,3710,3830},{41,3714,3832},{43,3718,3834},{45,3722,3836},{47,3726,3837},
|
||||
{49,3730,3839},{51,3734,3841},{53,3738,3842},{55,3742,3844},{57,3746,3844},
|
||||
{59,3750,3855},{61,3756,3860},{63,3764,3864},{65,3774,3871},{67,3786,3890},
|
||||
{69,3800,3910},{71,3808,3930},{73,3817,3977},{75,3827,3977},{77,3845,3997},
|
||||
{79,3950,4030},{81,3964,4047},{83,3982,4064},{85,4002,4080},{87,4026,4096},
|
||||
{89,4030,4132},{91,4034,4144},{93,4055,4150},{95,4085,4195},{97,4085,4195},{100,4120,4200},
|
||||
{0,3571,3730},//{1,3420,3525},{2,3420,3575},{3,3475,3600},{5,3505,3620},{7,3525,3644},
|
||||
{9,3628,3770},//{11,3557,3670},{13,3570,3684},{15,3580,3700},{17,3610,3715},
|
||||
{19,3670,3878},//{21,3640,3748},{23,3652,3756},{25,3662,3775},{27,3672,3790},
|
||||
{29,3719,3895},//{31,3687,3814},{33,3693,3818},{35,3699,3822},{37,3705,3825},
|
||||
{39,3770,3941},//{41,3714,3832},{43,3718,3834},{45,3722,3836},{47,3726,3837},
|
||||
{49,3801,3980},//{51,3734,3841},{53,3738,3842},{55,3742,3844},{57,3746,3844},
|
||||
{59,3849,4010},//{61,3756,3860},{63,3764,3864},{65,3774,3871},{67,3786,3890},
|
||||
{69,3864,4024},//{71,3808,3930},{73,3817,3977},{75,3827,3977},{77,3845,3997},
|
||||
{79,3884,4040},//{81,3964,4047},{83,3982,4064},{85,4002,4080},{87,4026,4096},
|
||||
{89,4001,4050},//{91,4034,4144},{93,4055,4150},{95,4085,4195},{97,4085,4195},
|
||||
{100,4070,4090},
|
||||
};
|
||||
#if 0
|
||||
static int capacity_changed(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
int curr_capacity = di->capacity;
|
||||
int charger_source = di->charger_source;
|
||||
int charging_disabled = 0;
|
||||
struct batt_vol_cal *p;
|
||||
p = batt_table;
|
||||
int i=0;
|
||||
|
||||
p = batt_table;
|
||||
/* Because system load is always greater than
|
||||
* termination current, we will never get a CHARGE DONE
|
||||
* int from BQ. And charging will alwys be in progress.
|
||||
@@ -1672,218 +1704,130 @@ static int capacity_changed(struct twl6030_bci_device_info *di)
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
void twl6030_batt_vol_level(struct twl6030_bci_device_info *di, int batt_vol, int *level)
|
||||
#endif
|
||||
static int twl6030_batt_vol_to_capacity (struct twl6030_bci_device_info *di)
|
||||
|
||||
{
|
||||
int i =0, status =0;
|
||||
static int chg_plus = 1000;
|
||||
static int chg_minus = 1000;
|
||||
static int chg_curr = 0;
|
||||
static int chg_num = 60;
|
||||
static int disp_plus = 1000;
|
||||
static int disp_minus = 1000;
|
||||
static int disp_minus2 = 1000;
|
||||
static int disp_curr = 0;
|
||||
static int disp_num = 50;
|
||||
static int batt_level_all = 0;
|
||||
static int batt_level[20];
|
||||
static int avr_num = 0;
|
||||
static int avr_int = 0;
|
||||
|
||||
int i = 0;
|
||||
int capacity = 0;
|
||||
int BatVoltage;
|
||||
|
||||
struct batt_vol_cal *p;
|
||||
p = batt_table;
|
||||
|
||||
BatVoltage = di ->voltage_mV;
|
||||
|
||||
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING){ //charge
|
||||
if(BatVoltage >= (p[BATT_NUM - 1].charge_vol)){
|
||||
capacity = 100;
|
||||
}
|
||||
else{
|
||||
if(BatVoltage <= (p[0].charge_vol)){
|
||||
capacity = 0;
|
||||
}
|
||||
else{
|
||||
for(i = 0; i < BATT_NUM - 1; i++){
|
||||
|
||||
if(((p[i].charge_vol) <= BatVoltage) && (BatVoltage < (p[i+1].charge_vol))){
|
||||
// capacity = p[i].disp_cal ;
|
||||
capacity = i * 10 + ((BatVoltage - p[i].charge_vol) * 10) / (p[i+1] .charge_vol- p[i].charge_vol);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{ //discharge
|
||||
if(BatVoltage >= (p[BATT_NUM - 1].dis_charge_vol)){
|
||||
capacity = 100;
|
||||
}
|
||||
else{
|
||||
if(BatVoltage <= (p[0].dis_charge_vol)){
|
||||
capacity = 0;
|
||||
}
|
||||
else{
|
||||
for(i = 0; i < BATT_NUM - 1; i++){
|
||||
if(((p[i].dis_charge_vol) <= BatVoltage) && (BatVoltage < (p[i+1].dis_charge_vol))){
|
||||
// capacity = p[i].disp_cal ;
|
||||
capacity = i * 10 + ((BatVoltage - p[i].dis_charge_vol) * 10) / (p[i+1] .dis_charge_vol- p[i].dis_charge_vol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
*level = di->capacity;
|
||||
}
|
||||
|
||||
if (status == POWER_SUPPLY_STATUS_DISCHARGING
|
||||
&& batt_vol >= batt_table[BATT_NUM-1].charge_vol) {
|
||||
*level = 100;
|
||||
return ;
|
||||
}
|
||||
return capacity;
|
||||
|
||||
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING)
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
disp_minus2 = 0;
|
||||
disp_curr = 0;
|
||||
for(i = 0; i < BATT_NUM; i++){
|
||||
if(batt_vol >= batt_table[i].charge_vol &&
|
||||
batt_vol < batt_table[i+1].charge_vol)
|
||||
break;
|
||||
}
|
||||
if(batt_vol <= batt_table[0].charge_vol)
|
||||
i = 0;
|
||||
if(batt_vol >= batt_table[BATT_NUM-1].charge_vol)
|
||||
i = BATT_NUM-1;
|
||||
if(avr_int==0){
|
||||
batt_level[avr_num] = batt_table[i].disp_cal;
|
||||
batt_level_all += batt_level[avr_num];
|
||||
avr_num++;
|
||||
if(avr_num >= 20)
|
||||
{
|
||||
avr_num = 0;
|
||||
avr_int = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = batt_table[i].disp_cal;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
batt_level_all -= batt_level[avr_num];
|
||||
batt_level[avr_num]=batt_table[i].disp_cal;
|
||||
batt_level_all += batt_level[avr_num];
|
||||
avr_num++;
|
||||
}
|
||||
if(avr_num >= 20)
|
||||
avr_num = 0;
|
||||
*level = batt_level_all/20;
|
||||
if ((chg_plus == 1000) && (chg_minus == 1000))
|
||||
{
|
||||
*level = *level;
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (*level >= (di->capacity +1))
|
||||
{
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
if(*level < 85)
|
||||
chg_num =10;
|
||||
else
|
||||
chg_num = 5;
|
||||
if (++chg_plus > chg_num)
|
||||
{
|
||||
*level = di->capacity + 1;
|
||||
chg_plus = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = di->capacity;
|
||||
|
||||
void twl6030_batt_capacity_samples(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
int capacity = 0;
|
||||
capacity = twl6030_batt_vol_to_capacity (di);
|
||||
twl6030battery_current(di);
|
||||
//printk("old-capactiyt == %d, now-capacity == %d , di->charge_status == %d,di->current_uA = %d\n", di->capacity, capacity, di->charge_status,di->current_uA);
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// capacity = twl6030_batt_vol_to_capacity (di);
|
||||
|
||||
if (di->charge_status == POWER_SUPPLY_STATUS_FULL){
|
||||
if (capacity < di->capacity){
|
||||
if (di ->gBatCapacityChargeCnt >= NUM_CHARGE_MIN_SAMPLE){
|
||||
di ->gBatCapacityChargeCnt = 0;
|
||||
if (di -> capacity < 99){
|
||||
di -> capacity++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
*level = di->capacity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (*level >= 100)
|
||||
*level = 100;
|
||||
if (*level < 0)
|
||||
*level = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
chg_plus = 0;
|
||||
chg_minus = 0;
|
||||
chg_curr = 0;
|
||||
for(i = 0; i < BATT_NUM; i++){
|
||||
if(batt_vol >= batt_table[i].dis_charge_vol &&
|
||||
batt_vol < batt_table[i+1].dis_charge_vol)
|
||||
break;
|
||||
}
|
||||
if(batt_vol <= batt_table[0].dis_charge_vol)
|
||||
i = 0;
|
||||
if(batt_vol >= batt_table[BATT_NUM-1].dis_charge_vol)
|
||||
i = BATT_NUM-1;
|
||||
if(avr_int==0){
|
||||
batt_level[avr_num] =batt_table[i].disp_cal;
|
||||
batt_level_all += batt_level[avr_num];
|
||||
avr_num++;
|
||||
if(avr_num >= 20)
|
||||
{
|
||||
avr_num = 0;
|
||||
avr_int = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = batt_table[i].disp_cal;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
batt_level_all -= batt_level[avr_num];
|
||||
batt_level[avr_num]=batt_table[i].disp_cal;
|
||||
batt_level_all += batt_level[avr_num];
|
||||
avr_num++;
|
||||
}
|
||||
if(avr_num >= 20)
|
||||
avr_num = 0;
|
||||
*level = batt_level_all/20;
|
||||
if ((disp_plus == 1000) && (disp_minus == 1000))
|
||||
{
|
||||
*level = *level;
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
disp_minus2 =0;
|
||||
disp_curr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(*level <= (di->capacity -20))
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_curr = 0;
|
||||
disp_minus2 = 0;
|
||||
disp_num = 1;
|
||||
if (++disp_minus > disp_num)
|
||||
{
|
||||
*level = di->capacity - 20;
|
||||
disp_minus = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*level = di->capacity;
|
||||
}
|
||||
}
|
||||
else if (*level <= (di->capacity-1))
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_curr = 0;
|
||||
disp_minus = 0;
|
||||
if((*level < 17) || (*level > 85))
|
||||
disp_num = 30;
|
||||
else
|
||||
disp_num = 80;
|
||||
|
||||
if (++disp_minus2 > disp_num)
|
||||
{
|
||||
*level = di->capacity - 1;
|
||||
disp_minus2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
*level = di->capacity;
|
||||
|
||||
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING){
|
||||
if (capacity > di->capacity){
|
||||
//ʵ<>ʲ<EFBFBD><CAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (++(di->gBatCapacityChargeCnt) >= NUM_CHARGE_MIN_SAMPLE){
|
||||
di ->gBatCapacityChargeCnt = 0;
|
||||
if (di -> capacity < 99){
|
||||
di -> capacity++;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disp_plus = 0;
|
||||
disp_minus = 0;
|
||||
disp_minus2 = 0;
|
||||
disp_curr = 0;
|
||||
*level = di->capacity;
|
||||
}
|
||||
di->gBatCapacityDisChargeCnt = 0; //<2F>ŵ<EFBFBD><C5B5>ļ<EFBFBD><C4BC><EFBFBD>ֵΪ0
|
||||
}
|
||||
|
||||
if (*level >= 100)
|
||||
*level = 100;
|
||||
if (*level < 0)
|
||||
*level = 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if ((di->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)||(di->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING)){
|
||||
|
||||
//<2F>ŵ<EFBFBD>ʱ,ֻ<><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD>½<EFBFBD>
|
||||
if (capacity < di -> capacity){
|
||||
if (++(di->gBatCapacityDisChargeCnt) >= NUM_DISCHARGE_MIN_SAMPLE){
|
||||
di ->gBatCapacityDisChargeCnt = 0;
|
||||
if (di -> capacity > 0){
|
||||
di -> capacity-- ;
|
||||
//bat->bat_change = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
di ->gBatCapacityDisChargeCnt = 0;
|
||||
}
|
||||
//di ->gBatCapacityChargeCnt = 0;
|
||||
}
|
||||
di ->capacitytmp = capacity;
|
||||
}
|
||||
|
||||
static int twl6030_set_watchdog(struct twl6030_bci_device_info *di, int val)
|
||||
@@ -1895,16 +1839,14 @@ static int twl6030_set_watchdog(struct twl6030_bci_device_info *di, int val)
|
||||
return twl_i2c_write_u8(TWL6030_MODULE_CHARGER, val, CONTROLLER_WDG);
|
||||
|
||||
}
|
||||
|
||||
static void twl6030_bci_battery_work(struct work_struct *work)
|
||||
#if 0
|
||||
static void twl6030_bci_adc_set(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
struct twl6030_bci_device_info *di = container_of(work,
|
||||
struct twl6030_bci_device_info, twl6030_bci_monitor_work.work);
|
||||
struct twl6030_gpadc_request req;
|
||||
int adc_code;
|
||||
int temp;
|
||||
int ret;
|
||||
int level;
|
||||
//int level;
|
||||
|
||||
/* Kick the charger watchdog */
|
||||
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING)
|
||||
@@ -1916,8 +1858,6 @@ static void twl6030_bci_battery_work(struct work_struct *work)
|
||||
req.func_cb = NULL;
|
||||
ret = twl6030_gpadc_conversion(&req);
|
||||
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
|
||||
msecs_to_jiffies(1000 * di->monitoring_interval));
|
||||
|
||||
if (ret < 0) {
|
||||
dev_dbg(di->dev, "gpadc conversion failed: %d\n", ret);
|
||||
@@ -1939,19 +1879,70 @@ static void twl6030_bci_battery_work(struct work_struct *work)
|
||||
battery_tmp_tbl[temp])
|
||||
break;
|
||||
}
|
||||
//printk("twl6030_bci_adc_set---di->voltage_mV-=-%d,di->capacity = %d \n",di->voltage_mV,di->capacity);
|
||||
/* first 2 values are for negative temperature */
|
||||
|
||||
}
|
||||
#endif
|
||||
static void twl6030_bci_battery_work(struct work_struct *work)
|
||||
{
|
||||
|
||||
struct twl6030_bci_device_info *di = container_of(work,
|
||||
struct twl6030_bci_device_info, twl6030_bci_monitor_work.work);
|
||||
struct twl6030_gpadc_request req;
|
||||
int adc_code;
|
||||
int temp;
|
||||
int ret;
|
||||
// int level;
|
||||
|
||||
/* Kick the charger watchdog */
|
||||
if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING)
|
||||
twl6030_set_watchdog(di, di->watchdog_duration);
|
||||
|
||||
req.method = TWL6030_GPADC_SW2;
|
||||
req.channels = (1 << 1) | (1 << di->gpadc_vbat_chnl) | (1 << 8);
|
||||
req.active = 0;
|
||||
req.func_cb = NULL;
|
||||
ret = twl6030_gpadc_conversion(&req);
|
||||
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
|
||||
msecs_to_jiffies(TIMER_MS_COUNTS)); //* di->monitoring_interval
|
||||
|
||||
if (ret < 0) {
|
||||
dev_dbg(di->dev, "gpadc conversion failed: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.rbuf[di->gpadc_vbat_chnl] > 0)
|
||||
di->voltage_mV = req.rbuf[di->gpadc_vbat_chnl];
|
||||
|
||||
if (req.rbuf[8] > 0)
|
||||
di->bk_voltage_mV = req.rbuf[8];
|
||||
|
||||
if (di->platform_data->battery_tmp_tbl == NULL)
|
||||
return;
|
||||
|
||||
adc_code = req.rbuf[1];
|
||||
for (temp = 0; temp < di->platform_data->tblsize; temp++) {
|
||||
if (adc_code >= di->platform_data->
|
||||
battery_tmp_tbl[temp])
|
||||
break;
|
||||
}
|
||||
//printk("workxxxxx---di->voltage_mV-=-%d,di->capacity = %d \n",di->voltage_mV,di->capacity);
|
||||
/* first 2 values are for negative temperature */
|
||||
di->temp_C = (temp - 2); /* in degrees Celsius */
|
||||
if (capacity_changed(di)){
|
||||
twl6030_batt_vol_level(di, di->voltage_mV, &level);
|
||||
di->capacity = level;
|
||||
// if (capacity_changed(di)) //xsf
|
||||
{
|
||||
twl6030_batt_capacity_samples(di);
|
||||
// di->capacity = level;
|
||||
power_supply_changed(&di->bat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void twl6030_current_mode_changed(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
int ret;
|
||||
//printk("%s\n", __func__);
|
||||
|
||||
/* FG_REG_01, 02, 03 is 24 bit unsigned sample counter value */
|
||||
ret = twl_i2c_read(TWL6030_MODULE_GASGAUGE, (u8 *) &di->timer_n1,
|
||||
@@ -1977,6 +1968,8 @@ err:
|
||||
|
||||
static void twl6030_work_interval_changed(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
//printk("%s\n", __func__);
|
||||
|
||||
cancel_delayed_work(&di->twl6030_bci_monitor_work);
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work,
|
||||
msecs_to_jiffies(1000 * di->monitoring_interval));
|
||||
@@ -1984,14 +1977,16 @@ static void twl6030_work_interval_changed(struct twl6030_bci_device_info *di)
|
||||
|
||||
#define to_twl6030_bci_device_info(x) container_of((x), \
|
||||
struct twl6030_bci_device_info, bat);
|
||||
|
||||
#if 0
|
||||
static void twl6030_bci_battery_external_power_changed(struct power_supply *psy)
|
||||
{
|
||||
{// printk("%s\n", __func__);
|
||||
|
||||
struct twl6030_bci_device_info *di = to_twl6030_bci_device_info(psy);
|
||||
|
||||
cancel_delayed_work(&di->twl6030_bci_monitor_work);
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define to_twl6030_ac_device_info(x) container_of((x), \
|
||||
struct twl6030_bci_device_info, ac);
|
||||
@@ -2000,14 +1995,25 @@ static int twl6030_ac_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
u8 stat1;
|
||||
struct twl6030_bci_device_info *di = to_twl6030_ac_device_info(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = di->ac_online;
|
||||
twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1,
|
||||
CONTROLLER_STAT1);
|
||||
|
||||
if (stat1 & VAC_DET) {
|
||||
val->intval = 1;
|
||||
}
|
||||
else
|
||||
val->intval = 0;
|
||||
|
||||
///printk("&&&&&&&&&&&&ac---charge ac->intval = %d &&&&&&&&&&&&&&&\n" ,val->intval);
|
||||
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
val->intval = twl6030_get_gpadc_conversion(di, 9) * 1000;
|
||||
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -2023,14 +2029,27 @@ static int twl6030_usb_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
u8 stat1;
|
||||
struct twl6030_bci_device_info *di = to_twl6030_usb_device_info(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = di->usb_online;
|
||||
|
||||
twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1,
|
||||
CONTROLLER_STAT1);
|
||||
|
||||
if (stat1 & VBUS_DET) {
|
||||
val->intval = 1;
|
||||
}
|
||||
else
|
||||
val->intval = 0;
|
||||
|
||||
//val->intval = di->usb_online; //xsf
|
||||
|
||||
//printk("&&&&&&&&&&&&usb---charge val->intval = %d &&&&&&&&&&&&&&&\n" ,val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
val->intval = twl6030_get_gpadc_conversion(di, 10) * 1000;
|
||||
//printk("&&&&&&&&&&&&usb-voltage = &&&&&&&&&&&&&&&%d\n", val->intval);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -2119,7 +2138,6 @@ static void twl6030_usb_charger_work(struct work_struct *work)
|
||||
{
|
||||
struct twl6030_bci_device_info *di =
|
||||
container_of(work, struct twl6030_bci_device_info, usb_work);
|
||||
|
||||
switch (di->event) {
|
||||
case USB_EVENT_CHARGER:
|
||||
/* POWER_SUPPLY_TYPE_USB_DCP */
|
||||
@@ -2152,6 +2170,7 @@ static void twl6030_usb_charger_work(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
twl6030_start_usb_charger(di);
|
||||
|
||||
power_supply_changed(&di->usb);
|
||||
}
|
||||
|
||||
@@ -2160,7 +2179,6 @@ static int twl6030_usb_notifier_call(struct notifier_block *nb,
|
||||
{
|
||||
struct twl6030_bci_device_info *di =
|
||||
container_of(nb, struct twl6030_bci_device_info, nb);
|
||||
|
||||
di->event = event;
|
||||
switch (event) {
|
||||
case USB_EVENT_VBUS:
|
||||
@@ -2700,9 +2718,13 @@ extern int dwc_vbus_status(void);
|
||||
static void twl6030_battery_update_status(struct twl6030_bci_device_info *di)
|
||||
{
|
||||
power_supply_changed(&di->bat);
|
||||
power_supply_changed(&di->usb);
|
||||
power_supply_changed(&di->ac);
|
||||
|
||||
}
|
||||
static void twl6030_battery_work(struct work_struct *work)
|
||||
{
|
||||
{
|
||||
|
||||
struct twl6030_bci_device_info *di = container_of(work, struct twl6030_bci_device_info, work.work);
|
||||
twl6030_battery_update_status(di);
|
||||
//set charging current
|
||||
@@ -2729,7 +2751,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
u8 chargerusb_ctrl1 = 0;
|
||||
u8 hw_state = 0;
|
||||
u8 reg = 0;
|
||||
printk("%s\n", __func__);
|
||||
//printk("%s\n", __func__);
|
||||
if (!pdata) {
|
||||
dev_info(&pdev->dev, "platform_data not available\n");
|
||||
return -EINVAL;
|
||||
@@ -2757,6 +2779,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
di->features = pdata->features;
|
||||
di->dev = &pdev->dev;
|
||||
|
||||
|
||||
// printk("di->feature = %d, TWL6032_SUBCLASS = %d\n",di->features,TWL6032_SUBCLASS);
|
||||
if (di->features & TWL6032_SUBCLASS) {
|
||||
ret = twl_i2c_read_u8(TWL_MODULE_RTC, ®, CHARGER_MODE_REG);
|
||||
if (ret)
|
||||
@@ -2781,7 +2805,9 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
di->use_power_path = 0;
|
||||
di->use_hw_charger = 0;
|
||||
}
|
||||
// printk("di->feature = %d, TWL6032_SUBCLASS = %d,di->use_hw_charger =%d \n",di->features,TWL6032_SUBCLASS,di->use_hw_charger );
|
||||
|
||||
|
||||
if (di->use_hw_charger) {
|
||||
di->platform_data->max_charger_currentmA =
|
||||
twl6030_get_limit2_reg(di);
|
||||
@@ -2792,7 +2818,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
di->platform_data->max_bat_voltagemV =
|
||||
twl6030_get_voreg_reg(di);
|
||||
}
|
||||
|
||||
// printk("max_charger_currentmA = %d, max_charger_voltagemV = %d\n,termination_currentmA =%d, max_bat_voltagemV =%d \n",di->platform_data->max_charger_currentmA ,
|
||||
// di->platform_data->max_charger_voltagemV,di->platform_data->termination_currentmA, di->platform_data->max_bat_voltagemV);
|
||||
di->bat.name = "twl6030_battery";
|
||||
di->bat.supplied_to = twl6030_bci_supplied_to;
|
||||
di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to);
|
||||
@@ -2800,8 +2827,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
di->bat.properties = twl6030_bci_battery_props;
|
||||
di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props);
|
||||
di->bat.get_property = twl6030_bci_battery_get_property;
|
||||
di->bat.external_power_changed =
|
||||
twl6030_bci_battery_external_power_changed;
|
||||
//di->bat.external_power_changed =
|
||||
// twl6030_bci_battery_external_power_changed;
|
||||
di->bat_health = POWER_SUPPLY_HEALTH_GOOD;
|
||||
|
||||
di->usb.name = "twl6030_usb";
|
||||
@@ -2872,8 +2899,8 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
0, "twl_bci_ctrl", di);
|
||||
else
|
||||
ret = request_threaded_irq(irq, NULL,
|
||||
twl6032charger_ctrl_interrupt_hw,
|
||||
0, "twl_bci_ctrl", di);
|
||||
twl6032charger_ctrl_interrupt_hw,
|
||||
0, "twl_bci_ctrl", di); // һֱ<D2BB>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>״̬
|
||||
|
||||
if (ret) {
|
||||
dev_info(&pdev->dev, "could not request irq %d, status %d\n",
|
||||
@@ -2908,14 +2935,16 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
di->timer_n1 = 0;
|
||||
|
||||
//di->freezable_work = create_freezable_workqueue("battery");
|
||||
di->freezable_work = system_freezable_wq;
|
||||
INIT_DELAYED_WORK(&di->twl6030_bci_monitor_work,
|
||||
twl6030_bci_battery_work);
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
|
||||
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_current_avg_work,
|
||||
twl6030_current_avg);
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work, 500);
|
||||
#if 1
|
||||
if (di->features & TWL6032_SUBCLASS) {
|
||||
di->charger_incurrentmA = 1000;
|
||||
di->gpadc_vbat_chnl = TWL6032_GPADC_VBAT_CHNL;
|
||||
} else {
|
||||
di->charger_incurrentmA = twl6030_get_usb_max_power(di->otg);
|
||||
di->gpadc_vbat_chnl = TWL6030_GPADC_VBAT_CHNL;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
|
||||
ret = twl6030battery_voltage_setup(di);
|
||||
if (ret)
|
||||
@@ -2925,6 +2954,32 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
dev_info(&pdev->dev, "current measurement setup failed\n");
|
||||
|
||||
|
||||
di->voltage_mV = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
|
||||
di->voltage_mV = twl6030_get_gpadc_conversion(di, di->gpadc_vbat_chnl);
|
||||
di->capacity = twl6030_batt_vol_to_capacity( di);
|
||||
twl6030battery_current(di);
|
||||
#endif
|
||||
di->freezable_work = system_freezable_wq;
|
||||
INIT_DELAYED_WORK(&di->twl6030_bci_monitor_work,
|
||||
twl6030_bci_battery_work);
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_bci_monitor_work, 0);
|
||||
#if 1
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_current_avg_work,
|
||||
twl6030_current_avg);
|
||||
queue_delayed_work(di->freezable_work, &di->twl6030_current_avg_work, 500);
|
||||
#endif
|
||||
#if 0
|
||||
ret = twl6030battery_voltage_setup(di);
|
||||
if (ret)
|
||||
dev_info(&pdev->dev, "voltage measurement setup failed\n");
|
||||
|
||||
ret = twl6030battery_current_setup(true);
|
||||
if (ret)
|
||||
dev_info(&pdev->dev, "current measurement setup failed\n");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* initialize for USB charging */
|
||||
if (!di->use_hw_charger) {
|
||||
twl6030_config_limit1_reg(di, pdata->max_charger_voltagemV);
|
||||
@@ -2962,6 +3017,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
} else
|
||||
dev_err(&pdev->dev, "otg_get_transceiver failed %d\n", ret);
|
||||
|
||||
|
||||
if (di->features & TWL6032_SUBCLASS) {
|
||||
di->charger_incurrentmA = 1000;
|
||||
di->gpadc_vbat_chnl = TWL6032_GPADC_VBAT_CHNL;
|
||||
@@ -2985,7 +3041,7 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto bk_batt_failed;
|
||||
|
||||
chargerusb_ctrl1 |= HZ_MODE;
|
||||
chargerusb_ctrl1 |= HZ_MODE; // high-impedance
|
||||
ret = twl_i2c_write_u8(TWL6030_MODULE_CHARGER,
|
||||
chargerusb_ctrl1, CHARGERUSB_CTRL1);
|
||||
if (ret)
|
||||
@@ -3036,11 +3092,11 @@ static int __devinit twl6030_bci_battery_probe(struct platform_device *pdev)
|
||||
POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
di->interval = msecs_to_jiffies(1 * 1000);
|
||||
INIT_DELAYED_WORK(&di->work, twl6030_battery_work);
|
||||
queue_delayed_work(di->freezable_work, &di->work, 1*HZ);
|
||||
|
||||
#endif
|
||||
ret = twl6030backupbatt_setup();
|
||||
if (ret)
|
||||
dev_info(&pdev->dev, "Backup Bat charging setup failed\n");
|
||||
|
||||
Reference in New Issue
Block a user