예제 #1
0
void battery_callback()
{
	if (!charging_allowed)
		return;

	adc_configure(&batt_adc_config);
    BATTERY_VOLTAGE_TRIS = 1;
	BATTERY_VOLTAGE_DIGITAL = 0;

    adc_set_channel(1);
    last_battery_voltage = adc_convert_one();

    //Disable charging if battery voltage is greater than max charge level
    if (last_battery_voltage >= kBatteryChargedLevel)
    	disable_charging();
    else if (last_battery_voltage < kBatteryHysteresisLevel) //Reenable charging once battery level falls below hysteresis
    	enable_charging();
}
예제 #2
0
static void change_charge_status(int status)
{

	switch (status) {
	case POWER_SUPPLY_STATUS_UNKNOWN:
	case POWER_SUPPLY_STATUS_NOT_CHARGING:
	case POWER_SUPPLY_STATUS_DISCHARGING:
		if (sec_bci->battery.battery_health != POWER_SUPPLY_HEALTH_DEAD)
			disable_charging();

#ifdef HIGH_TEMP_GAURD_FOR_CAMCORDER
		sec_bci->charger.camera_recording_inout = 0;
#endif
		break;

	case POWER_SUPPLY_STATUS_FULL:
		break;

	case POWER_SUPPLY_STATUS_FULL_END:
		sec_bci->charger.rechg_count = 4;
		/*Cancel timer */
		clear_charge_start_time();

		disable_charging();
		break;
		
	case POWER_SUPPLY_STATUS_CHARGING:

		if (sec_bci->battery.battery_vf_ok) {
			sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_GOOD;

			/*Start monitoring charging time */
			set_charge_start_time();

			enable_charging();
			break;

		} else {
			sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_DEAD;

			status = POWER_SUPPLY_STATUS_DISCHARGING;

			printk( KERN_INFO "[TA] INVALID BATTERY, %d !! \n", status);

			disable_charging();
			break;

		}

	case POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL:
		/*Start monitoring charging time */
		sec_bci->charger.charging_timeout = DEFAULT_RECHARGING_TIMEOUT;
		set_charge_start_time();

		enable_charging();

		break;

	case POWER_SUPPLY_STATUS_RECHARGING_FOR_TEMP:
		enable_charging();
		break;

	default:
		;
	}

	sec_bci->charger.prev_charge_status = sec_bci->charger.charge_status;
	sec_bci->charger.charge_status = status;

	_charger_state_change_(STATUS_CATEGORY_CHARGING, status);

}
예제 #3
0
int _battery_state_change_(int category, int value)
{
	struct charger_device_info *di;
	struct platform_device *pdev;

	int state;

	pdev = to_platform_device(this_dev);
	di = platform_get_drvdata(pdev);


	printk( KERN_INFO "[TA] cate: %d, value: %d, %s\n", category, value, di->dev->kobj.name );
	switch (category) {
	case STATUS_CATEGORY_TEMP:
		switch (value) {
		case BATTERY_TEMPERATURE_NORMAL:
			printk( KERN_INFO "[TA] Charging re start normal TEMP!!\n");
			change_charge_status(POWER_SUPPLY_STATUS_RECHARGING_FOR_TEMP);
			break;
	
		case BATTERY_TEMPERATURE_LOW:
			printk( KERN_INFO "[TA] Charging stop LOW TEMP!!\n");
			change_charge_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
			break;

		case BATTERY_TEMPERATURE_HIGH:
			printk( KERN_INFO "[TA] Charging stop HI TEMP!!\n");
			change_charge_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
			break;

#ifdef HIGH_TEMP_GAURD_FOR_CAMCORDER
		case BATTERY_TEMPERATURE_ETC:
			if(sec_bci->charger.camera_recording 
			   && sec_bci->charger.camera_recording_inout){
				printk( KERN_INFO "[TA] Charger is set to the USB mode\n");
				state = sec_bci->charger.cable_status;
				sec_bci->charger.cable_status = POWER_SUPPLY_TYPE_USB;
				enable_charging();
				sec_bci->charger.cable_status = state;
				break;
			} else {
				printk( KERN_INFO "[TA] Charger is set to the original mode\n");
				enable_charging();
				break;
			}
#endif

		default:
			break;
		}

		break;

	case STATUS_CATEGORY_CHARGING:
		switch (value) {
		case POWER_SUPPLY_STATUS_FULL:
			printk( KERN_INFO "[TA] Charge FULL(#1)! (monitoring charge current)\n");
			change_charge_status(POWER_SUPPLY_STATUS_FULL);
			break;

		case POWER_SUPPLY_STATUS_FULL_END:
			printk( KERN_INFO "[TA] Charge FULL(#2)! (monitoring charge current)\n");
			change_charge_status(POWER_SUPPLY_STATUS_FULL_END);
			break;

		case POWER_SUPPLY_STATUS_CHARGING_OVERTIME:
			printk( KERN_INFO "[TA] CHARGING TAKE OVER 6 hours !!\n");
			change_charge_status(POWER_SUPPLY_STATUS_FULL_END);
			break;

		case POWER_SUPPLY_STATUS_FULL_DUR_SLEEP:
			printk( KERN_INFO "[TA] Charge FULL!\n");
			change_charge_status(POWER_SUPPLY_STATUS_FULL);
			break;

		case POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL:
			printk( KERN_INFO "[TA] Re-Charging Start!!\n");
			change_charge_status(POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL);
			break;

		default:
			break;
		}

		break;

	case STATUS_CATEGORY_ETC:
		switch (value) {
			case ETC_CABLE_IS_DISCONNECTED:
			printk( KERN_INFO "[TA] CABLE IS NOT CONNECTED.... Charge Stop!!\n");
			change_cable_status(POWER_SUPPLY_TYPE_BATTERY, di);
			break;

		default:
			break;
		}

		break;

	default:
		printk( KERN_INFO "[TA] Invalid category!!!!!\n");
		break;
	}

	return 0;
}
예제 #4
0
void charger_task(void)
{
	int next_state;
	int wait_time = T1_USEC;
	timestamp_t pre_chg_start = get_time();

	pmu_init();

	/* Enable low current charging */
	pmu_low_current_charging(1);

	/* Enable charger interrupt */
	gpio_enable_interrupt(GPIO_CHARGER_INT_L);

	/*
	 * EC STOP mode support
	 *   The charging loop can be stopped in idle state with AC unplugged.
	 *   Charging loop will be resumed by TPSCHROME interrupt.
	 */
	enable_charging(0);
	disable_sleep(SLEEP_MASK_CHARGING);

	while (1) {
		last_waken = get_time();
		pmu_clear_irq();

#ifdef CONFIG_PMU_TPS65090_CHARGING_LED
		update_battery_led();
#endif
		/*
		 * When battery is extremely low, the internal voltage can not
		 * power on its gas guage IC. Charging loop will enable the
		 * charger and turn on trickle charging. For safty reason,
		 * charger should be disabled if the communication to battery
		 * failed.
		 */
		if (current_state == ST_PRE_CHARGING &&
		    get_time().val - pre_chg_start.val >= PRE_CHARGING_TIMEOUT)
			next_state = ST_CHARGING_ERROR;
		else
			next_state = calc_next_state(current_state);

		if (next_state != current_state) {
			/* Reset state of charge moving average window */
			rsoc_moving_average(-1);

			CPRINTS("batt state %s -> %s",
				state_list[current_state],
				state_list[next_state]);

			current_state = next_state;

			switch (current_state) {
			case ST_PRE_CHARGING:
				pre_chg_start = get_time();
				/* Fall through */
			case ST_CHARGING:
				if (pmu_blink_led(0))
					next_state = ST_CHARGING_ERROR;
				else
					enable_charging(1);
				break;
			case ST_CHARGING_ERROR:
				/*
				 * Enable hardware charging circuit after set
				 * PMU to hardware error state.
				 */
				if (pmu_blink_led(1))
					enable_charging(0);
				else
					enable_charging(1);
				break;
			case ST_IDLE:
			case ST_IDLE0:
			case ST_BAD_COND:
			case ST_DISCHARGING:
				enable_charging(0);
				/* Ignore charger error when discharging */
				pmu_blink_led(0);
				break;
			}
		}

		switch (current_state) {
		case ST_CHARGING:
		case ST_CHARGING_ERROR:
			wait_time = T2_USEC;
			break;
		case ST_DISCHARGING:
			wait_time = T3_USEC;
			break;
		case ST_PRE_CHARGING:
			wait_time = T1_USEC;
			if (get_time().val - pre_chg_start.val >=
			    PRE_CHARGING_TIMEOUT)
				enable_charging(0);
			break;
		default:
			if (extpower_is_present()) {
				wait_time = T1_USEC;
				break;
			} else if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) {
				wait_time = T1_OFF_USEC;
				enable_sleep(SLEEP_MASK_CHARGING);
			} else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) {
				wait_time = T1_SUSPEND_USEC;
			} else {
				wait_time = T1_USEC;
			}
		}

		if (!has_pending_event) {
			task_wait_event(wait_time);
			disable_sleep(SLEEP_MASK_CHARGING);
		} else {
			has_pending_event = 0;
		}
	}
}
예제 #5
0
static bool check_battery_vf( void )
{
	int count = 0;
	int val;
	bool ret = false;

#if 0
	count = 0;
	disable_charging( CHARGE_DUR_ACTIVE );
	msleep( 100 );
	enable_charging( CHARGE_DUR_ACTIVE );
	val = gpio_get_value( KCHG_ING_GPIO );
	if ( !val )
		return true;
	
	while ( count < 10 )
	{
		if ( !gpio_get_value( KCHG_ING_GPIO ) )
			return true;

		count++;
		msleep( 1 );
	}

	if ( !ret && device_config->VF_CHECK_USING_ADC )
	{
#if 0
		int i;
		int val[5];
		for ( i = 0; i < 5 ; i++ )
		{
			val[i] = _get_t2adc_data_( device_config->VF_ADC_PORT );
		}

		count = _get_average_value_( val, 5 );
#else
		count = _get_t2adc_data_( device_config->VF_ADC_PORT );
#endif
		
		printk("vf: %d\n", count);
		if ( count < 100 )
			return true;
	}
	
	disable_charging( CHARGE_DUR_ACTIVE );
#elif 0
	if ( device_config->VF_CHECK_USING_ADC )
	{
		int i;
		int val[5];
		
		for ( i = 0; i < 5 ; i++ )
		{
			val[i] = _get_t2adc_data_( device_config->VF_ADC_PORT );
			if ( val[i] >= 100 )
			{
				printk( "vf: %d\n", val[i] );
				return false;
			}
			msleep( 100 );
		}

		count = _get_average_value_( val, 5 );
		printk("vf: %d\n", count);
		if ( count < 100 )
			return true;
		
/*		count = _get_t2adc_data_( device_config->VF_ADC_PORT );		
		printk("vf: %d\n", count);
		if ( count < 100 )
			return true;*/
	}
	else
	{
		count = 0;
		disable_charging( CHARGE_DUR_ACTIVE );
		msleep( 100 );
		enable_charging( CHARGE_DUR_ACTIVE );
		val = gpio_get_value( KCHG_ING_GPIO );
		if ( !val )
			return true;
		
		while ( count < 10 )
		{
			if ( !gpio_get_value( KCHG_ING_GPIO ) )
				return true;

			count++;
			msleep( 1 );
		}

		disable_charging( CHARGE_DUR_ACTIVE );

	}
#else
	count = 0;
	disable_charging( CHARGE_DUR_ACTIVE );
	msleep( 100 );
	enable_charging( CHARGE_DUR_ACTIVE );
	val = gpio_get_value( KCHG_ING_GPIO );
	if ( !val )
	{
		ret = true;
	}
	
	while ( count < 10 )
	{
		if ( !gpio_get_value( KCHG_ING_GPIO ) )
		{
			ret = true;
			break;
		}

		count++;
		msleep( 1 );
	}

	disable_charging( CHARGE_DUR_ACTIVE );

	if ( !ret &&  device_config->VF_CHECK_USING_ADC )
	{
		int i;
		int val[5];
		
		for ( i = 0; i < 5 ; i++ )
		{
			val[i] = _get_t2adc_data_( device_config->VF_ADC_PORT );
			msleep( 100 );
		}

		count = _get_average_value_( val, 5 );
		printk("vf: %d\n", count);
		if ( count < 200)
			return true;
	}

#endif
	return ret;
}
예제 #6
0
static void change_charge_status( int status, bool is_sleep )
// ----------------------------------------------------------------------------
// Description    : 
// Input Argument :  
// Return Value   : 
{

	switch ( status )
	{
	case POWER_SUPPLY_STATUS_UNKNOWN :
	case POWER_SUPPLY_STATUS_DISCHARGING :
	case POWER_SUPPLY_STATUS_NOT_CHARGING :
		disable_charging( is_sleep );
		break;

	case POWER_SUPPLY_STATUS_FULL :
		disable_charging( is_sleep );
		/*Cancel timer*/
		clear_charge_start_time();

		break;

	case POWER_SUPPLY_STATUS_CHARGING :

		if ( sec_bci->battery.battery_vf_ok )
		{
			sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_GOOD;

			/*Start monitoring charging time*/
			set_charge_start_time();

			enable_charging( is_sleep );
		}
		else
		{
			sec_bci->battery.battery_health = POWER_SUPPLY_HEALTH_DEAD;

			status = POWER_SUPPLY_STATUS_NOT_CHARGING;

			disable_charging( is_sleep );

			printk( "[TA] INVALID BATTERY, %d !! \n", status );
		}

		break;

	case POWER_SUPPLY_STATUS_RECHARGING_FOR_FULL :
		/*Start monitoring charging time*/
		sec_bci->charger.charging_timeout = DEFAULT_RECHARGING_TIMEOUT;
		set_charge_start_time();

		enable_charging( is_sleep );

		break;
		
	case POWER_SUPPLY_STATUS_RECHARGING_FOR_TEMP :
		enable_charging( is_sleep );
		break;

	default :
		;
	}

	sec_bci->charger.prev_charge_status = sec_bci->charger.charge_status;
	sec_bci->charger.charge_status = status;

	_charger_state_change_( STATUS_CATEGORY_CHARGING, status, is_sleep );

}