summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/mt_scp/memmap.c135
-rw-r--r--chip/mt_scp/registers.h73
-rw-r--r--chip/mt_scp/system.c4
3 files changed, 205 insertions, 7 deletions
diff --git a/chip/mt_scp/memmap.c b/chip/mt_scp/memmap.c
index 798969b63d..cec1e5496b 100644
--- a/chip/mt_scp/memmap.c
+++ b/chip/mt_scp/memmap.c
@@ -7,9 +7,11 @@
#include "common.h"
#include "compile_time_macros.h"
+#include "console.h"
#include "hooks.h"
#include "memmap.h"
#include "registers.h"
+#include "util.h"
/*
* Map SCP address (bits 31~28) to AP address
@@ -47,6 +49,118 @@ static const uint8_t addr_map[16] = {
*/
#define CACHE_TRANS_AP_ADDR 0x50000000
#define CACHE_TRANS_SCP_CACHE_ADDR 0x10000000
+/* FIXME: This should be configurable */
+#define CACHE_TRANS_AP_SIZE 0x00400000
+
+#ifdef CONFIG_DRAM_BASE
+BUILD_ASSERT(CONFIG_DRAM_BASE_LOAD == CACHE_TRANS_AP_ADDR);
+BUILD_ASSERT(CONFIG_DRAM_BASE == CACHE_TRANS_SCP_CACHE_ADDR);
+#endif
+
+static void cpu_invalidate_icache(void)
+{
+ SCP_CACHE_OP(CACHE_ICACHE) &= ~SCP_CACHE_OP_OP_MASK;
+ SCP_CACHE_OP(CACHE_ICACHE) |=
+ OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN;
+ asm volatile("dsb; isb");
+}
+
+void cpu_invalidate_dcache(void)
+{
+ SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK;
+ SCP_CACHE_OP(CACHE_DCACHE) |=
+ OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN;
+ asm volatile("dsb;");
+}
+
+void cpu_clean_invalidate_dcache(void)
+{
+ SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK;
+ SCP_CACHE_OP(CACHE_DCACHE) |=
+ OP_CACHE_FLUSH_ALL_LINES | SCP_CACHE_OP_EN;
+ SCP_CACHE_OP(CACHE_DCACHE) &= ~SCP_CACHE_OP_OP_MASK;
+ SCP_CACHE_OP(CACHE_DCACHE) |=
+ OP_INVALIDATE_ALL_LINES | SCP_CACHE_OP_EN;
+ asm volatile("dsb;");
+}
+
+static void scp_cache_init(void)
+{
+ int c;
+
+ /* First make sure all caches are disabled, and reset stats. */
+ for (c = 0; c < CACHE_COUNT; c++) {
+ SCP_CACHE_REGION_EN(c) = 0;
+ SCP_CACHE_CON(c) = 0;
+
+ /* Reset statistics. */
+ SCP_CACHE_HCNT0U(c) = 0;
+ SCP_CACHE_HCNT0L(c) = 0;
+ SCP_CACHE_CCNT0U(c) = 0;
+ SCP_CACHE_CCNT0L(c) = 0;
+ }
+
+ /* No "normal" remap. */
+ SCP_L1_REMAP_CFG0 = 0;
+ SCP_L1_REMAP_CFG1 = 0;
+ SCP_L1_REMAP_CFG2 = 0;
+ SCP_L1_REMAP_CFG3 = 0;
+ /*
+ * Setup OTHER1: Remap register for addr msb 31 to 28 equal to 0x1 and
+ * not overlap with L1C_EXT_ADDR0 to L1C_EXT_ADDR7.
+ */
+ SCP_L1_REMAP_OTHER =
+ (CACHE_TRANS_AP_ADDR >> SCP_L1_EXT_ADDR_OTHER_SHIFT) << 8;
+
+ /* Disable sleep protect */
+ SCP_SLP_PROTECT_CFG = SCP_SLP_PROTECT_CFG &
+ ~(P_CACHE_SLP_PROT_EN | D_CACHE_SLP_PROT_EN);
+
+ /* Enable region 0 for both I-cache and D-cache. */
+ for (c = 0; c < CACHE_COUNT; c++) {
+ const int region = 0;
+
+ SCP_CACHE_ENTRY(c, region) = CACHE_TRANS_SCP_CACHE_ADDR;
+ SCP_CACHE_END_ENTRY(c, region) =
+ CACHE_TRANS_SCP_CACHE_ADDR + CACHE_TRANS_AP_SIZE;
+ SCP_CACHE_ENTRY(c, region) |= SCP_CACHE_ENTRY_C;
+
+ SCP_CACHE_REGION_EN(c) |= 1 << region;
+
+ /* Set cache to 8 kb, clear other registers */
+ SCP_CACHE_CON(c) = SCP_CACHE_CON_CACHESIZE_8KB |
+ SCP_CACHE_CON_MCEN | SCP_CACHE_CON_CNTEN0;
+ }
+
+ cpu_invalidate_icache();
+ /*
+ * TODO(b/123205971): It seems like we need to call this twice, else the
+ * cache keeps stale data.
+ */
+ cpu_invalidate_dcache();
+ cpu_invalidate_dcache();
+}
+
+static int command_cacheinfo(int argc, char **argv)
+{
+ const char cache_name[] = {'I', 'D'};
+ int c;
+
+ for (c = 0; c < 2; c++) {
+ uint64_t hit = ((uint64_t)SCP_CACHE_HCNT0U(c) << 32) |
+ SCP_CACHE_HCNT0L(c);
+ uint64_t access = ((uint64_t)SCP_CACHE_CCNT0U(c) << 32) |
+ SCP_CACHE_CCNT0L(c);
+
+ ccprintf("%ccache hit count: %lu\n", cache_name[c], hit);
+ ccprintf("%ccache access count: %lu\n", cache_name[c], access);
+ }
+
+ return EC_SUCCESS;
+}
+DECLARE_SAFE_CONSOLE_COMMAND(cacheinfo, command_cacheinfo,
+ NULL,
+ "Dump cache info");
void scp_memmap_init(void)
{
@@ -92,6 +206,9 @@ void scp_memmap_init(void)
(uint32_t)addr_map[0xf] << 16 |
(uint32_t)addr_map[0xe] << 8 |
(uint32_t)addr_map[0xc];
+
+ /* Initialize cache remapping. */
+ scp_cache_init();
}
int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr)
@@ -125,21 +242,31 @@ int memmap_scp_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr)
int memmap_ap_to_scp_cache(uintptr_t ap_addr, uintptr_t *scp_addr)
{
+ uintptr_t lsb;
+
if ((ap_addr & SCP_L1_EXT_ADDR_OTHER_MSB_MASK) != CACHE_TRANS_AP_ADDR)
return EC_ERROR_INVAL;
- *scp_addr = CACHE_TRANS_SCP_CACHE_ADDR |
- (ap_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK);
+ lsb = ap_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK;
+ if (lsb > CACHE_TRANS_AP_SIZE)
+ return EC_ERROR_INVAL;
+
+ *scp_addr = CACHE_TRANS_SCP_CACHE_ADDR | lsb;
return EC_SUCCESS;
}
int memmap_scp_cache_to_ap(uintptr_t scp_addr, uintptr_t *ap_addr)
{
+ uintptr_t lsb;
+
if ((scp_addr & SCP_L1_EXT_ADDR_OTHER_MSB_MASK) !=
CACHE_TRANS_SCP_CACHE_ADDR)
return EC_ERROR_INVAL;
- *ap_addr = CACHE_TRANS_AP_ADDR |
- (scp_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK);
+ lsb = scp_addr & SCP_L1_EXT_ADDR_OTHER_LSB_MASK;
+ if (lsb >= CACHE_TRANS_AP_SIZE)
+ return EC_ERROR_INVAL;
+
+ *ap_addr = CACHE_TRANS_AP_ADDR | lsb;
return EC_SUCCESS;
}
diff --git a/chip/mt_scp/registers.h b/chip/mt_scp/registers.h
index 7c0754b854..25368290a6 100644
--- a/chip/mt_scp/registers.h
+++ b/chip/mt_scp/registers.h
@@ -118,6 +118,8 @@
#define CORE_REG_PSP REG32(SCP_CFG_BASE + 0xB0)
#define CORE_REG_PC REG32(SCP_CFG_BASE + 0xB4)
#define SCP_SLP_PROTECT_CFG REG32(SCP_CFG_BASE + 0xC8)
+#define P_CACHE_SLP_PROT_EN (1 << 3)
+#define D_CACHE_SLP_PROT_EN (1 << 4)
#define SCP_ONE_TIME_LOCK REG32(SCP_CFG_BASE + 0xDC)
#define SCP_SECURE_CTRL REG32(SCP_CFG_BASE + 0xE0)
#define ENABLE_SPM_MASK_VREQ (1 << 28)
@@ -155,10 +157,28 @@
#define SCP_REMAP_ADDR_LSB_MASK ((1 << SCP_REMAP_ADDR_SHIFT) - 1)
#define SCP_REMAP_ADDR_MSB_MASK ((~0) << SCP_REMAP_ADDR_SHIFT)
-#define SCP_L1_REMAP_CFG0 REG32(SCP_CFG_BASE + 0x130)
+/* Cached memory remap control */
+#define SCP_L1_REMAP_CFG0 REG32(SCP_CFG_BASE + 0x12C)
+/*
+ * L1C_EXT_ADDR1[29:16] remap register for addr msb 31~20 equal to 0x401
+ * L1C_EXT_ADDR0[13:0] remap register for addr msb 31~20 equal to 0x400
+ */
#define SCP_L1_REMAP_CFG1 REG32(SCP_CFG_BASE + 0x130)
+/*
+ * L1C_EXT_ADDR3[29:16] remap register for addr msb 31~20 equal to 0x403
+ * L1C_EXT_ADDR2[13:0] remap register for addr msb 31~20 equal to 0x402
+ */
#define SCP_L1_REMAP_CFG2 REG32(SCP_CFG_BASE + 0x134)
+/*
+ * L1C_EXT_ADDR5[29:16] remap register for addr msb 31~20 equal to 0x405
+ * L1C_EXT_ADDR4[13:0] remap register for addr msb 31~20 equal to 0x404
+ */
#define SCP_L1_REMAP_CFG3 REG32(SCP_CFG_BASE + 0x138)
+/*
+ * L1C_EXT_ADDR_OTHER1[13:8] Remap register for addr msb 31 to 28 equal to 0x1
+ * L1C_EXT_ADDR_OTHER0[5:0] Remap register for addr msb 31 to 28 equal to 0x0
+ * and not overlap with L1C_EXT_ADDR0 to L1C_EXT_ADDR7
+ */
#define SCP_L1_REMAP_OTHER REG32(SCP_CFG_BASE + 0x13C)
#define SCP_L1_EXT_ADDR_SHIFT 20
@@ -369,6 +389,57 @@
#define SCP_SPI1_BASE (SCP_CFG_BASE + 0x10000)
#define SCP_SPI2_BASE (SCP_CFG_BASE + 0x11000)
+#define CACHE_ICACHE 0
+#define CACHE_DCACHE 1
+#define CACHE_COUNT 2
+#define SCP_CACHE_BASE (SCP_CFG_BASE + 0x14000)
+#define SCP_CACHE_SEL(x) (SCP_CACHE_BASE + (x)*0x3000)
+#define SCP_CACHE_CON(x) REG32(SCP_CACHE_SEL(x))
+#define SCP_CACHE_CON_MCEN (1 << 0)
+#define SCP_CACHE_CON_CNTEN0 (1 << 2)
+#define SCP_CACHE_CON_CNTEN1 (1 << 3)
+#define SCP_CACHE_CON_CACHESIZE_SHIFT 8
+#define SCP_CACHE_CON_CACHESIZE_MASK (0x3 << SCP_CACHE_CON_CACHESIZE_SHIFT)
+#define SCP_CACHE_CON_CACHESIZE_0KB (0x0 << SCP_CACHE_CON_CACHESIZE_SHIFT)
+#define SCP_CACHE_CON_CACHESIZE_8KB (0x1 << SCP_CACHE_CON_CACHESIZE_SHIFT)
+#define SCP_CACHE_CON_CACHESIZE_16KB (0x2 << SCP_CACHE_CON_CACHESIZE_SHIFT)
+#define SCP_CACHE_CON_CACHESIZE_32KB (0x3 << SCP_CACHE_CON_CACHESIZE_SHIFT)
+
+#define SCP_CACHE_OP(x) REG32(SCP_CACHE_SEL(x) + 0x04)
+#define SCP_CACHE_OP_EN (1 << 0)
+#define SCP_CACHE_OP_OP_SHIFT 1
+#define SCP_CACHE_OP_OP_MASK (0xf << SCP_CACHE_OP_OP_SHIFT)
+
+#define OP_INVALIDATE_ALL_LINES (0x1 << SCP_CACHE_OP_OP_SHIFT)
+#define OP_INVALIDATE_ONE_LINE_BY_ADDRESS (0x2 << SCP_CACHE_OP_OP_SHIFT)
+#define OP_INVALIDATE_ONE_LINE_BY_SET_WAY (0x4 << SCP_CACHE_OP_OP_SHIFT)
+#define OP_CACHE_FLUSH_ALL_LINES (0x9 << SCP_CACHE_OP_OP_SHIFT)
+#define OP_CACHE_FLUSH_ONE_LINE_BY_ADDRESS (0xa << SCP_CACHE_OP_OP_SHIFT)
+#define OP_CACHE_FLUSH_ONE_LINE_BY_SET_WAY (0xc << SCP_CACHE_OP_OP_SHIFT)
+
+#define SCP_CACHE_OP_TADDR_SHIFT 5
+#define SCP_CACHE_OP_TADDR_MASK (0x7ffffff << SCP_CACHE_OP_TADDR_SHIFT)
+
+/* Cache statistics */
+#define SCP_CACHE_HCNT0L(x) REG32(SCP_CACHE_SEL(x) + 0x08)
+#define SCP_CACHE_HCNT0U(x) REG32(SCP_CACHE_SEL(x) + 0x0c)
+#define SCP_CACHE_CCNT0L(x) REG32(SCP_CACHE_SEL(x) + 0x10)
+#define SCP_CACHE_CCNT0U(x) REG32(SCP_CACHE_SEL(x) + 0x14)
+#define SCP_CACHE_HCNT1L(x) REG32(SCP_CACHE_SEL(x) + 0x18)
+#define SCP_CACHE_HCNT1U(x) REG32(SCP_CACHE_SEL(x) + 0x1c)
+#define SCP_CACHE_CCNT1L(x) REG32(SCP_CACHE_SEL(x) + 0x20)
+#define SCP_CACHE_CCNT1U(x) REG32(SCP_CACHE_SEL(x) + 0x24)
+
+#define SCP_CACHE_REGION_EN(x) REG32(SCP_CACHE_SEL(x) + 0x2c)
+
+#define SCP_CACHE_ENTRY_BASE(x) (SCP_CACHE_SEL(x) + 0x2000)
+#define SCP_CACHE_ENTRY(x, reg) REG32(SCP_CACHE_ENTRY_BASE(x) + (reg)*4)
+#define SCP_CACHE_END_ENTRY_BASE(x) (SCP_CACHE_SEL(x) + 0x2040)
+#define SCP_CACHE_END_ENTRY(x, reg) REG32(SCP_CACHE_END_ENTRY_BASE(x) + \
+ (reg)*4)
+#define SCP_CACHE_ENTRY_C (1 << 8)
+#define SCP_CACHE_ENTRY_BASEADDR_MASK (0xfffff << 12)
+
/* ARMV7 regs */
#define ARM_SCB_SCR REG32(0xE000ED10)
#define SCR_DEEPSLEEP (1 << 2)
diff --git a/chip/mt_scp/system.c b/chip/mt_scp/system.c
index f10b79ddb5..baa0ea59b6 100644
--- a/chip/mt_scp/system.c
+++ b/chip/mt_scp/system.c
@@ -61,7 +61,7 @@ void chip_pre_init(void)
static void scp_enable_tcm(void)
{
- /* Enable tightly coupled memory (TCM) */
+ /* Enable L1 cache and tightly coupled memory (TCM) */
SCP_CLK_L1_SRAM_PD = 0;
SCP_CLK_TCM_TAIL_SRAM_PD = 0;
/* SCP CM4 mod */
@@ -193,7 +193,7 @@ void system_pre_init(void)
scp_enable_clock();
/* Peripheral IRQ */
scp_enable_pirq();
- /* Init dram mapping */
+ /* Init dram mapping (and cache) */
scp_memmap_init();
}