From eaaa61604170980a43a583efcfd359520db3176f Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Mon, 2 Nov 2020 17:54:48 +0800 Subject: chip/mt8192_scp: support RAM cache Supports RAM cache for: - L2TCM - System DRAM BRANCH=none BUG=b:156222459 BUG=b:156222508 BUG=b:172886808 TEST=manually check assembly code Signed-off-by: Tzung-Bi Shih Change-Id: I3fd3d8f858a172bf26dfec6a5c6c403d73164039 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2513414 Reviewed-by: Nicolas Boichat --- chip/mt8192_scp/build.mk | 1 + chip/mt8192_scp/cache.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++ chip/mt8192_scp/cache.h | 45 +++++++++++++++ chip/mt8192_scp/csr.h | 21 +++++++ chip/mt8192_scp/memmap.c | 3 + 5 files changed, 212 insertions(+) create mode 100644 chip/mt8192_scp/cache.c create mode 100644 chip/mt8192_scp/cache.h diff --git a/chip/mt8192_scp/build.mk b/chip/mt8192_scp/build.mk index 0925ff2245..aef19efd39 100644 --- a/chip/mt8192_scp/build.mk +++ b/chip/mt8192_scp/build.mk @@ -9,6 +9,7 @@ CORE:=riscv-rv32i # Required chip modules +chip-y+=cache.o chip-y+=clock.o chip-y+=gpio.o chip-y+=intc.o diff --git a/chip/mt8192_scp/cache.c b/chip/mt8192_scp/cache.c new file mode 100644 index 0000000000..11051e6d18 --- /dev/null +++ b/chip/mt8192_scp/cache.c @@ -0,0 +1,142 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cache.h" +#include "common.h" +#include "compile_time_macros.h" +#include "csr.h" +#include "util.h" + +/* rs1 0~31 register X0~X31 */ +#define COP(rs1) (((rs1) << 15) | 0x400f) + +#define COP_OP_BARRIER_ICACHE 0x0 +#define COP_OP_INVALIDATE_ICACHE 0x8 +#define COP_OP_INVALIDATE_ICACHE_ADDR 0x9 + +#define COP_OP_BARRIER_DCACHE 0x10 +#define COP_OP_WRITEBACK_DCACHE 0x14 +#define COP_OP_WRITEBACK_DCACHE_ADDR 0x15 +#define COP_OP_INVALIDATE_DCACHE 0x18 +#define COP_OP_INVALIDATE_DCACHE_ADDR 0x19 +/* FLUSH = WRITEBACK + INVALIDATE */ +#define COP_OP_FLUSH_DCACHE 0x1C +#define COP_OP_FLUSH_DCACHE_ADDR 0x1D + +inline static void cache_op_all(uint32_t op) +{ + register int t0 asm("t0") = op; + asm volatile (".word "STRINGIFY(COP(5)) :: "r"(t0)); +} + +static int cache_op_addr(uintptr_t addr, uint32_t length, uint32_t op) +{ + size_t offset; + register int t0 asm("t0"); + + /* NOTE: cache operations must use 32 byte aligned address */ + if (addr & GENMASK(3, 0)) + return EC_ERROR_INVAL; + + for (offset = 0; offset < length; offset += 4) { + t0 = addr + offset + op; + asm volatile (".word "STRINGIFY(COP(5)) :: "r"(t0)); + } + + return EC_SUCCESS; +} + +void cache_barrier_icache(void) +{ + cache_op_all(COP_OP_BARRIER_ICACHE); +} + +void cache_invalidate_icache(void) +{ + cache_op_all(COP_OP_INVALIDATE_ICACHE); +} + +int cache_invalidate_icache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_INVALIDATE_ICACHE_ADDR); +} + +void cache_barrier_dcache(void) +{ + cache_op_all(COP_OP_BARRIER_DCACHE); +} + +void cache_writeback_dcache(void) +{ + cache_op_all(COP_OP_WRITEBACK_DCACHE); +} + +int cache_writeback_dcache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_WRITEBACK_DCACHE_ADDR); +} + +void cache_invalidate_dcache(void) +{ + cache_op_all(COP_OP_INVALIDATE_DCACHE); +} + +int cache_invalidate_dcache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_INVALIDATE_DCACHE_ADDR); +} + +void cache_flush_dcache(void) +{ + cache_op_all(COP_OP_FLUSH_DCACHE); +} + +int cache_flush_dcache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_FLUSH_DCACHE_ADDR); +} + +extern struct mpu_entry mpu_entries[]; + +void cache_init(void) +{ + int i; + uint32_t mpu_en = 0; + + /* disable mpu */ + clear_csr(CSR_MCTREN, CSR_MCTREN_MPU); + + /* enable i$, d$ */ + set_csr(CSR_MCTREN, CSR_MCTREN_ICACHE); + set_csr(CSR_MCTREN, CSR_MCTREN_DCACHE); + + /* invalidate icache and dcache */ + cache_invalidate_icache(); + cache_invalidate_dcache(); + + /* set mpu entries + * + * The pragma is for force GCC unrolls the following loop. + * See b/172886808 + */ +#pragma GCC unroll 16 + for (i = 0; i < NR_MPU_ENTRIES; ++i) { + if (mpu_entries[i].end_addr - mpu_entries[i].start_addr) { + write_csr(CSR_MPU_L(i), mpu_entries[i].start_addr | + mpu_entries[i].attribute); + write_csr(CSR_MPU_H(i), mpu_entries[i].end_addr); + mpu_en |= BIT(i); + } + } + + /* enable mpu entries */ + write_csr(CSR_MPU_ENTRY_EN, mpu_en); + + /* enable mpu */ + set_csr(CSR_MCTREN, CSR_MCTREN_MPU); + + /* fence */ + asm volatile ("fence.i" ::: "memory"); +} diff --git a/chip/mt8192_scp/cache.h b/chip/mt8192_scp/cache.h new file mode 100644 index 0000000000..cf77e765f9 --- /dev/null +++ b/chip/mt8192_scp/cache.h @@ -0,0 +1,45 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_CACHE_H +#define __CROS_EC_CACHE_H + +#include "csr.h" +#include "stdint.h" + +struct mpu_entry { + /* 1k alignment and the address is inclusive */ + uintptr_t start_addr; + /* 1k alignment in 4GB boundary and non-inclusive */ + uintptr_t end_addr; + /* MPU_ATTR */ + uint32_t attribute; +}; + +/* memory barrier of I$ */ +void cache_barrier_icache(void); +/* invalidate all I$ */ +void cache_invalidate_icache(void); +/* invalidate a range of I$ */ +int cache_invalidate_icache_range(uintptr_t addr, uint32_t length); + +/* memory barrier of D$ */ +void cache_barrier_dcache(void); +/* writeback all D$ */ +void cache_writeback_dcache(void); +/* writeback a range of D$ */ +int cache_writeback_dcache_range(uintptr_t addr, uint32_t length); +/* invalidate all D$ */ +void cache_invalidate_dcache(void); +/* invalidate a range of D$ */ +int cache_invalidate_dcache_range(uintptr_t addr, uint32_t length); +/* writeback and invalidate all D$ */ +void cache_flush_dcache(void); +/* writeback and invalidate a range of D$ */ +int cache_flush_dcache_range(uintptr_t addr, uint32_t length); + +void cache_init(void); + +#endif /* #ifndef __CROS_EC_CACHE_H */ diff --git a/chip/mt8192_scp/csr.h b/chip/mt8192_scp/csr.h index e9e95f3ffa..e43c84294a 100644 --- a/chip/mt8192_scp/csr.h +++ b/chip/mt8192_scp/csr.h @@ -63,4 +63,25 @@ static inline uint32_t clear_csr(uint32_t reg, uint32_t bit) #define CSR_MCTREN_CG BIT(7) #define CSR_MCTREN_MPU BIT(8) +/* MPU */ +#define CSR_MPU_ENTRY_EN (0x9c0) +#define CSR_MPU_LITCM (0x9dc) +#define CSR_MPU_LDTCM (0x9dd) +#define CSR_MPU_HITCM (0x9de) +#define CSR_MPU_HDTCM (0x9df) +#define CSR_MPU_L(n) (0x9e0 + (n)) +#define CSR_MPU_H(n) (0x9f0 + (n)) +/* MPU attributes: set if permitted */ +/* Privilege, machine mode in RISC-V. We don't use the flag because + * we don't separate user / machine mode in EC OS. */ +#define MPU_ATTR_P BIT(5) +/* Readable */ +#define MPU_ATTR_R BIT(6) +/* Writable */ +#define MPU_ATTR_W BIT(7) +/* Cacheable */ +#define MPU_ATTR_C BIT(8) +/* Bufferable */ +#define MPU_ATTR_B BIT(9) + #endif /* __CROS_EC_CSR_H */ diff --git a/chip/mt8192_scp/memmap.c b/chip/mt8192_scp/memmap.c index 63fa4f8fc5..bfdbf17b33 100644 --- a/chip/mt8192_scp/memmap.c +++ b/chip/mt8192_scp/memmap.c @@ -3,6 +3,7 @@ * found in the LICENSE file. */ +#include "cache.h" #include "registers.h" #include "stdint.h" @@ -79,6 +80,8 @@ void memmap_init(void) (uint32_t)addr_map[0xd] << 8 | (uint32_t)addr_map[0xe] << 16 | (uint32_t)addr_map[0xf] << 24; + + cache_init(); } int memmap_ap_to_scp(uintptr_t ap_addr, uintptr_t *scp_addr) -- cgit v1.2.1