diff options
-rw-r--r-- | chip/mt_scp/memmap.c | 135 | ||||
-rw-r--r-- | chip/mt_scp/registers.h | 73 | ||||
-rw-r--r-- | chip/mt_scp/system.c | 4 |
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(); } |