summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@chromium.org>2020-11-02 17:54:48 +0800
committerCommit Bot <commit-bot@chromium.org>2020-11-17 12:07:50 +0000
commiteaaa61604170980a43a583efcfd359520db3176f (patch)
tree46a45f33bbcd5541e04e13461095418f55c77629
parent3ec81a13f83eb8f08166f6cbad3fe8471ef4537a (diff)
downloadchrome-ec-eaaa61604170980a43a583efcfd359520db3176f.tar.gz
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 <tzungbi@chromium.org> Change-Id: I3fd3d8f858a172bf26dfec6a5c6c403d73164039 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2513414 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--chip/mt8192_scp/build.mk1
-rw-r--r--chip/mt8192_scp/cache.c142
-rw-r--r--chip/mt8192_scp/cache.h45
-rw-r--r--chip/mt8192_scp/csr.h21
-rw-r--r--chip/mt8192_scp/memmap.c3
5 files changed, 212 insertions, 0 deletions
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)