diff options
Diffstat (limited to 'power/cometlake-discrete.c')
-rw-r--r-- | power/cometlake-discrete.c | 416 |
1 files changed, 0 insertions, 416 deletions
diff --git a/power/cometlake-discrete.c b/power/cometlake-discrete.c deleted file mode 100644 index a22e32a69f..0000000000 --- a/power/cometlake-discrete.c +++ /dev/null @@ -1,416 +0,0 @@ -/* Copyright 2019 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Chrome EC chipset power control for Cometlake with platform-controlled - * discrete sequencing. - */ - -#include "adc.h" -#include "chipset.h" -#include "console.h" -#include "gpio.h" -#include "power.h" -#include "power/intel_x86.h" -#include "power_button.h" -#include "task.h" -#include "timer.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ##args) - -/* Power signals list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - [PP5000_A_PGOOD] = { - GPIO_PG_PP5000_A_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "PP5000_A_PGOOD", - }, - [PP1800_A_PGOOD] = { - GPIO_PG_PP1800_A_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "PP1800_A_PGOOD", - }, - [VPRIM_CORE_A_PGOOD] = { - GPIO_PG_VPRIM_CORE_A_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "VPRIM_CORE_A_PGOOD", - }, - [PP1050_A_PGOOD] = { - GPIO_PG_PP1050_A_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "PP1050_A_PGOOD", - }, - [OUT_PCH_RSMRST_DEASSERTED] = { - GPIO_PCH_RSMRST_L, - POWER_SIGNAL_ACTIVE_HIGH, - "OUT_PCH_RSMRST_DEASSERTED", - }, - [X86_SLP_S4_DEASSERTED] = { - SLP_S4_SIGNAL_L, - POWER_SIGNAL_ACTIVE_HIGH, - "SLP_S4_DEASSERTED", - }, - [PP2500_DRAM_PGOOD] = { - GPIO_PG_PP2500_DRAM_U_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "PP2500_DRAM_PGOOD", - }, - [PP1200_DRAM_PGOOD] = { - GPIO_PG_PP1200_U_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "PP1200_DRAM_PGOOD", - }, - [X86_SLP_S3_DEASSERTED] = { - SLP_S3_SIGNAL_L, - POWER_SIGNAL_ACTIVE_HIGH, - "SLP_S3_DEASSERTED", - }, - [PP950_VCCIO_PGOOD] = { - GPIO_PG_PP950_VCCIO_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "PP950_VCCIO_PGOOD", - }, - [X86_SLP_S0_DEASSERTED] = { - GPIO_PCH_SLP_S0_L, - POWER_SIGNAL_ACTIVE_HIGH | POWER_SIGNAL_DISABLE_AT_BOOT, - "SLP_S0_DEASSERTED", - }, - [CPU_C10_GATE_DEASSERTED] = { - GPIO_CPU_C10_GATE_L, - POWER_SIGNAL_ACTIVE_HIGH, - "CPU_C10_GATE_DEASSERTED", - }, - [IMVP8_READY] = { - GPIO_IMVP8_VRRDY_OD, - POWER_SIGNAL_ACTIVE_HIGH, - "IMVP8_READY", - }, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -/* - * The EC is responsible for most of the power-on sequence with this driver, - * enabling rails and waiting for power-good signals from regulators before - * continuing. The power sequencing works as follows. - * - * 1. From G3 (all-off), power is applied and EC power supplies come up. - * The power button task kicks off platform power-up as desired. - * 2. Power up the platform to reach S5 - * a. Enable PP5000_A and wait for PP5000_A_PGOOD. - * b. Enable PP3300_A (EN_ROA_RAILS). - * c. Wait for PP3300_A power good. This regulator doesn't provide a power - * good output, so the EC monitors ADC_SNS_PP3300. - * d. Enable PP1800_A and wait for PP1800_A_PGOOD. - * e. PP1800_A_PGOOD automatically enables PPVAR_VPRIM_CORE_A, which receives - * power from PP3300_A (hence PP3300_A must precede PP1800_A, even though - * PP1800_A draws power from PP3300_G which is guaranteed to already be on) - * f. PPVAR_VPRIM_CORE_A_PGOOD automatically enables PP1050_A - * g. Wait for PP1050_A_PGOOD, indicating that both PPVAR_VPRIM_CORE_A and - * PP1050_A are good. - * h. Wait 10ms to satisfy tPCH03, then bring the PCH out of reset by - * deasserting RSMRST. - * 3. The PCH controls transition from S5 up to S3 and higher-power states. - * a. PCH deasserts SLP_S4, automatically turning on PP2500_DRAM_U and - * PP1200_DRAM_U. - * b. Wait for PP2500_DRAM_PGOOD and PP1200_DRAM_PGOOD. - * 4. PCH deasserts SLP_S3 to switch to S0 - * a. SLP_S3 transition automatically enables PP1050_ST_S. - * b. Wait for PP1050_ST_S good. The power good output from this regulator is - * not connected, so the EC monitors ADC_SNS_PP1050_ST_S. - * c. Turn on EN_S0_RAILS (enabling PP1200_PLLOC and PP1050_STG). - * VCCIO must not ramp up before VCCST, VCCSTG and memory rails are good - * (PDG figure 424, note 14). - * d. Wait 2ms (for EN_S0_RAILS load switches to turn on). - * e. Enable PP950_VCCIO. - * f. Wait for PG_PP950_VCCIO. Although the PCH may be asserting CPU_C10_GATED - * which holds the VCCIO regulator in a low-power mode, the regulator will - * turn on normally and assert power good then drop into low power mode - * and continue asserting power good. - * 5. Transition fully to S0 following SLP_S0 - * a. Assert VCCST_PWRGD. This notionally tracks PP1050_ST_S but must be - * deasserted in S3 and lower. - * b. Enable IMVP8_VR. - * c. Wait 2ms. - * d. Assert SYS_PWROK. - * e. Wait for IMVP8_VRRDY. - * f. Wait 2ms. - * g. Assert PCH_PWROK. - * - * When CPU_C10_GATED is asserted, we are free to disable PP1200_PLLOC and - * PP1050_STG by deasserting EN_S0_RAILS to save some power. VCCIO is - * automatically placed in low-power mode by CPU_C10_GATED, and no further - * action is required- power-good signals will not change, just the relevant - * load switches (which are specified to meet the platform's minimum turn-on - * time when CPU_C10_GATED is deasserted again) are turned off. This gating is - * done asynchronously directly in the interrupt handler because its timing is - * very tight. - * - * For further reference, Figure 421 and Table 370 in the Comet Lake U PDG - * summarizes platform power rail requirements in a reasonably easy-to-digest - * manner, while section 12.11 (containing those diagrams) details the required - * operation. - */ - -/* - * Reverse of S0->S3 transition. - * - * This is a separate function so it can be reused when forcing shutdown due to - * power failure or other reasons. - * - * This function may be called from an ISR (slp_s3_interrupt) so must not - * assume that it's running in a regular task. - */ -static void shutdown_s0_rails(void) -{ - board_enable_s0_rails(0); - /* - * Deassert VCCST_PG as early as possible to satisfy tCPU22; VDDQ is - * derived directly from SLP_S3. - */ - gpio_set_level(GPIO_VCCST_PG_OD, 0); - gpio_set_level(GPIO_EC_PCH_PWROK, 0); - gpio_set_level(GPIO_EC_PCH_SYS_PWROK, 0); - gpio_set_level(GPIO_EN_IMVP8_VR, 0); - gpio_set_level(GPIO_EN_S0_RAILS, 0); - /* - * * tPCH10: PCH_PWROK to VCCIO off >400ns (but only on unexpected - * power-down) - * * tPLT18: SLP_S3_L to VCCIO disable <200us - * - * tPCH10 is only 7 CPU cycles at 16 MHz so we should satisfy that - * minimum time with no extra code, and sleeping is likely to cause - * a delay that exceeds tPLT18. - */ - gpio_set_level(GPIO_EN_PP950_VCCIO, 0); -} - -/* - * Reverse of G3->S5 transition. - * - * This is a separate function so it can be reused when forcing shutdown due to - * power failure or other reasons. - */ -static void shutdown_s5_rails(void) -{ - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - /* tPCH12: RSMRST to VCCPRIM (PPVAR_VPRIM_CORE_A) off >400ns */ - usleep(1); - gpio_set_level(GPIO_EN_PP1800_A, 0); - gpio_set_level(GPIO_EN_ROA_RAILS, 0); -#ifdef CONFIG_POWER_PP5000_CONTROL - power_5v_enable(task_get_current(), 0); -#else - gpio_set_level(GPIO_EN_PP5000_A, 0); -#endif -} - -void chipset_force_shutdown(enum chipset_shutdown_reason reason) -{ - CPRINTS("%s(%d)", __func__, reason); - report_ap_reset(reason); - - shutdown_s0_rails(); - /* S3->S5 is automatic based on SLP_S3 driving memory rails. */ - shutdown_s5_rails(); -} - -void chipset_handle_espi_reset_assert(void) {} - -enum power_state chipset_force_g3(void) -{ - chipset_force_shutdown(CHIPSET_SHUTDOWN_G3); - - return POWER_G3; -} - -/* - * Wait for a power rail on an analog channel to become good. - * - * @param channel ADC channel to read - * @param min_voltage Minimum required voltage for rail (in mV) - * - * @return EC_SUCCESS, or non-zero if error. - */ -static int power_wait_analog(enum adc_channel channel, int min_voltage) -{ - timestamp_t deadline; - int reading; - - /* One second timeout */ - deadline = get_time(); - deadline.val += SECOND; - - do { - reading = adc_read_channel(channel); - if (reading == ADC_READ_ERROR) - return EC_ERROR_HW_INTERNAL; - if (timestamp_expired(deadline, NULL)) - return EC_ERROR_TIMEOUT; - } while (reading < min_voltage); - - return EC_SUCCESS; -} - -/* - * Force system power state if we time out waiting for a power rail to become - * good. - * - * In general the new state is to transition down to the next lower-power state, - * so if we time out in G3->S5 we return POWER_G3 to turn things off again and - * if S3->S0 times out we return POWER_S3S5 for the same reason. - * - * Correct sequencing of rails that might already be enabled is handled by - * chipset_force_shutdown(), so the caller of this function doesn't need to - * clean up after itself. - */ -static enum power_state pgood_timeout(enum power_state new_state) -{ - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return new_state; -} - -/* - * Called in the chipset task when power signal inputs change state. - * If this doesn't request a different state, power_common_state handles it. - * - * @param state Current power state - * @return New power state - */ -enum power_state power_handle_state(enum power_state state) -{ - switch (state) { - case POWER_G3S5: - if (intel_x86_wait_power_up_ok() != EC_SUCCESS) { - chipset_force_shutdown( - CHIPSET_SHUTDOWN_BATTERY_INHIBIT); - return POWER_G3; - } - /* Power-up steps 2a-2h. */ -#ifdef CONFIG_POWER_PP5000_CONTROL - power_5v_enable(task_get_current(), 1); -#else - gpio_set_level(GPIO_EN_PP5000_A, 1); -#endif - if (power_wait_signals(POWER_SIGNAL_MASK(PP5000_A_PGOOD))) - return pgood_timeout(POWER_S5G3); - gpio_set_level(GPIO_EN_ROA_RAILS, 1); - if (power_wait_analog(ADC_SNS_PP3300, 3000) != EC_SUCCESS) - return pgood_timeout(POWER_S5G3); - gpio_set_level(GPIO_EN_PP1800_A, 1); - if (power_wait_signals(POWER_SIGNAL_MASK(PP1800_A_PGOOD) | - POWER_SIGNAL_MASK(PP1050_A_PGOOD))) - return pgood_timeout(POWER_S5G3); - msleep(10); /* tPCH03: VCCPRIM good -> RSMRST >10ms */ - gpio_set_level(GPIO_PCH_RSMRST_L, 1); - break; - - case POWER_S5G3: - shutdown_s5_rails(); - break; - - case POWER_S5S3: - /* Power-up steps 3a-3b. */ - if (power_wait_signals(POWER_SIGNAL_MASK(PP2500_DRAM_PGOOD) | - POWER_SIGNAL_MASK(PP1200_DRAM_PGOOD))) - return pgood_timeout(POWER_S3S5); - break; - - case POWER_S3S0: - /* Power-up steps 4a-4f. */ - if (power_wait_analog(ADC_SNS_PP1050, 1000) != EC_SUCCESS) - return pgood_timeout(POWER_S3S5); - gpio_set_level(GPIO_EN_S0_RAILS, 1); - msleep(2); - gpio_set_level(GPIO_EN_PP950_VCCIO, 1); - if (power_wait_signals(POWER_SIGNAL_MASK(PP950_VCCIO_PGOOD))) - return pgood_timeout(POWER_S3S5); - - /* Power-up steps 5a-5h */ - gpio_set_level(GPIO_VCCST_PG_OD, 1); - gpio_set_level(GPIO_EN_IMVP8_VR, 1); - msleep(2); - gpio_set_level(GPIO_EC_PCH_SYS_PWROK, 1); - if (power_wait_signals(POWER_SIGNAL_MASK(IMVP8_READY))) - return pgood_timeout(POWER_S3S5); - msleep(2); - gpio_set_level(GPIO_EC_PCH_PWROK, 1); - - board_enable_s0_rails(1); - break; - - case POWER_S0S3: - /* - * Handled in the slp_s3_interrupt fast path, but also run - * here in case we miss the interrupt somehow. - */ - shutdown_s0_rails(); - break; - - case POWER_S5: - /* - * Return to G3 if S5 rails are not on, probably because of - * a forced power-off. - */ - if ((power_get_signals() & CHIPSET_G3S5_POWERUP_SIGNAL) != - CHIPSET_G3S5_POWERUP_SIGNAL) - return POWER_S5G3; - break; - - default: - break; - } - - /* - * Power-up steps 3a-3b (S5->S3 via IN_PGOOD_ALL_CORE) plus general - * bookkeeping. - */ - return common_intel_x86_power_handle_state(state); -} - -#ifdef CONFIG_VBOOT_EFS -/* - * Called in main() to ensure chipset power is in a good state. - * - * This may be useful because EC reset could happen under unexpected - * conditions and we want to ensure that if the AP is wedged for some - * reason (for instance) we unwedge it before continuing. - * - * Because power sequencing here is all EC-controlled and this is called - * as part of the init sequence, we don't need to do anything- EC reset - * implies power sequencing is all-off and we don't have any external - * PMIC to synchronize state with. - */ -void chipset_handle_reboot(void) {} -#endif /* CONFIG_VBOOT_EFS */ - -void c10_gate_interrupt(enum gpio_signal signal) -{ - /* - * Per PDG, gate VccSTG and VCCIO on (SLP_S3_L && CPU_C10_GATE_L). - * - * When in S3 we let the state machine do it since timing is less - * critical; when in S0/S0ix we do it here because timing is very - * tight. - */ - if (board_is_c10_gate_enabled() && gpio_get_level(GPIO_SLP_S3_L)) { - int enable_core = gpio_get_level(GPIO_CPU_C10_GATE_L); - - gpio_set_level(GPIO_EN_S0_RAILS, enable_core); - } - - return power_signal_interrupt(signal); -} - -void slp_s3_interrupt(enum gpio_signal signal) -{ - if (!gpio_get_level(GPIO_SLP_S3_L) - && chipset_in_state(CHIPSET_STATE_ON)) { - /* Falling edge on SLP_S3_L means dropping to S3 from S0 */ - shutdown_s0_rails(); - } - - return power_signal_interrupt(signal); -} |