summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCHLin <CHLin56@nuvoton.com>2020-09-28 11:31:02 +0800
committerCommit Bot <commit-bot@chromium.org>2020-10-05 10:07:45 +0000
commit60ea87ad25e3a64a3f53de566924492148fb0ce2 (patch)
tree7283d32d79391870c20e3c00f6111978a9ecb6fd
parente6ca724f8b5e15a18bccf14c5905b3f1d8baf7c2 (diff)
downloadchrome-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>
-rw-r--r--chip/npcx/config_chip-npcx9.h6
-rw-r--r--chip/npcx/system-npcx7.c161
-rw-r--r--chip/npcx/system.c8
-rw-r--r--chip/npcx/system_chip.h2
-rw-r--r--include/config.h6
5 files changed, 181 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);
diff --git a/include/config.h b/include/config.h
index 2a5f86377d..e32f7282c9 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1089,6 +1089,12 @@
/* Wireless chargers */
#undef CONFIG_WIRELESS_CHARGER_P9221_R7
+/*
+ * Workaround npcx9 A1 chip's bug for download_from_flash API in th booter.
+ * This can be removed when A2 chip is available.
+ */
+#undef CONFIG_WORKAROUND_FLASH_DOWNLOAD_API
+
/*****************************************************************************/
/*