diff --git a/src/board/system76/galp3-c/include/board/power.h b/src/board/system76/galp3-c/include/board/power.h new file mode 100644 index 0000000..504ed64 --- /dev/null +++ b/src/board/system76/galp3-c/include/board/power.h @@ -0,0 +1,6 @@ +#ifndef _BOARD_POWER_H +#define _BOARD_POWER_H + +void power_event(void); + +#endif // _BOARD_POWER_H diff --git a/src/board/system76/galp3-c/power.c b/src/board/system76/galp3-c/power.c index 6d9c3c2..e06ec04 100644 --- a/src/board/system76/galp3-c/power.c +++ b/src/board/system76/galp3-c/power.c @@ -1,4 +1,7 @@ #include +#include +#include +#include #include // Platform does not currently support Deep Sx @@ -48,11 +51,19 @@ static struct Gpio __code SUS_PWR_ACK = GPIO(J, 0); #define tPCH11 delay_ns(100) // RSMRST# asserting to VccPRIM dropping 5% #define tPCH12 delay_ns(400) +// DSW_PWROK falling to any of VccDSW, VccPRIM dropping 5% +#define tPCH14 delay_ns(400) +// De-assertion of RSMRST# to de-assertion of ESPI_RESET# +#if DEEP_SX + #define tPCH18 delay_us(90) +#else + #define tPCH18 delay_ms(95) +#endif // DSW_PWROK assertion to SLP_SUS# de-assertion #define tPCH32 delay_ms(95) // Enable deep sleep well power -int power_on_dsw() { +void power_on_ds5() { #if DEEP_SX // See Figure 12-18 in Whiskey Lake Platform Design Guide // | VCCRTC | RTCRST# | VCCDSW_3P3 | DSW_PWROK | @@ -78,9 +89,6 @@ int power_on_dsw() { // tPCH04 is the ideal delay tPCH04; #endif // DEEP_SX - - // We are ready to move on to the next stage - return 0; } // Enable S5 power @@ -88,27 +96,160 @@ void power_on_s5() { #if DEEP_SX // See Figure 12-18 in Whiskey Lake Platform Design Guide - // RTC stage - { - // | VCCRTC | RTCRST# | VCCDSW_3P3 | DSW_PWROK | - // | tPCH01---------- | | | - // | tPCH04----------------------- | | - // | | tPCH05-------------------------- | - // | | | tPCH02---------------- | - // tPCH01 and tPCH02 combined make the longest delay - tPCH01; - tPCH02; - } - - // Deep sleep well is a-ok - gpio_set(PCH_DPWROK_EC, true); - tPCH32; - - // TODO #else // DEEP_SX // See Figure 12-19 in Whiskey Lake Platform Design Guide + // TODO - signal timing graph + // See Figure 12-25 in Whiskey Lake Platform Design Guide + // TODO - rail timing graph - // TODO + // Enable VCCPRIM_* planes - must be enabled prior to USB power in order to + // avoid leakage + gpio_set(&VA_EC_EN, true); + tPCH06; + + // Enable VDD5 + gpio_set(&DD_ON, true); + + // De-assert SUS_ACK# - TODO is this needed on non-dsx? + gpio_set(&SUS_PWR_ACK, true); + tPCH03; + + // Assert DSW_PWROK + gpio_set(&PCH_DPWROK_EC, true); + + // De-assert RSMRST# + gpio_set(&EC_RSMRST_N, true); + + // Wait for PCH stability + tPCH18; + + // Allow processor to control SUSB# and SUSC# + gpio_set(&EC_EN, true); +#endif // DEEP_SX +} + +void power_off_s5() { +#if DEEP_SX + // TODO +#else // DEEP_SX + // De-assert SYS_PWROK + gpio_set(&PCH_PWROK_EC, false); + + // De-assert PCH_PWROK + gpio_set(&PM_PWROK, false); + + // Block processor from controlling SUSB# and SUSC# + gpio_set(&EC_EN, false); + + // De-assert RSMRST# + gpio_set(&EC_RSMRST_N, false); + + // Disable VDD5 + gpio_set(&DD_ON, false); + tPCH12; + + // Disable VCCPRIM_* planes + gpio_set(&VA_EC_EN, false); + + // De-assert DSW_PWROK + gpio_set(&PCH_DPWROK_EC, false); + tPCH14; +#endif // DEEP_SX +} + +enum PowerState { + POWER_STATE_DEFAULT, + POWER_STATE_DS5, + POWER_STATE_S5, + POWER_STATE_DS3, + POWER_STATE_S3, + POWER_STATE_S0, +}; + +void power_event(void) { + static enum PowerState state = POWER_STATE_DEFAULT; + + // Always switch to ds5 if EC is running + if (state == POWER_STATE_DEFAULT) { + power_on_ds5(); + state = POWER_STATE_DS5; + + //TODO: Logic for switching from ds5 to s5 + power_on_s5(); + state = POWER_STATE_S5; + } + + // Read power button state + static bool last = true; + bool new = gpio_get(&PWR_SW_N); + if (!new && last) { + // Ensure press is not spurious + delay_ms(10); + if (gpio_get(&PWR_SW_N) != new) { + DEBUG("Spurious press\n"); + return; + } + + DEBUG("Power switch press\n"); + } + #if LEVEL >= LEVEL_DEBUG + else if (new && !last) { + DEBUG("Power switch release\n"); + } + #endif + + // Send power signal to PCH + gpio_set(&PWR_BTN_N, new); + +#if DEEP_SX + //TODO +#else // DEEP_SX + //TODO: set power state as necessary + + // If system power is good + if (gpio_get(&ALL_SYS_PWRGD)) { + DEBUG("ALL_SYS_PWRGD asserted\n"); + + // Allow H_VR_READY to set PCH_PWROK + gpio_set(&PM_PWROK, true); + + // OEM defined delay from ALL_SYS_PWRGD to SYS_PWROK - TODO + delay_ms(10); + + // Assert SYS_PWROK, system can finally perform PLT_RST# and boot + gpio_set(&PCH_PWROK_EC, true); + } else { + DEBUG("ALL_SYS_PWRGD de-asserted\n"); + + // De-assert SYS_PWROK + gpio_set(&PCH_PWROK_EC, false); + + // De-assert PCH_PWROK + gpio_set(&PM_PWROK, false); + } + + static bool rst_old = false; + bool rst_new = gpio_get(&BUF_PLT_RST_N); + if (!rst_old && rst_new) { + // LPC was just reset, enable PNP devices + pnp_enable(); + //TODO: reset KBC and touchpad states + } + + // EC must keep VccPRIM powered if SUSPWRDNACK is de-asserted low or system + // state is S3 + bool primary = !gpio_get(&SUSWARN_N) || !gpio_get(&SUSB_N_PCH); + if (primary) { + if (state == POWER_STATE_DS5) { + power_on_s5(); + state = POWER_STATE_DS5; + } + } else { + if (state == POWER_STATE_S5) { + power_off_s5(); + state = POWER_STATE_DS5; + } + } #endif // DEEP_SX }