summaryrefslogtreecommitdiff
path: root/chip/npcx/system-npcx7.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/npcx/system-npcx7.c')
-rw-r--r--chip/npcx/system-npcx7.c161
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