static void max17040_schedule(void) { switch(max17040_data.online) { case 0 : //usb not connected if(max17040_data.slow_poll) //usb not connected and suspend { sleep_dbg("CONFIG SLOW_POLL [The alarm is set for [%d] seconds ]\n",SLOW_POLL); max17040_program_alarm_set(&max17040_data, SLOW_POLL); } else { sleep_dbg("CONFIG FAST_POLL [The alarm is set for [%d] seconds]\n",FAST_POLL); max17040_program_alarm_set(&max17040_data, FAST_POLL); } break; case 1 : //usb connection sleep_dbg("CONFIG FAST_POLL [The alarm is set for [%d] seconds]\n",FAST_POLL); max17040_program_alarm_set(&max17040_data, FAST_POLL); break; default: sleep_dbg("CONFIG [Time setting is not]\n"); break; } }
static void max17040_quick_get_vcell(void) { u8 msb=0; u8 lsb=0; unsigned long quick_avalue; //unsigned long temp; unsigned long voltage=0; int i=0; bool completed = false; while (!completed) { msb = max17040_read_reg(MAX17040_VCELL_MSB); lsb = max17040_read_reg(MAX17040_VCELL_LSB); if(msb < 0 || lsb < 0) { for(i=0;i<MAX_READ;i++) { msb = max17040_read_reg(MAX17040_VCELL_MSB); lsb = max17040_read_reg(MAX17040_VCELL_LSB); if(msb < 0 || lsb <0) { continue; } else break; } } voltage=(msb<<4)|((lsb&0xf0)>>4); quick_avalue=(voltage*1250)/100; sleep_dbg("MAX17040_QUICK LOW MSB [%d] : LSB [%d] : LOW VOLTAGE [%d]\n",msb,lsb,voltage); sleep_dbg("MAX17040_QUICK Adjusted [%d] : I2C Error Count [%d]\n",quick_avalue,i); if(i==MAX_READ) { printk("Re-running to check V-Cell!!!\n"); i = 0; continue; } else { mutex_lock(&max17040_data.data_mutex); max17040_data.quick_data.vcell_msb = msb; max17040_data.quick_data.vcell_lsb = lsb; max17040_data.quick_data.quick_vcell = quick_avalue; mutex_unlock(&max17040_data.data_mutex); completed = true; break; } } }
static ssize_t max17040_get_low_soc(struct device *dev, struct device_attribute *attr, char *buf) { int enable; sleep_dbg("max17040_get_low_soc START\n"); enable=max17040_data.soc; return sprintf(buf, "%d\n", enable); }
static int max17040_write_reg(u8 reg, u8 ahigh, u8 alow) { int ret; u8 buf[20]; buf[0]=reg; buf[1]=ahigh; buf[2]=alow; if ( max17040_data.client == NULL ) { sleep_dbg("%s : max17040.client is NULL\n", __func__); return -ENODEV; } mutex_lock(&max17040_data.i2c_mutex); ret = i2c_master_send(max17040_data.client, buf, 3); mutex_unlock(&max17040_data.i2c_mutex); if (ret<0) { dev_err(&max17040_data.client->dev, "%s couldn't write reg %d\n", __func__, ret); return -1; } else if (ret!=3) { dev_err(&max17040_data.client->dev, "%s couldn't write reg %d\n", __func__, ret); return -1; } else return ret; }
static ssize_t max17040_start_quickstart(struct device *dev, struct device_attribute *attr, char *buf) { int enable; sleep_dbg("QUICK START\n"); max17040_restart(); msleep(300); //quick start update time enable=max17040_data.quick_data.quick_state; return sprintf(buf, "%d\n", enable); }
static ssize_t max17040_get_low_voltage(struct device *dev, struct device_attribute *attr, char *buf) { int enable; sleep_dbg("max17040_get_low_voltage START\n"); max17040_restart(); msleep(300); //quick start update time enable=max17040_data.vcell; return sprintf(buf, "%d\n", enable); }
static int max17040_resume(struct i2c_client *client) { dbg_func_in(); if (max17040_data.slow_poll) { schedule_delayed_work(&max17040_data.work, 0); sleep_dbg("[RESUME] CONFIG FAST_POLL [The alarm is set for [%d] seconds]\n",FAST_POLL); } dbg_func_out(); return 0; }
static void max17040_quick_get_soc(void) { u8 msb=0; u8 lsb=0; int avalue=0; //unsigned long quick_soc; int i=0; bool completed = false; dbg_func_in(); while (!completed) { msb = max17040_read_reg(MAX17040_SOC_MSB); lsb = max17040_read_reg(MAX17040_SOC_LSB); if(msb < 0 || lsb < 0) { for(i=0;i<MAX_READ;i++) { msb = max17040_read_reg(MAX17040_SOC_MSB); lsb = max17040_read_reg(MAX17040_SOC_LSB); if(msb < 0 || lsb <0) { continue; } else break; } } /*//description read i2c data [msb=20,lsb=10] avalue=20*1000+(10*1000)/256 */ avalue=SKY_MULT_1000(msb)+(SKY_MULT_1000(lsb)/SKY_SOC_LSB); //Ajdusted soc%=(SOC%-EMPTY)/(FULL-EMPTY)*100 //logic code sleep_dbg("MAX17040_QUICK Adjusted SOC MSB [%d] : LSB [%d] : Adjusted SOC [%d] :Try Count [%d]\n",msb,lsb,avalue,i); if(i>=MAX_READ-1 || msb < 0 || lsb <0 ) { //Battery Bug Fixing Coded by Illustrious by Proto printk("Re-running to check Battery SoC!!!\n"); i = 0; continue; } else { mutex_lock(&max17040_data.data_mutex); max17040_data.quick_data.soc_msb=msb; max17040_data.quick_data.soc_lsb=lsb; max17040_data.quick_data.quick_soc=avalue; mutex_unlock(&max17040_data.data_mutex); completed = true; break; } } dbg_func_out(); }
static void max_battery_alarm_callback(struct alarm *alarm) { struct max17040_chip *di = container_of(alarm, struct max17040_chip, alarm); dbg_func_in(); sleep_dbg("MAX17040_ALARM_CALLBACK CALL.\n"); /*enable wake_lock*/ max17040_prevent_suspend(); /*schdule workqueue*/ queue_work(di->monitor_wqueue, &di->monitor_work); dbg_func_out(); }
static void max17040_quick_get_vcell(void) { u8 msb=0; u8 lsb=0; unsigned long quick_avalue; //unsigned long temp; unsigned long voltage=0; int i=0; msb = max17040_read_reg(MAX17040_VCELL_MSB); lsb = max17040_read_reg(MAX17040_VCELL_LSB); if(msb < 0 || lsb < 0) { for(i=0; i<MAX_READ; i++) { msb = max17040_read_reg(MAX17040_VCELL_MSB); lsb = max17040_read_reg(MAX17040_VCELL_LSB); if(msb < 0 || lsb <0) { continue; } else break; } } voltage=(msb<<4)|((lsb&0xf0)>>4); quick_avalue=(voltage*1250)/100; sleep_dbg("MAX17040_QUICK LOW MSB [%d] : LSB [%d] : LOW VOLTAGE [%d]\n",msb,lsb,(unsigned int)voltage); sleep_dbg("MAX17040_QUICK Adjusted [%d] : I2C Error Count [%d]\n",(unsigned int)quick_avalue,i); mutex_lock(&max17040_data.data_mutex); max17040_data.quick_data.vcell_msb = msb; max17040_data.quick_data.vcell_lsb = lsb; if(i==MAX_READ) max17040_data.quick_data.quick_vcell = 33975; else max17040_data.quick_data.quick_vcell = quick_avalue; mutex_unlock(&max17040_data.data_mutex); }
static u8 max17040_read_reg(u8 reg) { u8 ret_s,ret_r ,ret; u8 buf[20]; buf[0]=reg; mutex_lock(&max17040_data.i2c_mutex); ret_s = i2c_master_send(max17040_data.client, buf, 1); ret_r = i2c_master_recv(max17040_data.client, buf, 1); mutex_unlock(&max17040_data.i2c_mutex); if(ret_s<0 || ret_r<0) { sleep_dbg("max17040 I2C FILED ret [%d] [%d]\n",ret_s,ret_r); return -1; } else if(ret_s !=1 || ret_r !=1) { sleep_dbg("max17040 I2C FILED [%d] [%d] bytes transferred (expected 1)\n",ret_s,ret_r); return -1; } else ret=buf[0]; return ret; }
void max17040_batt_early_suspend(struct early_suspend *h) { dbg_func_in(); /* If we are on battery, reduce our update rate until * we next resume. */ /*ps2 team shs : Runs only when the cable is not connected.*/ max17040_data.online=sky_get_plug_state(); max17040_data.slow_poll = Early_suspend; if(!max17040_data.online) { sleep_dbg("[IMPORT]USB CABLE is not connected\n"); max17040_program_alarm_set(&max17040_data, SLOW_POLL); sleep_dbg("CONFIG SLOW_POLL [The alarm is set for [%d] seconds ]\n",SLOW_POLL); } else { sleep_dbg("[IMPORT]USB CABLE is connected\n"); max17040_program_alarm_set(&max17040_data, FAST_POLL); sleep_dbg("CONFIG SLOW_POLL [The alarm is set for [%d] seconds ]\n",FAST_POLL); } dbg_func_out(); }
static int max17040_check_restart( unsigned long avoltage, int soc ) { int i=0; //ps2 team shs : dont check charging mode unsigned long sky_low_soc=0; unsigned long sky_fuelgauge_ref_soc=0; unsigned long sky_high_soc=0; int high_soc=0; int low_soc=0; for( i = 0; i < COMPENSATION_MAX; i++ ) { if( avoltage >= sky_fuelgauge_linearlize_table[0][i].volt ) { mutex_lock(&max17040_data.quick_mutex); sky_high_soc = (avoltage - sky_fuelgauge_linearlize_table[0][i].offset)/sky_fuelgauge_linearlize_table[0][i].slop; sky_low_soc=(avoltage - sky_fuelgauge_linearlize_table[0][i].offset)%sky_fuelgauge_linearlize_table[0][i].slop; sky_fuelgauge_ref_soc = SKY_MULT_1000(sky_high_soc)+(SKY_MULT_1000(sky_low_soc)/sky_fuelgauge_linearlize_table[0][i].slop); high_soc=sky_fuelgauge_ref_soc + 30000; low_soc=sky_fuelgauge_ref_soc - 30000; mutex_unlock(&max17040_data.quick_mutex); //ps1 team shs : soc+20 > soc and soc < soc-20 and soc <=1 && ref_soc > 4 if( (soc > high_soc) || (soc < low_soc)|| ( (soc <= 1000) && (sky_fuelgauge_ref_soc > 4000) ) ) { max17040_data.quick_data.quick_state=i; sleep_dbg("[QUICK START] voltage : [%u]mv, soc : [%d], index [%d], sky_high_soc [%u] ,sky_low_soc [%u]\n",avoltage,soc,i,sky_high_soc,sky_low_soc); sleep_dbg("[QUICK START] ref_soc : [%u], high_soc : [%u], low_soc : [%d]\n",sky_fuelgauge_ref_soc,high_soc,low_soc); return 1; } break; } } max17040_data.quick_data.quick_state=-1; sleep_dbg("[QUICK DISABLE] voltage : [%u]mv, soc : [%d], index [%d], sky_high_soc [%u], sky_low_soc [%u] \n",avoltage,soc,i,sky_high_soc,sky_low_soc); sleep_dbg("[QUICK DISABLE] ref_soc : [%u], high_soc : [%u], low_soc : [%d]\n",sky_fuelgauge_ref_soc,high_soc,low_soc); return 0; }
void max17040_batt_late_resume(struct early_suspend *h) { dbg_func_in(); /* We might be on a slow sample cycle. If we're * resuming we should resample the battery state * if it's been over a minute since we last did * so, and move back to sampling every minute until * we suspend again. */ if (max17040_data.slow_poll) { max17040_program_alarm_set(&max17040_data, FAST_POLL); max17040_data.slow_poll = Early_resume; sleep_dbg("CONFIG FAST_POLL [The alarm is set for [%d] seconds]\n",FAST_POLL); } dbg_func_out(); }
static void max17040_set_rcomp(void) { int ret=0,i=0; ret=max17040_write_reg(MAX17040_RCOMP_MSB, 0xc0,0x00); if(ret<0) { for(i=0;i<MAX_READ;i++) { ret=max17040_write_reg(MAX17040_RCOMP_MSB, 0xc0,0x00); if(ret<0) continue; else break; } } sleep_dbg("MAX17040 SET_RCOMP TRY : [%d]\n",i); }
static void max17040_restart(void) { int ret=0,i=0; ret=max17040_write_reg(MAX17040_MODE_MSB, 0x40,0x00); if(ret<0) { for(i=0;i<MAX_READ;i++) { ret=max17040_write_reg(MAX17040_MODE_MSB, 0x40,0x00); if(ret<0) continue; else break; } } sleep_dbg("MAX17040 QUICK START TRY : [%d]\n",i); }
static void max17040_quick_get_soc(void) { u8 msb=0; u8 lsb=0; int avalue=0; //unsigned long quick_soc; int i=0; dbg_func_in(); msb = max17040_read_reg(MAX17040_SOC_MSB); lsb = max17040_read_reg(MAX17040_SOC_LSB); if(msb < 0 || lsb < 0) { for(i=0; i<MAX_READ; i++) { msb = max17040_read_reg(MAX17040_SOC_MSB); lsb = max17040_read_reg(MAX17040_SOC_LSB); if(msb < 0 || lsb <0) { continue; } else break; } } /*//description read i2c data [msb=20,lsb=10] avalue=20*1000+(10*1000)/256 */ avalue=SKY_MULT_1000(msb)+(SKY_MULT_1000(lsb)/SKY_SOC_LSB); //Ajdusted soc%=(SOC%-EMPTY)/(FULL-EMPTY)*100 //logic code sleep_dbg("MAX17040_QUICK Adjusted SOC MSB [%d] : LSB [%d] : Adjusted SOC [%d] :Try Count [%d]\n",msb,lsb,avalue,i); mutex_lock(&max17040_data.data_mutex); max17040_data.quick_data.soc_msb=msb; max17040_data.quick_data.soc_lsb=lsb; if(i==MAX_READ) max17040_data.quick_data.quick_soc=0; else max17040_data.quick_data.quick_soc=avalue; mutex_unlock(&max17040_data.data_mutex); dbg_func_out(); }
static void max17040_set_rcomp(void) { int ret=0,i=0; int chg_type; chg_type = atomic_read(&smb_charger_state); if((high_current_rcomp_mode == 1) && (chg_type == 0)){ ret = max17040_write_reg(MAX17040_RCOMP_MSB, 0x25,0x00); ret=max17040_write_reg(MAX17040_RCOMP_LSB, 0x1F,0x00); max17040_data.set_rcomp_mode = 1; } else { ret=max17040_write_reg(MAX17040_RCOMP_MSB, 0xC0,0x00); ret=max17040_write_reg(MAX17040_RCOMP_LSB, 0x1F,0x00); max17040_data.set_rcomp_mode = 0; } if(ret<0) { for(i=0;i<MAX_READ;i++) { if((high_current_rcomp_mode == 1) && (chg_type == 0)) { ret=max17040_write_reg(MAX17040_RCOMP_MSB, 0x65,0x00); ret=max17040_write_reg(MAX17040_RCOMP_LSB, 0x1F,0x00); } else { ret=max17040_write_reg(MAX17040_RCOMP_MSB, 0xC0,0x00); ret=max17040_write_reg(MAX17040_RCOMP_LSB, 0x1F,0x00); } if(ret<0) continue; else break; } } sleep_dbg("MAX17040 SET_RCOMP TRY : [%d]\n",i); }
static int max17040_suspend(struct i2c_client *client, pm_message_t state) { int time =0; int soc=max17040_data.soc; dbg_func_in(); /* If we are on battery, reduce our update rate until * we next resume. */ /*ps2 team shs : Runs only when the cable is not connected.*/ max17040_data.online=sky_get_plug_state(); max17040_data.slow_poll = Early_suspend; //ps1 team shs : cancel schedule_delayer_work cancel_delayed_work(&max17040_data.work); //ps1 team shs : set time time=max17040_sleep_time(soc); msm_pm_set_max_sleep_time((int64_t)((int64_t) time * NSEC_PER_SEC)); sleep_dbg("[SUSPEND] set time [%d] seconds : soc [%d] ]\n",time,soc); dbg_func_out(); return 0; }
static void max17040_work(struct work_struct *work) { #ifdef MAX17040_ALARM_RTC_ENABLE struct max17040_chip *di = container_of(work, struct max17040_chip, monitor_work); #else struct max17040_chip *di = container_of(work, struct max17040_chip, work.work); #endif //MAX17040_ALARM_RTC_ENABLE #ifdef MAX17040_ALARM_RTC_ENABLE unsigned long flags; #endif //MAX17040_ALARM_RTC_ENABLE int enable; static int first_enable = 1; dbg_func_in(); max17040_data.event=NoEvents; max17040_data.suspend_event=NoEvents; #ifndef MAX17040_ALARM_RTC_ENABLE // sleep_dbg("MAX17040_WORK CALL.\n"); //prevent suspend max17040_prevent_suspend(); #else // sleep_dbg("MAX17040_WORK RTC CALL.\n"); #endif //MAX17040_ALARM_RTC_ENABLE //read voltage now max17040_get_vcell(); //read soc max17040_get_soc(); #ifdef MAX17040_DEBUG_QUICK max17040_quick_get_value(); #endif enable = atomic_read(&max17040_data.set_test); //save volate now and soc [TEST APPLICATION] if(enable) { if((max17040_data.event)||first_enable) // ps2 team shs : soc is changed { sleep_dbg("MAX17040 SET TEST.\n"); sleep_dbg("MAX17040_WORK SOC [%d] prev[%d] : voltage [%d] : charger_state [%d] : i2c state [%d]\n",max17040_data.soc,max17040_data.prev_soc, max17040_data.vcell,charge_state,max17040_data.i2c_state); input_report_rel(max17040_data.max17040_input_data, REL_RX, max17040_data.vcell); input_report_rel(max17040_data.max17040_input_data, REL_RY, max17040_data.soc); input_report_rel(max17040_data.max17040_input_data, REL_RZ, enable); input_sync(max17040_data.max17040_input_data); if(first_enable) first_enable = 0; } } else first_enable = 1; //ps2 team shs : After you determine the value of voltage and soc If there are changes to the event generates. if(max17040_data.slow_poll) //do not call early resume state. { if(max17040_data.suspend_event)// 15 percent below where they were soc. { dbg("low battery [%d] percent!!!!!!!\n",max17040_data.soc); power_supply_changed(&di->battery); sleep_dbg("[SLEEP_EVENT] 15 percent below Send Event [%d].\n",max17040_data.soc ); } else //15 percent up where were soc. { power_supply_changed(&di->battery); sleep_dbg("[SLEEP_EVENT] 15 percent up Send Event [%d].\n",max17040_data.soc ); } } else //call early resume state. { if(max17040_data.event) //Different values soc. { sleep_dbg("MAX17040_WORK SOC [%d] prev[%d] : voltage [%d] : charger_state [%d] : i2c state [%d]\n",max17040_data.soc,max17040_data.prev_soc, max17040_data.vcell,charge_state,max17040_data.i2c_state); power_supply_changed(&di->battery); } else //same values soc. { dbg("[EVENT] Stop Event.\n"); } } #ifdef MAX17040_ALARM_RTC_ENABLE di->last_poll=alarm_get_elapsed_realtime(); /* prevent suspend before starting the alarm */ local_irq_save(flags); max17040_schedule(); max17040_allow_suspend(); local_irq_restore(flags); dbg_func_out(); #else max17040_data.slow_poll = Early_resume; max17040_allow_suspend(); schedule_delayed_work(&max17040_data.work, MAX17040_DELAY); #endif // MAX17040_ALARM_RTC_ENABLE }
static void max17040_work(struct work_struct *work) { #ifdef MAX17040_ALARM_RTC_ENABLE struct max17040_chip *di = container_of(work, struct max17040_chip, monitor_work); #else struct max17040_chip *di = container_of(work, struct max17040_chip, work.work); #endif //MAX17040_ALARM_RTC_ENABLE #ifdef CONFIG_SKY_SMB136S_CHARGER int thermal_time_check_count = 0; unsigned long pm_temp = 0; unsigned long pm_temp_sum = 0; unsigned long current_batt_delta = 0; unsigned long pre_batt_delta = 0; int batt_delta_sum = 0; int batt_delta = 0; int chg_type; #endif // unsigned long flags; int enable; dbg_func_in(); max17040_data.event=NoEvents; max17040_data.suspend_event=NoEvents; #ifndef MAX17040_ALARM_RTC_ENABLE // sleep_dbg("MAX17040_WORK CALL.\n"); //prevent suspend max17040_prevent_suspend(); #else // sleep_dbg("MAX17040_WORK RTC CALL.\n"); #endif //MAX17040_ALARM_RTC_ENABLE //read voltage now max17040_get_vcell(); //read soc max17040_get_soc(); #ifdef MAX17040_DEBUG_QUICK max17040_quick_get_value(); #endif enable = atomic_read(&max17040_data.set_test); //save volate now and soc [TEST APPLICATION] if(enable) { if(max17040_data.event) // soc is changed { pr_err("MAX17040 SET TEST.\n"); sleep_dbg("MAX17040_WORK SOC [%d] prev[%d] : voltage [%d] : charger_state [%d] : i2c state [%d]\n", max17040_data.soc,max17040_data.prev_soc, max17040_data.vcell,charge_state,max17040_data.i2c_state); input_report_abs(max17040_data.max17040_input_data, ABS_X, max17040_data.vcell); input_report_abs(max17040_data.max17040_input_data, ABS_Y, max17040_data.soc); input_report_abs(max17040_data.max17040_input_data, ABS_WAKE, enable); input_sync(max17040_data.max17040_input_data); } } //After you determine the value of voltage and soc If there are changes to the event generates. if(max17040_data.slow_poll) //do not call early resume state. { if(max17040_data.suspend_event)// 15 percent below where they were soc. { pr_err("low battery [%d] percent!!!!!!!\n",max17040_data.soc); power_supply_changed(&di->battery); pr_err("[SLEEP_EVENT] 15 percent below Send Event [%d].\n",max17040_data.soc ); } else //15 percent up where were soc. { power_supply_changed(&di->battery); pr_err("[SLEEP_EVENT] 15 percent up Send Event [%d].\n",max17040_data.soc ); } } else //call early resume state. { if(max17040_data.event) { //Different values soc. pr_err("MAX17040_WORK SOC [%d] prev[%d] : voltage [%d] : charger_state [%d] : i2c state [%d]\n", max17040_data.soc,max17040_data.prev_soc, max17040_data.vcell,charge_state,max17040_data.i2c_state); power_supply_changed(&di->battery); } else { //same values soc. //pr_err("[EVENT] Stop Event.\n"); } } if(max17040_raw_soc != max17040_raw_pre_soc) { pr_err("[SOC:%d->%d]\n", max17040_raw_pre_soc, max17040_raw_soc); /* if battery is fully charged, charging done*/ if(sky_get_plug_state() == 1 && (max17040_raw_pre_soc >= (CHARGING_DONE_THRESHOLD-5) && max17040_raw_soc >= CHARGING_DONE_THRESHOLD)) { notify_event_charging_done(); } /* if gauge falls below a threshold, recharging */ if(sky_get_plug_state() == 0 && (max17040_raw_pre_soc >= (RECHARGING_THRESHOLD-5) && max17040_raw_soc <= RECHARGING_THRESHOLD)) { notify_event_recharging(); } } #ifdef MAX17040_ALARM_RTC_ENABLE di->last_poll=alarm_get_elapsed_realtime(); /* prevent suspend before starting the alarm */ local_irq_save(flags); max17040_schedule(); max17040_allow_suspend(); local_irq_restore(flags); dbg_func_out(); #else #ifdef CONFIG_SKY_SMB136S_CHARGER chg_type = atomic_read(&smb_charger_state); pmic8058_tz_get_temp_charging(&pm_temp); if(thermal_time_check_count != 3) { pm_temp_sum = pm_temp_sum + pm_temp; current_batt_delta = pm_temp; if (pm_temp > pre_batt_delta) { batt_delta = pm_temp - pre_batt_delta; batt_delta_sum = batt_delta_sum + batt_delta; } else { batt_delta = 0; batt_delta_sum = batt_delta_sum + batt_delta; } pre_batt_delta = current_batt_delta; thermal_time_check_count ++; } else { if(chg_type == 0) { if(((pm_temp_sum > 114000) || (batt_delta_sum > 600 && pm_temp_sum > 84000)) && max17040_data.set_rcomp_mode == 0) { high_current_rcomp_mode = 1; max17040_set_rcomp(); } else { if(max17040_data.set_rcomp_mode == 1) { high_current_rcomp_mode = 0; max17040_set_rcomp(); } } } else { high_current_rcomp_mode = 0; max17040_set_rcomp(); } thermal_time_check_count = 0; pm_temp_sum = 0; batt_delta_sum = 0; } #endif max17040_data.slow_poll = Early_resume; max17040_allow_suspend(); schedule_delayed_work(&max17040_data.work, MAX17040_DELAY); #endif // MAX17040_ALARM_RTC_ENABLE }
static void max17040_work(struct work_struct *work) { #ifdef MAX17040_ALARM_RTC_ENABLE unsigned long flags; #endif //MAX17040_ALARM_RTC_ENABLE int enable; static int first_enable = 1; dbg_func_in(); max17040_data.event=NoEvents; max17040_data.suspend_event=NoEvents; #ifndef MAX17040_ALARM_RTC_ENABLE // sleep_dbg("MAX17040_WORK CALL.\n"); //prevent suspend max17040_prevent_suspend(); #else // sleep_dbg("MAX17040_WORK RTC CALL.\n"); #endif //MAX17040_ALARM_RTC_ENABLE //read voltage now max17040_get_vcell(); //read soc max17040_get_soc(); #ifdef MAX17040_DEBUG_QUICK max17040_quick_get_value(); #endif enable = atomic_read(&max17040_data.set_test); //save volate now and soc [TEST APPLICATION] if(enable) { if((max17040_data.event)||first_enable) // ps2 team shs : soc is changed { sleep_dbg("MAX17040 SET TEST.\n"); sleep_dbg("MAX17040_WORK SOC [%d] prev[%d] : voltage [%d] : charger_state [%d] : i2c state [%d]\n",max17040_data.soc,max17040_data.prev_soc, max17040_data.vcell,charge_state,max17040_data.i2c_state); input_report_rel(max17040_data.max17040_input_data, REL_RX, max17040_data.vcell); input_report_rel(max17040_data.max17040_input_data, REL_RY, max17040_data.soc); input_report_rel(max17040_data.max17040_input_data, REL_RZ, enable); input_sync(max17040_data.max17040_input_data); if(first_enable) first_enable = 0; } } else first_enable = 1; //ps2 team shs : After you determine the value of voltage and soc If there are changes to the event generates. if(max17040_data.slow_poll) //do not call early resume state. { if(max17040_data.suspend_event)// 15 percent below where they were soc. { dbg("low battery [%d] percent!!!!!!!\n",max17040_data.soc); max17040_power_supply_changed(); sleep_dbg("[SLEEP_EVENT] 15 percent below Send Event [%d].\n",max17040_data.soc ); } else //15 percent up where were soc. { max17040_power_supply_changed(); sleep_dbg("[SLEEP_EVENT] 15 percent up Send Event [%d].\n",max17040_data.soc ); } } else //call early resume state. { if(max17040_data.event) //Different values soc. { sleep_dbg("MAX17040_WORK SOC [%d] prev[%d] : voltage [%d] : charger_state [%d] : i2c state [%d]\n",max17040_data.soc,max17040_data.prev_soc, max17040_data.vcell,charge_state,max17040_data.i2c_state); max17040_power_supply_changed(); } else //same values soc. { dbg("[EVENT] Stop Event.\n"); } } #if defined(CONFIG_SKY_SMB136S_CHARGER) if(max17040_raw_soc != max17040_raw_pre_soc) { pr_err("[SOC:%d->%d]\n", max17040_raw_pre_soc, max17040_raw_soc); /* if battery is fully charged, charging done*/ if(sky_get_plug_state() == 1 && (max17040_raw_pre_soc >= (CHARGING_DONE_THRESHOLD-5) && max17040_raw_soc >= CHARGING_DONE_THRESHOLD)) { notify_event_charging_done(); } /* if gauge falls below a threshold, recharging */ if(sky_get_plug_state() == 0 && (max17040_raw_pre_soc >= (RECHARGING_THRESHOLD-5) && max17040_raw_soc <= RECHARGING_THRESHOLD)) { notify_event_recharging(); } } #endif #ifdef MAX17040_ALARM_RTC_ENABLE di->last_poll=alarm_get_elapsed_realtime(); /* prevent suspend before starting the alarm */ local_irq_save(flags); max17040_schedule(); max17040_allow_suspend(); local_irq_restore(flags); dbg_func_out(); #else max17040_data.slow_poll = Early_resume; max17040_allow_suspend(); schedule_delayed_work(&max17040_data.work, MAX17040_DELAY); #endif // MAX17040_ALARM_RTC_ENABLE }
static void max17040_get_soc(void) { u8 msb; u8 lsb; int avalue=0; int soc=0; #ifdef MAX17040_SLEEP_DEBUG int sky_state=0; #endif dbg_func_in(); msb = max17040_read_reg(MAX17040_SOC_MSB); lsb = max17040_read_reg(MAX17040_SOC_LSB); //check i2c error if(msb<0 ||lsb <0) { max17040_data.i2c_state =1; } else { max17040_data.i2c_state =0; max17040_data.prev_soc=max17040_data.soc; } #ifdef MAX17040_DEBUG_QUICK //quick start code soc=SKY_MULT_1000(msb)+(SKY_MULT_1000(lsb)/SKY_SOC_LSB); soc=soc/1000; #else /*//description read i2c data [msb=20,lsb=10] avalue=20*1000+(10*1000)/256 */ avalue=SKY_MULT_1000(msb)+(SKY_MULT_1000(lsb)/SKY_SOC_LSB); //Ajdusted soc%=(SOC%-EMPTY)/(FULL-EMPTY)*100 if(avalue>1200) soc=(((avalue-SKY_MULT_100(SKY_SOC_EMPTY))*100)/(SKY_MULT_100(SKY_SOC_FULL)-SKY_MULT_100(SKY_SOC_EMPTY))); else soc=0; if(avalue >1000 && avalue <1200) soc=1; #endif //logic code if(soc>100) //soc>100 soc=100; if(soc==100) charge_state=1; else charge_state=0; #ifdef CONFIG_SKY_CHARGING if(pm8058_chg_nobattery_factory_cable()) soc = 10; #endif if(max17040_data.event) // ps2 team shs : soc is changed { sleep_dbg("CONFIG CAPACITY [%d] : BATTERY STATS : [%d]\n",soc,sky_state); sleep_dbg("SOC MSB [%d] : LSB [%d] : Lower SOC [%d] : Adjusted SOC [%d] : charge_state [%d] \n",msb,lsb,avalue,soc,charge_state); } if(soc!=max17040_data.soc) max17040_data.event=Events; if(soc==0)//ps1 team shs : 0% persent is occured events max17040_data.event=Events; max17040_check_power(soc); mutex_lock(&max17040_data.data_mutex); max17040_data.soc = soc; mutex_unlock(&max17040_data.data_mutex); dbg_func_out(); }
static void max17040_quick_get_value(void) { u8 rcomp=0, rcomp_low; sleep_dbg("\n=======================================================================\n"); sleep_dbg("[INFORMATION] QUICK START STATE [%d]\n",max17040_data.quick_data.quick_state); sleep_dbg("[INFORMATION] QUICK START SOC_MSB [%d]\n",max17040_data.quick_data.soc_msb); sleep_dbg("[INFORMATION] QUICK START SOC_LSB [%d]\n",max17040_data.quick_data.soc_lsb); sleep_dbg("[INFORMATION] QUICK START SOC [%d]\n",max17040_data.quick_data.quick_soc); sleep_dbg("[INFORMATION] QUICK START REFERENSE SOC [%d]\n",sky_fuelgauge_ref_soc); sleep_dbg("[INFORMATION] QUICK START VCELL_MSB [%d]\n",max17040_data.quick_data.vcell_msb); sleep_dbg("[INFORMATION] QUICK START VCELL_LSB [%d]\n",max17040_data.quick_data.vcell_lsb); sleep_dbg("[INFORMATION] QUICK START VOLTAGE [%d]\n",max17040_data.quick_data.quick_vcell); rcomp=max17040_read_reg(MAX17040_RCOMP_MSB); rcomp_low=max17040_read_reg(MAX17040_RCOMP_LSB); sleep_dbg("[INFORMATION] RCOMP 0x[%x][%x]\n",rcomp,rcomp_low); sleep_dbg("\n=======================================================================\n"); }
static int __devinit max17040_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct input_dev *input_data = NULL; int ret; #if 0 int aflag=0; #endif sleep_dbg("[MAX17040] max17040_probe [IN]\n"); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) return -EIO; max17040_data.client = client; i2c_set_clientdata(client, &max17040_data); //sys file system are registered max17040_data.battery.name = "batterys"; max17040_data.battery.type = POWER_SUPPLY_TYPE_BATTERY; max17040_data.battery.get_property = max17040_get_property; max17040_data.battery.properties = max17040_battery_props; max17040_data.battery.external_power_changed = max17040_bat_external_power_changed; max17040_data.battery.num_properties = ARRAY_SIZE(max17040_battery_props); ret = power_supply_register(&client->dev, &max17040_data.battery); if (ret) { sleep_dbg("[MAX17040] failed: power supply register [ERROR]\n"); i2c_set_clientdata(client, NULL); return ret; } //The code used in the test mode [TEST MODE] ret = sysfs_create_group(&client->dev.kobj, &max17040_attr_group); if (ret) { sleep_dbg("[MAX17040] failed: sysfs_create_group [ERROR]\n"); } //mutex is init mutex_init(&max17040_data.data_mutex); mutex_init(&max17040_data.i2c_mutex); mutex_init(&max17040_data.quick_mutex); //rcomp is set max17040_set_rcomp(); //Version of reading max17040_get_version(); //read vell and soc max17040_quick_get_vcell(); max17040_quick_get_soc(); #if 0 //check quick start aflag=max17040_check_restart(max17040_data.quick_data.quick_vcell,max17040_data.quick_data.quick_soc); if(aflag) { max17040_restart(); msleep(300); //quick start update time } #endif //The code used in the test mode [TEST MODE] atomic_set(&max17040_data.set_test, 0); input_data = input_allocate_device(); if (!input_data) { sleep_dbg("MAX17040: Unable to input_allocate_device \n"); return -1; } set_bit(EV_REL,input_data->evbit); input_set_capability(input_data, EV_REL, REL_RX); input_set_capability(input_data, EV_REL, REL_RY); /* wake */ input_set_capability(input_data, EV_REL, REL_RZ); /* wake */ input_data->name="max17040"; ret =input_register_device(input_data); if (ret) { sleep_dbg("MAX17040: Unable to register input_data device\n"); return -1; } input_set_drvdata(input_data, &max17040_data); max17040_data.max17040_input_data=input_data; //initialize workqueue and alarm setting wake_lock_init(&max17040_data.work_wake_lock, WAKE_LOCK_SUSPEND, "max17040-battery"); #ifdef MAX17040_ALARM_RTC_ENABLE max17040_data.last_poll=alarm_get_elapsed_realtime(); INIT_WORK(&max17040_data.monitor_work, max17040_work); max17040_data.monitor_wqueue = create_freezeable_workqueue("max17040"); /* init to something sane */ if (!max17040_data.monitor_wqueue) { sleep_dbg("fail_workqueue Error [PROBE FUNCTION]"); return -1; } alarm_init(&max17040_data.alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, max_battery_alarm_callback); //prevent suspend max17040_prevent_suspend(); #ifdef CONFIG_HAS_EARLYSUSPEND max17040_data.early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; max17040_data.early_suspend.suspend = max17040_batt_early_suspend; max17040_data.early_suspend.resume = max17040_batt_late_resume; dbg("set max17040 EARLY_SUSPEND\n"); register_early_suspend(&max17040_data.early_suspend); #endif //CONFIG_HAS_EARLYSUSPEND queue_work(max17040_data.monitor_wqueue, &max17040_data.monitor_work); #else INIT_DELAYED_WORK_DEFERRABLE(&max17040_data.work, max17040_work); schedule_delayed_work(&max17040_data.work, 0); #endif //MAX17040_ALARM_RTC_ENABLE sleep_dbg("[MAX17040] max17040_probe [OUT]\n"); return 0; }