diff --git a/board/hx20/board.c b/board/hx20/board.c index d91ef42799..c29e86e378 100644 --- a/board/hx20/board.c +++ b/board/hx20/board.c @@ -421,6 +421,8 @@ static void board_power_off_deferred(void) charger_psys_enable(0); charge_gate_onoff(0); + MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) |= 0x80; + /* Disable interrupts */ interrupt_disable(); for (i = 0; i < MCHP_IRQ_MAX; ++i) { diff --git a/board/hx20/lfw/gpio.inc b/board/hx20/lfw/gpio.inc index f4142d3c29..a62b0c685c 100644 --- a/board/hx20/lfw/gpio.inc +++ b/board/hx20/lfw/gpio.inc @@ -15,6 +15,8 @@ */ GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) +/* We need to take control of this away from VCI */ +GPIO(EC_ON, PIN(0250), GPIO_OUT_HIGH) /* keep +3VL_EC to power on */ /* Alternate functions GPIO definition */ @@ -31,13 +33,15 @@ ALTERNATE(PIN_MASK(2, 0x30), 1, MODULE_UART, 0) * MEC1701H SHD SPI is connected to QMSPI controller. * QMSPI drives chip select. SHD_CS0#(GPIO_0055) must be set * to alternate function 2 and GPIO_ODR_HIGH. - * GPIO_0055 Function 2, Bank 1 bit[13] */ +/* GPIO_0055 Function 2, Bank 1 bit[13] */ ALTERNATE(PIN_MASK(1, 0x2000), 2, MODULE_SPI_FLASH, GPIO_ODR_HIGH) /* SHD_CLK - GPIO_0056 Function 2, Bank 1 bit[14] */ ALTERNATE(PIN_MASK(1, 0x4000), 2, MODULE_SPI_FLASH, 0) -/* MOSI(SHD_IO0) - GPIO_0223 Function 2, Bank 4 bit[19] */ +/* MOSI(SHD_IO0) - GPIO_0223 Function 1, Bank 4 bit[19] */ /* MISO(SHD_IO1) - GPIO_0224 Function 2, Bank 4 bit[20] */ -ALTERNATE(PIN_MASK(4, 0x180000), 2, MODULE_SPI_FLASH, 0) - - +/* nWP(SHD_IO2) - GPIO_0227 Function 1, Bank 4 bit[23] */ +ALTERNATE(PIN_MASK(4, 0x880000), 1, MODULE_SPI_FLASH, 0) +ALTERNATE(PIN_MASK(4, 0x100000), 2, MODULE_SPI_FLASH, 0) +/* nHOLD(SHD_IO3) - GPIO_0016 Function 2, Bank 0 bit[14] */ +ALTERNATE(PIN_MASK(0, 0x4000), 2, MODULE_SPI_FLASH, 0) diff --git a/board/hx20/power_sequence.c b/board/hx20/power_sequence.c index 530d4025b5..540ca47ee7 100644 --- a/board/hx20/power_sequence.c +++ b/board/hx20/power_sequence.c @@ -559,6 +559,10 @@ enum power_state power_handle_state(enum power_state state) gpio_set_level(GPIO_SYSON, 0); hook_notify(HOOK_CHIPSET_SHUTDOWN); cypd_set_power_active(POWER_S5); + + /* Call hooks after we remove power rails */ + hook_notify(HOOK_CHIPSET_SHUTDOWN_COMPLETE); + power_s5_up = 0; return POWER_S5; break; diff --git a/board/hx30/lfw/gpio.inc b/board/hx30/lfw/gpio.inc index f4142d3c29..fc7440cb23 100644 --- a/board/hx30/lfw/gpio.inc +++ b/board/hx30/lfw/gpio.inc @@ -15,6 +15,8 @@ */ GPIO(QMSPI_CS0, PIN(055), GPIO_ODR_HIGH) +/* We need to take control of this away from VCI */ +GPIO(EC_ON, PIN(0250), GPIO_OUT_HIGH) /* keep +3VL_EC to power on */ /* Alternate functions GPIO definition */ diff --git a/chip/mchp/lfw/ec_lfw.c b/chip/mchp/lfw/ec_lfw.c index 61cfc293fe..334338daa3 100644 --- a/chip/mchp/lfw/ec_lfw.c +++ b/chip/mchp/lfw/ec_lfw.c @@ -338,14 +338,26 @@ void system_init(void) uint32_t wdt_sts = MCHP_VBAT_STS & MCHP_VBAT_STS_ANY_RST; uint32_t rst_sts = MCHP_PCR_PWR_RST_STS & MCHP_PWR_RST_STS_VTR; + /* + * **HX20**: We can't hibernate the EC without also keeping + * 5v3v ALW on, so we cut power entirely. Unfortunately, + * that means that one of rst_sts or wdt_sts will always be + * on... and that precludes the use of the RW firmware. + * However, if we store a bit in IMAGETYPE to indicate that + * we cut power to ourselves, we can use it at the next boot + * to determine whether this poweroff was EC-origin or not. + */ + bool wacked = (MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) & 0x80) != 0; trace12(0, LFW, 0, "VBAT_STS = 0x%08x PCR_PWR_RST_STS = 0x%08x", wdt_sts, rst_sts); - if (rst_sts || wdt_sts) + if ((rst_sts || wdt_sts) && !wacked) MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) = EC_IMAGE_UNKNOWN; + + MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) &= 0x7F; } enum ec_image system_get_image_copy(void) @@ -410,6 +422,16 @@ void lfw_main(void) uart_init(); system_init(); + /* + * We need to switch control of VCI_OUT (aliased as EC_ON) away from + * VCI_INx to keep the machine powered even after the user releases the + * power button. This ensures that we can stay on long enough to read + * from SPI flash. + */ + gpio_reset(GPIO_EC_ON); + MCHP_VCI_REGISTER |= MCHP_VCI_REGISTER_FW_CNTRL; + MCHP_VCI_REGISTER |= MCHP_VCI_REGISTER_FW_EXT; + spi_enable(CONFIG_SPI_FLASH_PORT, 1); uart_puts("littlefw ");