diff options
author | CHLin <CHLin56@nuvoton.com> | 2020-09-28 11:31:02 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-05 10:07:45 +0000 |
commit | 60ea87ad25e3a64a3f53de566924492148fb0ce2 (patch) | |
tree | 7283d32d79391870c20e3c00f6111978a9ecb6fd /chip | |
parent | e6ca724f8b5e15a18bccf14c5905b3f1d8baf7c2 (diff) | |
download | chrome-ec-60ea87ad25e3a64a3f53de566924492148fb0ce2.tar.gz |
npcx9: workaround the download_from_flash API of the booter
The download_from_flash API in the booter is called to copy the RO/RW
image from flash to code RAM when doing the sysjump. There is a bug in
the npcx9 A1 chip. We have to workaround it with this CL and remove
the bypass when A2 chip is available.
BRANCH=none
BUG=b:165777478
TEST=pass "make buildall"
TEST="sysjump RO/RW" succeeds in the npcx9 EVB.
Signed-off-by: CHLin <CHLin56@nuvoton.com>
Change-Id: Id2babe9b9dbd36ca8b0450051d22632eb5bd4825
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2435165
Tested-by: CH Lin <chlin56@nuvoton.com>
Tested-by: caveh jalali <caveh@chromium.org>
Reviewed-by: caveh jalali <caveh@chromium.org>
Commit-Queue: CH Lin <chlin56@nuvoton.com>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/npcx/config_chip-npcx9.h | 6 | ||||
-rw-r--r-- | chip/npcx/system-npcx7.c | 161 | ||||
-rw-r--r-- | chip/npcx/system.c | 8 | ||||
-rw-r--r-- | chip/npcx/system_chip.h | 2 |
4 files changed, 175 insertions, 2 deletions
diff --git a/chip/npcx/config_chip-npcx9.h b/chip/npcx/config_chip-npcx9.h index 0f7f9ce179..86e7ed5b85 100644 --- a/chip/npcx/config_chip-npcx9.h +++ b/chip/npcx/config_chip-npcx9.h @@ -53,8 +53,14 @@ #define NPCX_PSL_CFG_PSL_OUT_OD BIT(1) #define CONFIG_HIBERNATE_PSL_OUT_FLAGS 0 + +#define CONFIG_WORKAROUND_FLASH_DOWNLOAD_API /*****************************************************************************/ /* Memory mapping */ +#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API +#define CONFIG_LPRAM_BASE 0x40001400 /* memory address of lpwr ram */ +#define CONFIG_LPRAM_SIZE 0x00000620 /* 1568B low power ram */ +#endif #define NPCX_RAM_SIZE (CONFIG_DATA_RAM_SIZE + NPCX_PROGRAM_MEMORY_SIZE) diff --git a/chip/npcx/system-npcx7.c b/chip/npcx/system-npcx7.c index abbb6755c3..89b3e25e9b 100644 --- a/chip/npcx/system-npcx7.c +++ b/chip/npcx/system-npcx7.c @@ -18,6 +18,7 @@ #include "util.h" #include "gpio.h" #include "hwtimer_chip.h" +#include "mpu.h" #include "system_chip.h" #include "rom_chip.h" @@ -29,11 +30,49 @@ /* Higher bits are reserved and need to be masked */ #define RAM_PD_MASK (~BIT(LAST_RAM_BLK)) +#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API +#define LFW_OFFSET 0x160 +/* Begin address of Suspend RAM for little FW (GDMA utilities). */ +uintptr_t __lpram_lfw_start = CONFIG_LPRAM_BASE + LFW_OFFSET; +#endif /*****************************************************************************/ /* IC specific low-level driver depends on chip series */ +/* + * Configure address 0x40001600 (Low Power RAM) in the the MPU + * (Memory Protection Unit) as a "regular" memory + */ void system_mpu_config(void) { +#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API + /* + * npcx9 Rev.1 has the problem for download_from_flash API. + * Workwaroud it by by the system_download_from_flash function + * in the suspend RAM like npcx5. + * TODO: Remove this when A2 chip is available + */ + /* Enable MPU */ + CPU_MPU_CTRL = 0x7; + + /* Create a new MPU Region to allow execution from low-power ram */ + CPU_MPU_RNR = REGION_CHIP_RESERVED; + CPU_MPU_RASR = CPU_MPU_RASR & 0xFFFFFFFE; /* Disable region */ + CPU_MPU_RBAR = CONFIG_LPRAM_BASE; /* Set region base address */ + /* + * Set region size & attribute and enable region + * [31:29] - Reserved. + * [28] - XN (Execute Never) = 0 + * [27] - Reserved. + * [26:24] - AP = 011 (Full access) + * [23:22] - Reserved. + * [21:19,18,17,16] - TEX,S,C,B = 001000 (Normal memory) + * [15:8] - SRD = 0 (Subregions enabled) + * [7:6] - Reserved. + * [5:1] - SIZE = 01001 (1K) + * [0] - ENABLE = 1 (enabled) + */ + CPU_MPU_RASR = 0x03080013; +#endif } #ifdef CONFIG_HIBERNATE_PSL @@ -229,3 +268,125 @@ static void report_psl_wake_source(void) } DECLARE_HOOK(HOOK_INIT, report_psl_wake_source, HOOK_PRIO_DEFAULT); #endif + +/* + * npcx9 Rev.1 has the problem for download_from_flash API. + * Workwaroud it by executing the system_download_from_flash function + * in the suspend RAM like npcx5. + * TODO: Removing npcx9 when Rev.2 is available. + */ +#ifdef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API +#ifdef CONFIG_EXTERNAL_STORAGE +/* Sysjump utilities in low power ram for npcx9 series. */ +noreturn void __keep __attribute__ ((section(".lowpower_ram2"))) +__start_gdma(uint32_t exeAddr) +{ + /* Enable GDMA now */ + SET_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAEN); + + /* Start GDMA */ + SET_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_SOFTREQ); + + /* Wait for transfer to complete/fail */ + while (!IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_TC) && + !IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAERR)) + ; + + /* Disable GDMA now */ + CLEAR_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAEN); + + /* + * Failure occurs during GMDA transaction. Let watchdog issue and + * boot from RO region again. + */ + if (IS_BIT_SET(NPCX_GDMA_CTL, NPCX_GDMA_CTL_GDMAERR)) + while (1) + ; + + /* + * Jump to the exeAddr address if needed. Setting bit 0 of address to + * indicate it's a thumb branch for cortex-m series CPU. + */ + ((void (*)(void))(exeAddr | 0x01))(); + + /* Should never get here */ + while (1) + ; +} + +/* Bypass for GMDA issue of ROM api utilities only on npcx5 series. */ +void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, + uint32_t size, uint32_t exeAddr) +{ + int i; + uint8_t chunkSize = 16; /* 4 data burst mode. ie.16 bytes */ + /* + * GDMA utility in Suspend RAM. Setting bit 0 of address to indicate + * it's a thumb branch for cortex-m series CPU. + */ + void (*__start_gdma_in_lpram)(uint32_t) = + (void(*)(uint32_t))(__lpram_lfw_start | 0x01); + + /* + * Before enabling burst mode for better performance of GDMA, it's + * important to make sure srcAddr, dstAddr and size of transactions + * are 16 bytes aligned in case failure occurs. + */ + ASSERT((size % chunkSize) == 0 && (srcAddr % chunkSize) == 0 && + (dstAddr % chunkSize) == 0); + + /* Check valid address for jumpiing */ + ASSERT(exeAddr != 0x0); + + /* Enable power for the Low Power RAM */ + CLEAR_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6), 6); + + /* Enable Low Power RAM */ + NPCX_LPRAM_CTRL = 1; + + /* + * Initialize GDMA for flash reading. + * [31:21] - Reserved. + * [20] - GDMAERR = 0 (Indicate GMDA transfer error) + * [19] - Reserved. + * [18] - TC = 0 (Terminal Count. Indicate operation is end.) + * [17] - Reserved. + * [16] - SOFTREQ = 0 (Don't trigger here) + * [15] - DM = 0 (Set normal demand mode) + * [14] - Reserved. + * [13:12] - TWS. = 10 (One double-word for every GDMA transaction) + * [11:10] - Reserved. + * [9] - BME = 1 (4-data ie.16 bytes - Burst mode enable) + * [8] - SIEN = 0 (Stop interrupt disable) + * [7] - SAFIX = 0 (Fixed source address) + * [6] - Reserved. + * [5] - SADIR = 0 (Source address incremented) + * [4] - DADIR = 0 (Destination address incremented) + * [3:2] - GDMAMS = 00 (Software mode) + * [1] - Reserved. + * [0] - ENABLE = 0 (Don't enable yet) + */ + NPCX_GDMA_CTL = 0x00002200; + + /* Set source base address */ + NPCX_GDMA_SRCB = CONFIG_MAPPED_STORAGE_BASE + srcAddr; + + /* Set destination base address */ + NPCX_GDMA_DSTB = dstAddr; + + /* Set number of transfers */ + NPCX_GDMA_TCNT = (size / chunkSize); + + /* Clear Transfer Complete event */ + SET_BIT(NPCX_GDMA_CTL, NPCX_GDMA_CTL_TC); + + /* Copy the __start_gdma_in_lpram instructions to LPRAM */ + for (i = 0; i < &__flash_lplfw_end - &__flash_lplfw_start; i++) + *((uint32_t *)__lpram_lfw_start + i) = + *(&__flash_lplfw_start + i); + + /* Start GDMA in Suspend RAM */ + __start_gdma_in_lpram(exeAddr); +} +#endif /* CONFIG_EXTERNAL_STORAGE */ +#endif diff --git a/chip/npcx/system.c b/chip/npcx/system.c index 0930e8be0e..e74ae65d58 100644 --- a/chip/npcx/system.c +++ b/chip/npcx/system.c @@ -1270,8 +1270,14 @@ void system_jump_to_booter(void) */ clock_turbo(); +/* + * npcx9 Rev.1 has the problem for download_from_flash API. + * Workwaroud it by executing the system_download_from_flash function + * in the suspend RAM like npcx5. + * TODO: Removing npcx9 when Rev.2 is available. + */ /* Bypass for GMDA issue of ROM api utilities */ -#if defined(CHIP_FAMILY_NPCX5) +#if defined(CHIP_FAMILY_NPCX5) || defined(CONFIG_WORKAROUND_FLASH_DOWNLOAD_API) system_download_from_flash( flash_offset, /* The offset of the data in spi flash */ CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of downloaded data */ diff --git a/chip/npcx/system_chip.h b/chip/npcx/system_chip.h index db2351cf33..c084cd04a6 100644 --- a/chip/npcx/system_chip.h +++ b/chip/npcx/system_chip.h @@ -64,7 +64,7 @@ void __hibernate_npcx_series(void); void system_check_bbram_on_reset(void); /* The utilities and variables depend on npcx chip family */ -#if defined(CHIP_FAMILY_NPCX5) +#if defined(CHIP_FAMILY_NPCX5) || defined(CONFIG_WORKAROUND_FLASH_DOWNLOAD_API) /* Bypass for GMDA issue of ROM api utilities only on npcx5 series */ void system_download_from_flash(uint32_t srcAddr, uint32_t dstAddr, uint32_t size, uint32_t exeAddr); |