void summit_fsm_doAction(struct summit_smb347_info *di,int event) { int state=di->current_state; int temp=0; u32 value; int config,command=0; u8 pre_protect_event=0; switch (state){ case STATE_SUSPEND: if(event==USB_EVENT_NONE){ di->usb_online=0; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); summit_charge_reset(di); /* * Turn off LEDs when USB is unplugged, * this is safe when the battery is already * discharging or full. There's no way * the battery is being charged when USB * is not connected. */ omap4430_green_led_set(NULL, 0); omap4430_orange_led_set(NULL, 0); CLEAR_BAT_FULL(di->protect_event); //enable low battery interrupt summit_enable_stat_interrupt(di,LOW_BATTERY_TRIGGER_IRQ); /* * Hold the wake lock, and schedule a delayed work * to release it in 1 second */ wake_lock(&di->chrg_lock); schedule_delayed_work(&di->disconnect_work, msecs_to_jiffies(1000)); } break; break; case STATE_INIT: if(event==USB_EVENT_DETECT_SOURCE){ /* * Cancel the scheduled delayed work that * releases the wakelock */ cancel_delayed_work_sync(&di->disconnect_work); di->fake_disconnect=0; if(di->mbid!=0){ temp=-1; config=i2c_smbus_read_byte_data(di->client,SUMMIT_SMB347_STAT_TIMERS); if(IS_BIT_CLEAR(config,5)){//The detect need to be redo again. dev_info(di->dev,"Redo apsd\n"); //disable stat summit_write_config(di,1); config=i2c_smbus_read_byte_data(di->client,SUMMIT_SMB347_STAT_TIMERS); SET_BIT(config,5); i2c_smbus_write_byte_data(di->client,SUMMIT_SMB347_STAT_TIMERS,config); summit_write_config(di,0); summit_config_apsd(di,0); summit_config_apsd(di,1); queue_delayed_work_on(0,summit_work_queue,&di->summit_check_work,msecs_to_jiffies(2000)); }else{//The detect has already done in u-boot dev_info(di->dev,"The detect has already done in u-boot\n"); temp=summit_get_apsd_result(di); writeIntoCBuffer(&di->events,temp); queue_delayed_work_on(0,summit_work_queue,&di->summit_monitor_work,0); } } summit_charger_reconfig(di); summit_config_time_protect(di,1); //reload the protection setting if(IS_ADJUST_CURRENT_VOLTAGE_ENABLE(di->protect_enable) && di->mbid>=4){ summit_adjust_charge_current(di,event); } if(pre_protect_event!=di->protect_event && di->mbid>=4){ summit_protection(di); } } if(event==EVENT_APSD_COMPLETE){ writeIntoCBuffer(&di->events,summit_get_apsd_result(di)); queue_delayed_work_on(0,summit_work_queue,&di->summit_monitor_work,0); } break; case STATE_ONDEMAND: summit_charge_reset(di); break; case STATE_PC: if(event==EVENT_DETECT_PC){ blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_VBUS, di->xceiv->gadget); di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; case STATE_CD: if(event==USB_EVENT_HOST_CHARGER){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); } di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_VBUS, di->xceiv->gadget); } break; case STATE_PC_100: summit_switch_mode(di,USB1_OR_15_MODE); di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); break; //summit bug: if enable charge,then vbus always exits. case STATE_PC_500: if(event==USB_EVENT_LIMIT_500){ summit_switch_mode(di,USB5_OR_9_MODE); if(di->mbid==0){//summit bug: if enable charge,then vbus always exits. if((di->protect_enable==1 && di->protect_event==0) || di->protect_enable==0) summit_charge_enable(di,1); } di->usb_online=1; di->ac_online=0; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; case STATE_OTHER://It will switch to usb5 mode,so need to switch hc mode. if(event==EVENT_DETECT_OTHER){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); if((di->protect_enable==1 && di->protect_event==0) || di->protect_enable==0) summit_charge_enable(di,1); }else{ summit_write_config(di,1); config=i2c_smbus_read_byte_data(di->client,SUMMIT_SMB347_ENABLE_CONTROL); command&=~(0x1<<(4)); i2c_smbus_write_byte_data(di->client,SUMMIT_SMB347_ENABLE_CONTROL,config); summit_write_config(di,0); summit_switch_mode(di,HC_MODE); } di->usb_online=0; di->ac_online=1; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } //Some PC get a usb port that was detected by Other charger //if(event==EVENT_AICL_COMPLETE) // blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_VBUS, di->xceiv->gadget); break; case STATE_DC: if(event==USB_EVENT_CHARGER){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); } di->usb_online=0; di->ac_online=1; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; case STATE_UC: if(event==EVENT_DETECT_TBD){ if(di->mbid==0){ summit_switch_mode(di,HC_MODE); if((di->protect_enable==1 && di->protect_event==0) || di->protect_enable==0) summit_charge_enable(di,1); } di->usb_online=0; di->ac_online=1; power_supply_changed(&di->usb); power_supply_changed(&di->ac); } break; } pre_protect_event=di->protect_event; switch(event){ case EVENT_FULL_BATTERY: SET_BAT_FULL(di->protect_event); break; case EVENT_RECHARGE_BATTERY: CLEAR_BAT_FULL(di->protect_event); break; case EVENT_BATTERY_I2C_ERROR: SET_BAT_I2C_FAIL(di->protect_event); break; case EVENT_BATTERY_I2C_NORMAL: CLEAR_BAT_I2C_FAIL(di->protect_event); break; case EVENT_NOT_RECOGNIZE_BATTERY: SET_BAT_NOT_RECOGNIZE(di->protect_event); break; case EVENT_RECOGNIZE_BATTERY: CLEAR_BAT_NOT_RECOGNIZE(di->protect_event); break; case EVENT_BATTERY_NTC_ZERO: SET_BAT_NTC_ERR(di->protect_event); break; case EVENT_BATTERY_NTC_NORMAL: CLEAR_BAT_NTC_ERR(di->protect_event); break; case EVENT_WEAK_BATTERY: SET_BAT_TOO_WEAK(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_2:// -20 < temp < 0 Stop Charge SET_BAT_TOO_COLD_FOR_CHARGE(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_1:// temp < -20 Stop Discharge SET_BAT_TOO_COLD_FOR_DISCHARGE(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_8:// 60 > temp SET_BAT_TOO_HOT_FOR_CHARGE(di->protect_event); break; case EVENT_TEMP_PROTECT_STEP_3: case EVENT_TEMP_PROTECT_STEP_4: case EVENT_TEMP_PROTECT_STEP_5: case EVENT_TEMP_PROTECT_STEP_6: case EVENT_TEMP_PROTECT_STEP_7: CLEAR_BAT_TOO_COLD_FOR_CHARGE(di->protect_event); CLEAR_BAT_TOO_COLD_FOR_DISCHARGE(di->protect_event); CLEAR_BAT_TOO_HOT_FOR_CHARGE(di->protect_event); di->bat_thermal_step=event; if(IS_ADJUST_CURRENT_VOLTAGE_ENABLE(di->protect_enable) && di->mbid>=4){ summit_adjust_charge_current(di,event); } break; } if( (pre_protect_event!=di->protect_event && di->mbid>=4 ) || (event==EVENT_RECHECK_PROTECTION)){ if(event==EVENT_RECHECK_PROTECTION) summit_adjust_charge_current(di,di->bat_thermal_step); summit_protection(di); }else if(di->mbid<4){ summit_charge_enable(di,1); } }
void check_low_bat() { u16 v = 0, cap = 0; s16 t = 0; int power_source=0; int input_limit=0; int voltage=0; int capacity=0; int temperature=0; int ms=0; int sec=0; int mbid=0; int value=0; //turn off the phy __raw_writel(0x100, 0x4A0093E0); //disable ocp2scp_usb_phy_ick __raw_writel(0x30000, 0x4A0093E0); //disable ocp2scp_usb_phy_phy_48m __raw_writel(0x0, 0x4A008640); //disable usb_phy_cm_clk32k __raw_writel(1, 0x4A002300); //power down the usb phy mbid=get_mbid(); if(mbid!=0){ __raw_writel(0x40000000,0x4a100620); //disable the detect charger fuction } bq27541_temperature(&t); temperature = t; bq27541_voltage(&v); voltage = v; bq27541_capacity(&cap); capacity = cap; printf("Battery capacity =%d voltage=%d temperature=%d\n",capacity,voltage,temperature); //Temperature protect if( (temperature>TEMPERATURE_HOT_LIMIT) || (temperature<TEMPERATURE_COLD_LIMIT)){ printf("shutdown due to temperature protect %d\n",temperature); twl6030_shutdown(); } if( (voltage < LOW_BATTERY_VOLTAGE_LIMIT) || (capacity < LOW_BATTERY_CAPACITY_LIMIT)){ //Prepare to display the low battery message. if(twl6030_get_vbus_status()){ run_command("setgreenled 0", 0); run_command("setamberled 5", 0); //enable the VUSB 3.3 V twl6030_disable_vusb(); twl6030_init_vusb(); g_smb_address = SUMMIT_SMB347_I2C_ADDRESS; if (smb347_i2c_read_u8(&value,SUMMIT_SMB347_SLAVE_ADDR) != 0){ g_smb_address = SUMMIT_SMB347_I2C_ADDRESS_SECONDARY; if (smb347_i2c_read_u8(&value,SUMMIT_SMB347_SLAVE_ADDR) != 0){ goto LOW_BAT_TURN_OFF; } else { value = value >> 1; if(value != SUMMIT_SMB347_I2C_ADDRESS_SECONDARY) goto LOW_BAT_TURN_OFF; } }else{ value = value >> 1; if(value != SUMMIT_SMB347_I2C_ADDRESS) goto LOW_BAT_TURN_OFF; } summit_write_config(1); //enable charge time out smb347_i2c_read_u8(&value,SUMMIT_SMB347_STAT_TIMERS); //enable Pre-charge Timeout 48 min CLEAR_BIT(value,1);CLEAR_BIT(value,0); //enable complete charge timeout 1527 min CLEAR_BIT(value,2);SET_BIT(value,3); smb347_i2c_write_u8(value,SUMMIT_SMB347_STAT_TIMERS); /*reset the charge current to maximum*/ smb347_i2c_write_u8(kc1_chargerdetect_setting_pvt[0],0); summit_write_config(0); //Detect the power source if(mbid==0){//EVT 1.0 DETECT_BY_PHY printf("DETECT_BY_PHY\n"); power_source=detect_usb(); }else{//DETECT_BY_CHARGER printf("DETECT_BY_CHARGER\n"); //check is this first boot? smb347_i2c_read_u8(&value,SUMMIT_SMB347_STAT_TIMERS); if(IS_BIT_CLEAR(value,5)){//FIRST BOOT printf("FIRST BOOT\n"); //disable stat summit_write_config(1); SET_BIT(value,5); smb347_i2c_write_u8(value,SUMMIT_SMB347_STAT_TIMERS); summit_write_config(0); //redo the apsd summit_config_apsd(0); summit_config_apsd(1); } power_source=summit_detect_usb(); if(power_source==NO_VBUS) goto LOW_BAT_TURN_OFF; if(power_source==2){ if(mbid==0){ //Need to fixed,this is bug of summit summit_switch_mode(USB5_OR_9_MODE); summit_init(mbid); summit_charge_enable(1); } /* Enter low battery charge loop */ low_bat_charge(); if(mbid==0) summit_charge_enable(0); }else if(power_source==3||power_source==1){ if(mbid==0){ summit_switch_mode(HC_MODE); summit_init(mbid); summit_charge_enable(1); } if(mbid>=4){ //For DVT input_limit=summit_is_aicl_complete(); if(input_limit==NO_VBUS) goto LOW_BAT_TURN_OFF; printf("Power:AICL=%d mA\n",input_limit); /* Enter low battery charge loop */ //if(input_limit>0 && input_limit<=900) low_bat_charge(); } } } }else{