/* * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved. * * SPDX-License-Identifier: MIT */ #ifndef RISCV_CACHE_H #define RISCV_CACHE_H #include "riscv_encoding.h" #define MCACHE_CTL_IC_EN (1<<0) #define MCACHE_CTL_IC_SCPD_MOD (1<<1) #define MCACHE_CTL_IC_ECC_EN (1<<2) #define MCACHE_CTL_IC_ECC_EXCP_EN (1<<3) #define MCACHE_CTL_IC_TRAM_ECC_INJ_EN (1<<4) #define MCACHE_CTL_IC_RWTECC (1<<4) #define MCACHE_CTL_IC_RWDECC (1<<5) #define MCACHE_CTL_IC_DRAM_ECC_INJ_EN (1<<5) #define MCACHE_CTL_IC_PF_EN (1<<6) #define MCACHE_CTL_IC_CANCEL_EN (1<<7) #define MCACHE_CTL_IC_ECC_CHK_EN (1<<8) #define MCACHE_CTL_DC_EN (1<<16) #define MCACHE_CTL_DC_ECC_EN (1<<17) #define MCACHE_CTL_DC_ECC_EXCP_EN (1<<18) #define MCACHE_CTL_DC_TRAM_ECC_INJ_EN (1<<19) #define MCACHE_CTL_DC_RWTECC (1<<19) #define MCACHE_CTL_DC_RWDECC (1<<20) #define MCACHE_CTL_DC_DRAM_ECC_INJ_EN (1<<20) #define MCACHE_CTL_DC_ECC_CHK_EN (1<<21) #define MCFG_INFO_ICACHE (1<<9) #define MCFG_INFO_DCACHE (1<<10) #define __FENCE(p, s) __asm volatile ("fence " #p "," #s : : : "memory") #define __RWMB() __FENCE(iorw, iorw) /*!< Lock Succeed */ /*!< Exceed the number of lockable ways(N-Way I/D-Cache, lockable is N-1) */ /*!< PMP/sPMP/Page-Table X(I-Cache)/R(D-Cache) permission check failed, * or belong to Device/Non-Cacheable address range */ /*!< Refill has Bus Error */ typedef enum CCM_OP_FINFO { CCM_OP_SUCCESS = 0x0, CCM_OP_EXCEED_ERR = 0x1, CCM_OP_PERM_CHECK_ERR = 0x2, CCM_OP_REFILL_BUS_ERR = 0x3, } CCM_OP_FINFO_Type; /*!< Unlock and invalidate D-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Flush the specific D-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Unlock, flush and invalidate the specific D-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Lock the specific D-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Unlock the specific D-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Unlock and flush and invalidate all the valid and dirty D-Cache lines */ /*!< Flush all the valid and dirty D-Cache lines */ /*!< Unlock and invalidate all the D-Cache lines */ /*!< Unlock and invalidate I-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Lock the specific I-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Unlock the specific I-Cache line specified by CSR CCM_XBEGINADDR */ /*!< Unlock and invalidate all the I-Cache lines */ typedef enum CCM_CMD { CCM_DC_INVAL = 0x0, CCM_DC_WB = 0x1, CCM_DC_WBINVAL = 0x2, CCM_DC_LOCK = 0x3, CCM_DC_UNLOCK = 0x4, CCM_DC_WBINVAL_ALL = 0x6, CCM_DC_WB_ALL = 0x7, CCM_DC_INVAL_ALL = 0x17, CCM_IC_INVAL = 0x8, CCM_IC_LOCK = 0xb, CCM_IC_UNLOCK = 0xc, CCM_IC_INVAL_ALL = 0xd } CCM_CMD_Type; /** * brief Flush pipeline after CCM operation * details * This function is used to flush pipeline after CCM operations * on Cache, it will ensure latest instructions or data can be * seen by pipeline. * remarks * This function can be called in M/S/U-Mode only. */ static inline void vFlushPipeCCM(void) { write_csr(ccm_fpipe, 0x1); } /** * brief Check DCache Unit Present or Not * details * This function check dcache unit present or not via mcfg_info csr * remarks * This function might not work for some old nuclei processors * Please make sure the version of your nuclei processor contain DCACHE bit in mcfg_info * return 1 if present otherwise 0 */ static inline uint32_t ulDCachePresent(void) { if (read_csr(mcfg_info) & MCFG_INFO_DCACHE) return 1; return 0; } /** * brief Enable DCache * details * This function enable D-Cache * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control D Cache enable. * sa * ref vDisableDCache */ static inline void vEnableDCache(void) { set_csr(mcache_ctl, MCACHE_CTL_DC_EN); } /** * brief Disable DCache * details * This function Disable D-Cache * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control D Cache enable. * sa * ref vEnableDCache */ static inline void vDisableDCache(void) { clear_csr(mcache_ctl, MCACHE_CTL_DC_EN); } /** * brief Enable DCache ECC * details * This function enable D-Cache ECC * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control D Cache ECC enable. * sa * ref vDisableDCacheECC */ static inline void vEnableDCacheECC(void) { set_csr(mcache_ctl, MCACHE_CTL_DC_ECC_EN); } /** * brief Disable DCache ECC * details * This function disable D-Cache ECC * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control D Cache ECC enable. * sa * ref EnableDCacheECC */ static inline void vDisableDCacheECC(void) { clear_csr(mcache_ctl, MCACHE_CTL_DC_ECC_EN); } /** * brief Invalidate one D-Cache line specified by address in M-Mode * details * This function unlock and invalidate one D-Cache line specified * by the address. * Command \ref CCM_DC_INVAL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be invalidated */ static inline void vMInvalDCacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_DC_INVAL); vFlushPipeCCM(); __RWMB(); } /** * brief Invalidate several D-Cache lines specified by address in M-Mode * details * This function unlock and invalidate several D-Cache lines specified * by the address and line count. * Command \ref CCM_DC_INVAL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be invalidated * param [in] cnt count of cache lines to be invalidated */ static inline void vMInvalDCacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) write_csr(ccm_mcommand, CCM_DC_INVAL); vFlushPipeCCM(); __RWMB(); } } /** * brief Flush one D-Cache line specified by address in M-Mode * details * This function flush one D-Cache line specified by the address. * Command \ref CCM_DC_WB is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be flushed */ static inline void vMFlushDCacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_DC_WB); vFlushPipeCCM(); __RWMB(); } /** * brief Flush several D-Cache lines specified by address in M-Mode * details * This function flush several D-Cache lines specified * by the address and line count. * Command ref CCM_DC_WB is written to CSR ref ccm_mcommand. * \remarks * This function must be executed in M-Mode only. * param [in] addr start address to be flushed * param [in] cnt count of cache lines to be flushed */ static inline void vMFlushDCacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) write_csr(ccm_mcommand, CCM_DC_WB); vFlushPipeCCM(); __RWMB(); } } /** * brief Flush and invalidate one D-Cache line specified by address in M-Mode * details * This function flush and invalidate one D-Cache line specified by the address. * Command \ref CCM_DC_WBINVAL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be flushed and invalidated */ static inline void vMFlushInvalDCacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_DC_WBINVAL); vFlushPipeCCM(); __RWMB(); } /** * brief Flush and invalidate several D-Cache lines specified by address in M-Mode * details * This function flush and invalidate several D-Cache lines specified * by the address and line count. * Command \ref CCM_DC_WBINVAL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be flushed and invalidated * param [in] cnt count of cache lines to be flushed and invalidated */ static inline void vMFlushInvalDCacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) write_csr(ccm_mcommand, CCM_DC_WBINVAL); vFlushPipeCCM(); __RWMB(); } } /** * brief Lock one D-Cache line specified by address in M-Mode * details * This function lock one D-Cache line specified by the address. * Command \ref CCM_DC_LOCK is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be locked * return result of CCM lock operation, see enum \ref CCM_OP_FINFO */ static inline unsigned long ulMLockDCacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_DC_LOCK); vFlushPipeCCM(); __RWMB(); return read_csr(ccm_mdata); } /** * brief Lock several D-Cache lines specified by address in M-Mode * details * This function lock several D-Cache lines specified by the address * and line count. * Command \ref CCM_DC_LOCK is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be locked * param [in] cnt count of cache lines to be locked * return result of CCM lock operation, see enum \ref CCM_OP_FINFO */ static inline unsigned long ulMLockDCacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; unsigned long fail_info = CCM_OP_SUCCESS; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) { write_csr(ccm_mcommand, CCM_DC_LOCK); vFlushPipeCCM(); __RWMB(); fail_info = read_csr(ccm_mdata); if (CCM_OP_SUCCESS != fail_info) return fail_info; } } return CCM_OP_SUCCESS; } /** * brief Unlock one D-Cache line specified by address in M-Mode * details * This function unlock one D-Cache line specified by the address. * Command \ref CCM_DC_UNLOCK is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be unlocked */ static inline void MUnlockDCacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_DC_UNLOCK); vFlushPipeCCM(); __RWMB(); } /** * brief Unlock several D-Cache lines specified by address in M-Mode * details * This function unlock several D-Cache lines specified * by the address and line count. * Command \ref CCM_DC_UNLOCK is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be unlocked * param [in] cnt count of cache lines to be unlocked */ static inline void vMUnlockDCacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) write_csr(ccm_mcommand, CCM_DC_UNLOCK); vFlushPipeCCM(); __RWMB(); } } /** * brief Invalidate all D-Cache lines in M-Mode * details * This function invalidate all D-Cache lines. * Command \ref CCM_DC_INVAL_ALL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be invalidated */ static inline void vMInvalDCache(void) { write_csr(ccm_mcommand, CCM_DC_INVAL_ALL); vFlushPipeCCM(); __RWMB(); } /** * brief Flush all D-Cache lines in M-Mode * details * This function flush all D-Cache lines. * Command \ref CCM_DC_WB_ALL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be flushed */ static inline void vMFlushDCache(void) { write_csr(ccm_mcommand, CCM_DC_WB_ALL); vFlushPipeCCM(); __RWMB(); } /** * brief Flush and invalidate all D-Cache lines in M-Mode * details * This function flush and invalidate all D-Cache lines. * Command \ref CCM_DC_WBINVAL_ALL is written to CSR \ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be flushed and locked */ static inline void vMFlushInvalDCache(void) { write_csr(ccm_mcommand, CCM_DC_WBINVAL_ALL); vFlushPipeCCM(); __RWMB(); } /** * brief Check ICache Unit Present or Not * details * This function check icache unit present or not via mcfg_info csr * remarks * This function might not work for some old nuclei processors * Please make sure the version of your nuclei processor contain ICACHE bit in mcfg_info * return 1 if present otherwise 0 */ static inline uint32_t ulICachePresent(void) { if (read_csr(mcfg_info) & MCFG_INFO_ICACHE) return 1; return 0; } /** * brief Enable ICache * details * This function enable I-Cache * remarks * This function can be called in M-Mode only. * This ref mcache_ctl register control I Cache enable. * sa * ref vDisableICache */ static inline void vEnableICache(void) { set_csr(mcache_ctl, MCACHE_CTL_IC_EN); } /** * brief Disable ICache * details * This function Disable I-Cache * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control I Cache enable. * sa * ref vEnableICache */ static inline void vDisableICache(void) { clear_csr(mcache_ctl, MCACHE_CTL_IC_EN); } /** * brief Enable ICache ECC * details * This function enable I-Cache ECC * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control I Cache ECC enable. * sa * ref vDisableICacheECC */ static inline void vEnableICacheECC(void) { set_csr(mcache_ctl, MCACHE_CTL_IC_ECC_EN); } /** * brief Disable ICache ECC * details * This function disable I-Cache ECC * remarks * This function can be called in M-Mode only. * This \ref mcache_ctl register control I Cache ECC enable. * sa * ref vEnableICacheECC */ static inline void vDisableICacheECC(void) { clear_csr(mcache_ctl, MCACHE_CTL_IC_ECC_EN); } /** * brief Invalidate one I-Cache line specified by address in M-Mode * details * This function unlock and invalidate one I-Cache line specified * by the address. * Command ref CCM_IC_INVAL is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be invalidated */ static inline void vMInvalICacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_IC_INVAL); vFlushPipeCCM(); __RWMB(); } /** * brief Invalidate several I-Cache lines specified by address in M-Mode * details * This function unlock and invalidate several I-Cache lines specified * by the address and line count. * Command ref CCM_IC_INVAL is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be invalidated * param [in] cnt count of cache lines to be invalidated */ static inline void vMInvalICacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) write_csr(ccm_mcommand, CCM_IC_INVAL); vFlushPipeCCM(); __RWMB(); } } /** * brief Invalidate all I-Cache lines in M-Mode * details * This function invalidate all I-Cache lines. * Command ref CCM_IC_INVAL_ALL is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be invalidated */ static inline void vMInvalICache(void) { write_csr(ccm_mcommand, CCM_IC_INVAL_ALL); vFlushPipeCCM(); __RWMB(); } /** * brief Lock one I-Cache line specified by address in M-Mode * details * This function lock one I-Cache line specified by the address. * Command ref CCM_IC_LOCK is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be locked * return result of CCM lock operation, see enum ref CCM_OP_FINFO */ static inline unsigned long ulMLockICacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_IC_LOCK); vFlushPipeCCM(); __RWMB(); return read_csr(ccm_mdata); } /** * brief Lock several I-Cache lines specified by address in M-Mode * details * This function lock several I-Cache lines specified by the address * and line count. * Command ref CCM_IC_LOCK is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be locked * param [in] cnt count of cache lines to be locked * return result of CCM lock operation, see enum ref CCM_OP_FINFO */ static inline unsigned long ulMLockICacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; unsigned long fail_info = CCM_OP_SUCCESS; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) { write_csr(ccm_mcommand, CCM_IC_LOCK); vFlushPipeCCM(); __RWMB(); fail_info = read_csr(ccm_mdata); if (CCM_OP_SUCCESS != fail_info) return fail_info; } } return CCM_OP_SUCCESS; } /** * brief Unlock one I-Cache line specified by address in M-Mode * details * This function unlock one I-Cache line specified by the address. * Command ref CCM_IC_UNLOCK is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be unlocked */ static inline void vMUnlockICacheLine(unsigned long addr) { write_csr(ccm_mbeginaddr, addr); write_csr(ccm_mcommand, CCM_IC_UNLOCK); vFlushPipeCCM(); __RWMB(); } /** * brief Unlock several I-Cache lines specified by address in M-Mode * details * This function unlock several I-Cache lines specified * by the address and line count. * Command ref CCM_IC_UNLOCK is written to CSR ref ccm_mcommand. * remarks * This function must be executed in M-Mode only. * param [in] addr start address to be unlocked * param [in] cnt count of cache lines to be unlocked */ static inline void vMUnlockICacheLines(unsigned long addr, unsigned long cnt) { if (cnt > 0) { unsigned long i; write_csr(ccm_mbeginaddr, addr); for (i = 0; i < cnt; i++) write_csr(ccm_mcommand, CCM_IC_UNLOCK); vFlushPipeCCM(); __RWMB(); } } #endif