diff options
Diffstat (limited to 'chip/npcx/system-npcx7.c')
-rw-r--r-- | chip/npcx/system-npcx7.c | 161 |
1 files changed, 161 insertions, 0 deletions
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 |