static void chipset_turn_off_power_rails(void) { /* Release the power on pin, if it was asserted */ set_pmic_pwron(0); /* Close the pmic power source immediately */ set_pmic_source(0); /* Keep AP and PMIC in reset the whole time */ set_pmic_warm_reset(1); }
/** * Power on the AP */ static void power_on(void) { int i; set_pmic_source(1); usleep(PMIC_SOURCE_STARTUP_TIME); set_pmic_pwron(1); /* * BUG Workaround(crosbug.com/p/31635): usleep hangs in task when using * big delays. */ for (i = 0; i < PMIC_STARTUP_MS; i++) usleep(1 * MSEC); set_pmic_warm_reset(0); }
/** * Power on the AP */ static void power_on(void) { int i; set_pmic_source(1); usleep(PMIC_SOURCE_STARTUP_TIME); set_pmic_pwron(1); /* * BUG Workaround(crosbug.com/p/31635): usleep hangs in task when using * big delays. */ for (i = 0; i < PMIC_STARTUP_MS; i++) usleep(1 * MSEC); /* Reset the PMIC to make sure it's in a known state. */ set_pmic_reset(1); usleep(PMIC_RESET_HOLD_TIME); set_pmic_reset(0); set_pmic_warm_reset(0); }
enum power_state power_handle_state(enum power_state state) { int value; static int boot_from_g3; switch (state) { case POWER_G3: boot_from_g3 = check_for_power_on_event(); if (boot_from_g3) return POWER_G3S5; break; case POWER_G3S5: return POWER_S5; case POWER_S5: if (boot_from_g3) { value = boot_from_g3; boot_from_g3 = 0; } else { value = check_for_power_on_event(); } if (value) { CPRINTS("power on %d", value); return POWER_S5S3; } return state; case POWER_S5S3: hook_notify(HOOK_CHIPSET_PRE_INIT); power_on(); disable_sleep(SLEEP_MASK_AP_RUN); powerled_set_state(POWERLED_STATE_ON); if (power_wait_signals(IN_POWER_GOOD) == EC_SUCCESS) { CPRINTS("POWER_GOOD seen"); if (power_button_wait_for_release( DELAY_SHUTDOWN_ON_POWER_HOLD) == EC_SUCCESS) { power_button_was_pressed = 0; set_pmic_pwron(0); /* setup misc gpio for S3/S0 functionality */ gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT | GPIO_INT_BOTH | GPIO_PULL_DOWN); gpio_set_flags(GPIO_EC_INT_L, GPIO_OUTPUT | GPIO_OUT_HIGH); /* Call hooks now that AP is running */ hook_notify(HOOK_CHIPSET_STARTUP); return POWER_S3; } else { CPRINTS("long-press button, shutdown"); power_off(); /* * Since the AP may be up already, return S0S3 * state to go through the suspend hook. */ return POWER_S0S3; } } else { CPRINTS("POWER_GOOD not seen in time"); } chipset_turn_off_power_rails(); return POWER_S5; case POWER_S3: if (!(power_get_signals() & IN_POWER_GOOD)) return POWER_S3S5; else if (!(power_get_signals() & IN_SUSPEND)) return POWER_S3S0; return state; case POWER_S3S0: powerled_set_state(POWERLED_STATE_ON); hook_notify(HOOK_CHIPSET_RESUME); return POWER_S0; case POWER_S0: value = check_for_power_off_event(); if (value) { CPRINTS("power off %d", value); power_off(); return POWER_S0S3; } else if (power_get_signals() & IN_SUSPEND) return POWER_S0S3; return state; case POWER_S0S3: if (lid_is_open()) powerled_set_state(POWERLED_STATE_SUSPEND); else powerled_set_state(POWERLED_STATE_OFF); /* Call hooks here since we don't know it prior to AP suspend */ hook_notify(HOOK_CHIPSET_SUSPEND); return POWER_S3; case POWER_S3S5: power_button_wait_for_release(-1); power_button_was_pressed = 0; return POWER_S5; case POWER_S5G3: return POWER_G3; } return state; }