diff options
Diffstat (limited to 'board/kukui/emmc.c')
-rw-r--r-- | board/kukui/emmc.c | 69 |
1 files changed, 45 insertions, 24 deletions
diff --git a/board/kukui/emmc.c b/board/kukui/emmc.c index b0c3d1e74b..f9fd0f9a1b 100644 --- a/board/kukui/emmc.c +++ b/board/kukui/emmc.c @@ -28,6 +28,7 @@ * case we interrupt the transfer, and the BootROM will try again. */ +#include "chipset.h" #include "clock.h" #include "console.h" #include "dma.h" @@ -57,6 +58,13 @@ #error "Please define EMMC_SPI_PORT in board.h." #endif +/* Is eMMC emulation enabled? */ +static int emmc_enabled; + +/* Maximum amount of time to wait for AP to boot. */ +static timestamp_t boot_deadline; +#define BOOT_TIMEOUT (5 * SECOND) + /* 1024 bytes circular buffer is enough for ~0.6ms @ 13Mhz. */ #define SPI_RX_BUF_BYTES 1024 #define SPI_RX_BUF_WORDS (SPI_RX_BUF_BYTES/4) @@ -219,29 +227,12 @@ static void emmc_init_spi(void) } DECLARE_HOOK(HOOK_INIT, emmc_init_spi, HOOK_PRIO_INIT_SPI); -static int spi_enabled; - -static void emmc_disable_spi(void); - -static void emmc_check_status(void) -{ - /* Bootblock switch disabled, switch off emulation */ - if (gpio_get_level(GPIO_BOOTBLOCK_EN_L) == 1) { - emmc_disable_spi(); - return; - } - - /* - * TODO(b:110907438): If we reach here, it is likely that the AP failed - * to boot, and we should try to recover from that. - */ - CPRINTS("emmc: AP failed to boot."); -} +static void emmc_check_status(void); DECLARE_DEFERRED(emmc_check_status); static void emmc_enable_spi(void) { - if (spi_enabled) + if (emmc_enabled) return; disable_sleep(SLEEP_MASK_EMMC); @@ -250,25 +241,37 @@ static void emmc_enable_spi(void) dma_start_rx(&dma_rx_option, sizeof(in_msg), in_msg); /* Enable internal chip select. */ STM32_SPI_EMMC_REGS->cr1 &= ~STM32_SPI_CR1_SSI; + /* + * EMMC_CMD and SPI1_NSS share EXTI15, make sure GPIO_EMMC_CMD is + * selected. + */ + gpio_disable_interrupt(GPIO_SPI1_NSS); gpio_enable_interrupt(GPIO_EMMC_CMD); - spi_enabled = 1; + emmc_enabled = 1; CPRINTS("emmc enabled"); - /* Check if AP has booted 5 seconds later. */ - hook_call_deferred(&emmc_check_status_data, 5*SECOND); + boot_deadline.val = get_time().val + BOOT_TIMEOUT; + + /* Check if AP has booted periodically. */ + hook_call_deferred(&emmc_check_status_data, 100 * MSEC); } DECLARE_HOOK(HOOK_CHIPSET_STARTUP, emmc_enable_spi, HOOK_PRIO_FIRST); static void emmc_disable_spi(void) { - if (!spi_enabled) + if (!emmc_enabled) return; /* Cancel check hook. */ hook_call_deferred(&emmc_check_status_data, -1); gpio_disable_interrupt(GPIO_EMMC_CMD); + /* + * EMMC_CMD and SPI1_NSS share EXTI15, so re-enable interrupt on + * SPI1_NSS to reconfigure the interrupt selection. + */ + gpio_enable_interrupt(GPIO_SPI1_NSS); /* Disable TX DMA. */ dma_disable(STM32_DMAC_SPI_EMMC_TX); /* Disable internal chip select. */ @@ -281,11 +284,29 @@ static void emmc_disable_spi(void) enable_sleep(SLEEP_MASK_EMMC); - spi_enabled = 0; + emmc_enabled = 0; CPRINTS("emmc disabled"); } DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, emmc_disable_spi, HOOK_PRIO_FIRST); +static void emmc_check_status(void) +{ + /* Bootblock switch disabled, switch off emulation */ + if (gpio_get_level(GPIO_BOOTBLOCK_EN_L) == 1) { + emmc_disable_spi(); + return; + } + + if (timestamp_expired(boot_deadline, NULL)) { + CPRINTS("emmc: AP failed to boot."); + chipset_force_shutdown(CHIPSET_SHUTDOWN_BOARD_CUSTOM); + return; + } + + /* Check if AP has booted again, next time. */ + hook_call_deferred(&emmc_check_status_data, 100 * MSEC); +} + void emmc_task(void *u) { int dma_pos, i; |