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);
    }
}
예제 #2
0
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{