static int calc_next_state(int state)
{
	struct batt_params batt;
	int alarm;

	battery_get_params_and_save_a_copy(&batt);

	switch (state) {
	case ST_IDLE0:
	case ST_BAD_COND:
	case ST_IDLE:
		/* Check AC and chiset state */
		if (!extpower_is_present()) {
			if (chipset_in_state(CHIPSET_STATE_ON))
				return ST_DISCHARGING;
			return ST_IDLE;
		}

		/* Stay in idle mode if charger overtemp */
		if (pmu_is_charger_alarm())
			return ST_BAD_COND;

		/* Enable charging when battery doesn't respond */
		if (!(batt.flags & BATT_FLAG_RESPONSIVE))
			return ST_PRE_CHARGING;

		/* Turn off charger when battery temperature is out
		 * of the start charging range.
		 */
		if (!battery_start_charging_range(batt.temperature))
			return ST_BAD_COND;

		/* Turn off charger on battery over temperature alarm */
		if (battery_status(&alarm) || (alarm & ALARM_OVER_TEMP))
			return ST_BAD_COND;

		/* Stop charging if the battery says it's charged */
		if (alarm & ALARM_CHARGED)
			return ST_IDLE;

		/* Start charging only when battery charge lower than 100% */
		if (!(batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE)) {
			if (batt.state_of_charge < 100)
				return ST_CHARGING;
		}

		return ST_IDLE;

	case ST_PRE_CHARGING:
		if (!extpower_is_present())
			return ST_IDLE0;

		/*
		 * If the battery goes online after enabling the charger, go
		 * into charging state.
		 */
		if (batt.flags & BATT_FLAG_RESPONSIVE) {
			if (!battery_start_charging_range(batt.temperature))
				return ST_IDLE0;
			if (!(batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE)) {
				if (batt.state_of_charge >= 100)
					return ST_IDLE0;
			}
			return ST_CHARGING;
		}

		return ST_PRE_CHARGING;

	case ST_CHARGING:
		/* Go back to idle state when AC is unplugged */
		if (!extpower_is_present())
			return ST_IDLE0;

		/*
		 * Disable charging on battery access error, or charging
		 * temperature out of range.
		 */
		if (!(batt.flags & BATT_FLAG_RESPONSIVE)) {
			CPRINTS("pmu charging: unable to get battery "
				"temperature");
			return ST_IDLE0;
		} else if (!battery_charging_range(batt.temperature)) {
			CPRINTS("pmu charging: temperature out of range "
				"%dC",
				DECI_KELVIN_TO_CELSIUS(batt.temperature));
			return ST_CHARGING_ERROR;
		}

		/*
		 * Disable charging on battery alarm events or access error:
		 *   - over temperature
		 *   - over current
		 */
		if (battery_status(&alarm))
			return ST_IDLE0;

		if (alarm & ALARM_OVER_TEMP) {
			CPRINTS("pmu charging: battery over temp");
			return ST_CHARGING_ERROR;
		}

		/* Go to idle state if battery is fully charged */
		if (alarm & ALARM_CHARGED)
			return ST_IDLE;

		/*
		 * Disable charging on charger alarm events:
		 *   - charger over current
		 *   - charger over temperature
		 */
		if (pmu_is_charger_alarm()) {
			CPRINTS("pmu charging: charger alarm");
			return ST_IDLE0;
		}

		return ST_CHARGING;

	case ST_CHARGING_ERROR:
		/*
		 * This state indicates AC is plugged but the battery is not
		 * charging. The conditions to exit this state:
		 *   - battery detected
		 *   - battery temperature is in start charging range
		 *   - no battery alarm
		 */
		if (extpower_is_present()) {
			if (battery_status(&alarm))
				return ST_CHARGING_ERROR;

			if (alarm & ALARM_OVER_TEMP)
				return ST_CHARGING_ERROR;

			if (!(batt.flags & BATT_FLAG_RESPONSIVE))
				return ST_CHARGING_ERROR;

			if (!battery_charging_range(batt.temperature))
				return ST_CHARGING_ERROR;

			return ST_CHARGING;
		}

		return ST_IDLE0;


	case ST_DISCHARGING:
		/* Go back to idle state when AC is plugged */
		if (extpower_is_present())
			return ST_IDLE0;

		/* Prepare EC sleep after system stopped discharging */
		if (chipset_in_state(CHIPSET_STATE_ANY_OFF))
			return ST_IDLE0;

		/* Check battery discharging temperature range */
		if (batt.flags & BATT_FLAG_RESPONSIVE) {
			if (!battery_discharging_range(batt.temperature)) {
				CPRINTS("pmu discharging: temperature out of "
					"range %dC",
					DECI_KELVIN_TO_CELSIUS(
							batt.temperature));
				return system_off();
			}
		}
		/* Check discharging alarm */
		if (!battery_status(&alarm) && (alarm & ALARM_DISCHARGING)) {
			CPRINTS("pmu discharging: battery alarm %016b", alarm);
			return system_off();
		}
		/* Check remaining charge % */
		if (!(batt.flags & BATT_FLAG_BAD_STATE_OF_CHARGE)) {
			/*
			 * Shutdown AP when state of charge < 1.5%.
			 * Moving average is rounded to integer.
			 */
			if (rsoc_moving_average(batt.state_of_charge) < 2)
				return system_off();
			else if (batt.state_of_charge < 4)
				notify_battery_low();
		}

		return ST_DISCHARGING;
	}

	return ST_IDLE0;
}
Example #2
0
static void button_long_push()
{
  if(system_off) system_off();
}