diff options
Diffstat (limited to 'chip/mt_scp/rv32i_common/cache.h')
-rw-r--r-- | chip/mt_scp/rv32i_common/cache.h | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/chip/mt_scp/rv32i_common/cache.h b/chip/mt_scp/rv32i_common/cache.h new file mode 100644 index 0000000000..13e5ad1a42 --- /dev/null +++ b/chip/mt_scp/rv32i_common/cache.h @@ -0,0 +1,140 @@ +/* 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 "common.h" +#include "csr.h" +#include "stdint.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 + +static inline void cache_op_all(uint32_t op) +{ + register int t0 asm("t0") = op; + asm volatile (".word "STRINGIFY(COP(5)) :: "r"(t0)); +} + +static inline 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; +} + +/* memory barrier of I$ */ +static inline void cache_barrier_icache(void) +{ + cache_op_all(COP_OP_BARRIER_ICACHE); +} + +/* invalidate all I$ */ +static inline void cache_invalidate_icache(void) +{ + cache_op_all(COP_OP_INVALIDATE_ICACHE); +} + +/* invalidate a range of I$ */ +static inline int cache_invalidate_icache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_INVALIDATE_ICACHE_ADDR); +} + +/* memory barrier of D$ */ +static inline void cache_barrier_dcache(void) +{ + cache_op_all(COP_OP_BARRIER_DCACHE); +} + +/* writeback all D$ */ +static inline void cache_writeback_dcache(void) +{ + cache_op_all(COP_OP_WRITEBACK_DCACHE); + cache_barrier_icache(); + cache_barrier_dcache(); +} + +/* writeback a range of D$ */ +static inline int cache_writeback_dcache_range(uintptr_t addr, uint32_t length) +{ + int ret = cache_op_addr(addr, length, COP_OP_WRITEBACK_DCACHE_ADDR); + cache_barrier_icache(); + cache_barrier_dcache(); + return ret; +} + +/* invalidate all D$ */ +static inline void cache_invalidate_dcache(void) +{ + cache_op_all(COP_OP_INVALIDATE_DCACHE); +} + +/* invalidate a range of D$ */ +static inline int cache_invalidate_dcache_range(uintptr_t addr, uint32_t length) +{ + return cache_op_addr(addr, length, COP_OP_INVALIDATE_DCACHE_ADDR); +} + +/* writeback and invalidate all D$ */ +static inline void cache_flush_dcache(void) +{ + cache_op_all(COP_OP_FLUSH_DCACHE); + cache_barrier_icache(); + cache_barrier_dcache(); +} + +/* writeback and invalidate a range of D$ */ +static inline int cache_flush_dcache_range(uintptr_t addr, uint32_t length) +{ + int ret = cache_op_addr(addr, length, COP_OP_FLUSH_DCACHE_ADDR); + cache_barrier_icache(); + cache_barrier_dcache(); + return ret; +} + +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; +}; + +void cache_init(void); + +#ifdef DEBUG +int command_enable_pmu(int argc, char **argv); +int command_disable_pmu(int argc, char **argv); +int command_show_pmu(int argc, char **argv); +#endif + +#endif /* #ifndef __CROS_EC_CACHE_H */ |