예제 #1
0
/**
 * Common handler for steady states
 *
 * @param state		Current power state
 * @return Updated power state
 */
static enum power_state power_common_state(enum power_state state)
{
	switch (state) {
	case POWER_G3:
		if (want_g3_exit) {
			want_g3_exit = 0;
			return POWER_G3S5;
		}

		in_want = 0;
#ifdef CONFIG_HIBERNATE
		if (extpower_is_present())
			task_wait_event(-1);
		else {
			uint64_t target_time;
			uint64_t time_now = get_time().val;
			uint32_t delay = hibernate_delay;
#ifdef CONFIG_HIBERNATE_BATT_PCT
			if (charge_get_percent() <= CONFIG_HIBERNATE_BATT_PCT
			    && CONFIG_HIBERNATE_BATT_SEC < delay)
				delay = CONFIG_HIBERNATE_BATT_SEC;
#endif
			target_time = last_shutdown_time + delay * 1000000ull;
			if (time_now > target_time) {
				/*
				 * Time's up.  Hibernate until wake pin
				 * asserted.
				 */
#ifdef CONFIG_LOW_POWER_PSEUDO_G3
				enter_pseudo_g3();
#else
				CPRINTS("hibernating");
				system_hibernate(0, 0);
#endif
			} else {
				uint64_t wait = target_time - time_now;
				if (wait > TASK_MAX_WAIT_US)
					wait = TASK_MAX_WAIT_US;

				/* Wait for a message */
				task_wait_event(wait);
			}
		}
#else /* !CONFIG_HIBERNATE */
		task_wait_event(-1);
#endif
		break;

	case POWER_S5:
		/*
		 * If the power button is pressed before S5 inactivity timer
		 * expires, the timer will be cancelled and the task of the
		 * power state machine will be back here again. Since we are
		 * here, which means the system has been waiting for CPU
		 * starting up, we don't need want_g3_exit flag to be set
		 * anymore. Therefore, we can reset the flag here to prevent
		 * the situation that the flag is still set after S5 inactivity
		 * timer expires, which can cause the system to exit G3 again.
		 */
		want_g3_exit = 0;

		/* Wait for inactivity timeout */
		power_wait_signals(0);
		if (task_wait_event(S5_INACTIVITY_TIMEOUT) ==
		    TASK_EVENT_TIMER) {
			/* Prepare to drop to G3; wake not requested yet */
			return POWER_S5G3;
		}
		break;

	case POWER_S3:
		/* Wait for a message */
		power_wait_signals(0);
		task_wait_event(-1);
		break;

	case POWER_S0:
		/* Wait for a message */
		power_wait_signals(0);
		task_wait_event(-1);
		break;

	default:
		/* No common functionality for transition states */
		break;
	}

	return state;
}
예제 #2
0
파일: common.c 프로젝트: fourier49/BIZ_EC
/**
 * Common handler for steady states
 *
 * @param state		Current power state
 * @return Updated power state
 */
static enum power_state power_common_state(enum power_state state)
{
    switch (state) {
    case POWER_G3:
                if (want_g3_exit) {
                want_g3_exit = 0;
                return POWER_G3S5;
            }

        in_want = 0;
#ifdef CONFIG_HIBERNATE
        if (extpower_is_present())
            task_wait_event(-1);
        else {
            uint64_t target_time;
            uint64_t time_now = get_time().val;
            uint32_t delay = hibernate_delay;
#ifdef CONFIG_HIBERNATE_BATT_PCT
            if (charge_get_percent() <= CONFIG_HIBERNATE_BATT_PCT
                    && CONFIG_HIBERNATE_BATT_SEC < delay)
                delay = CONFIG_HIBERNATE_BATT_SEC;
#endif
            target_time = last_shutdown_time + delay * 1000000ull;
            if (time_now > target_time) {
                /*
                 * Time's up.  Hibernate until wake pin
                 * asserted.
                 */
#ifdef CONFIG_LOW_POWER_PSEUDO_G3
                enter_pseudo_g3();
#else
                CPRINTS("hibernating");
                system_hibernate(0, 0);
#endif
            } else {
                uint64_t wait = target_time - time_now;
                if (wait > TASK_MAX_WAIT_US)
                    wait = TASK_MAX_WAIT_US;

                /* Wait for a message */
                task_wait_event(wait);
            }
        }
#else /* !CONFIG_HIBERNATE */
        task_wait_event(-1);
#endif
        break;

    case POWER_S5:
        /* Wait for inactivity timeout */
        power_wait_signals(0);
        if (task_wait_event(S5_INACTIVITY_TIMEOUT) ==
                TASK_EVENT_TIMER) {
            /* Drop to G3; wake not requested yet */
            want_g3_exit = 0;
            return POWER_S5G3;
        }
        break;

    case POWER_S3:
        /* Wait for a message */
        power_wait_signals(0);
        task_wait_event(-1);
        break;

    case POWER_S0:
        /* Wait for a message */
        power_wait_signals(0);
        task_wait_event(-1);
        break;

    default:
        /* No common functionality for transition states */
        break;
    }

    return state;
}