/* ------------------------------------------ * Copyright (c) 2016, Synopsys, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1) Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * \version 2016.05 * \date 2014-07-15 * \author Wayne Ren(Wei.Ren@synopsys.com) --------------------------------------------- */ /** * \file * \ingroup ARC_HAL_MISC_CACHE * \brief header file of cache module */ #ifndef _ARC_HAL_CACHE_H_ #define _ARC_HAL_CACHE_H_ #include "inc/embARC_toolchain.h" #include "inc/arc/arc.h" #include "inc/arc/arc_builtin.h" #include "inc/arc/arc_exception.h" /** * \name instruction cache control register related definition * \todo this definitions will be reviewed. * @{ */ #define IC_CTRL_IC_ENABLE 0x0 /*!< enable instruction cache */ #define IC_CTRL_IC_DISABLE 0x1 /*!< disable instruction cache */ #define IC_CTRL_DIRECT_ACCESS 0x0 /*!< direct access mode */ #define IC_CTRL_INDIRECT_ACCESS 0x20 /*!< indirect access mode */ #define IC_CTRL_OP_SUCCEEDED 0x8 /*!< instruction cache operation succeeded */ /** @} */ /** * \name data cache control register related definition * \todo this definition will be reviewed. * @{ */ #define IC_CTRL_I #define DC_CTRL_DC_ENABLE 0x0 /*!< enable data cache */ #define DC_CTRL_DC_DISABLE 0x1 /*!< disable data cache */ #define DC_CTRL_INVALID_ONLY 0x0 /*!< invalid data cache only */ #define DC_CTRL_INVALID_FLUSH 0x40 /*!< invalid and flush data cache */ #define DC_CTRL_ENABLE_FLUSH_LOCKED 0x80 /*!< the locked data cache can be flushed */ #define DC_CTRL_DISABLE_FLUSH_LOCKED 0x0 /*!< the locked data cache cannot be flushed */ #define DC_CTRL_FLUSH_STATUS 0x100 /*!< flush status */ #define DC_CTRL_DIRECT_ACCESS 0x0 /*!< direct access mode */ #define DC_CTRL_INDIRECT_ACCESS 0x20 /*!< indirect access mode */ #define DC_CTRL_OP_SUCCEEDED 0x4 /*!< data cache operation succeeded */ /** @} */ /** * \name instruction cache related inline function * @{ */ /** * \brief check whether instruction cache is available, * 0 for not available, >0 for available */ Inline uint8_t icache_available(void) { return (_arc_aux_read(AUX_BCR_I_CACHE) & 0xF); } /** * \brief enable instruction cache * \param[in] icache_en_mask operation mask */ Inline void icache_enable(uint32_t icache_en_mask) { if (!icache_available()) return; _arc_aux_write(AUX_IC_CTRL, icache_en_mask); } /** * \brief disable instruction cache */ Inline void icache_disable(void) { if (!icache_available()) return; _arc_aux_write(AUX_IC_CTRL, IC_CTRL_IC_DISABLE); } /** * \brief invalidate the entire instruction cache */ Inline void icache_invalidate(void) { if (!icache_available()) return; /* invalidate the entire icache */ _arc_aux_write(AUX_IC_IVIC, 0); Asm("nop_s"); Asm("nop_s"); Asm("nop_s"); } /** * \brief invalidate specific cache line * \param[in] address memory address */ Inline void icache_invalidate_line(uint32_t address) { if (!icache_available()) return; _arc_aux_write(AUX_IC_IVIL, address); /* the 3 nops are required by ARCv2 ISA */ Asm("nop_s"); Asm("nop_s"); Asm("nop_s"); } /** * \brief lock specific cache line * \param[in] address memory address * \return 0, succeeded, -1, failed */ Inline int32_t icache_lock_line(uint32_t address) { if (!icache_available()) return -1; _arc_aux_write(AUX_IC_LIL, address); if(_arc_aux_read(AUX_IC_CTRL) & IC_CTRL_OP_SUCCEEDED) { return 0; } else { return -1; } } /** * \brief set icache access mode * \param[in] mode, access mode, 1: indirect access 0:direct access */ Inline void icache_access_mode(uint32_t mode) { if (!icache_available()) return; if (mode) { _arc_aux_write(AUX_IC_CTRL, _arc_aux_read(AUX_IC_CTRL) | IC_CTRL_INDIRECT_ACCESS); } else { _arc_aux_write(AUX_IC_CTRL, _arc_aux_read(AUX_IC_CTRL) & (~IC_CTRL_INDIRECT_ACCESS)); } } /** @} */ /** * \name data cache related inline functions * @{ */ /** * \brief check whether data cache is available, * 0 for not available, >0 for available */ Inline uint8_t dcache_available(void) { return (_arc_aux_read(AUX_BCR_D_CACHE) & 0xF); } /** * \brief invalidate the entire data cache */ Inline void dcache_invalidate(void) { if (!dcache_available()) return; uint32_t status; status = cpu_lock_save(); _arc_aux_write(AUX_DC_IVDC, 1); /* wait for flush completion */ while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); cpu_unlock_restore(status); } /** * \brief invalidate the specific cache line * \param[in] address memory address */ Inline void dcache_invalidate_line(uint32_t address) { if (!dcache_available()) return; _arc_aux_write(AUX_DC_IVDL, address); Asm("nop_s"); Asm("nop_s"); Asm("nop_s"); } /** * \brief enable data cache * \param[in] dcache_en_mask operation mask */ Inline void dcache_enable(uint32_t dcache_en_mask) { if (!dcache_available()) return; _arc_aux_write(AUX_DC_CTRL, dcache_en_mask); } /** * \brief disable data cache */ Inline void dcache_disable(void) { if (!dcache_available()) return; _arc_aux_write(AUX_DC_CTRL, DC_CTRL_DC_DISABLE); } /** * \brief flush data cache */ Inline void dcache_flush(void) { if (!dcache_available()) return; uint32_t status; status = cpu_lock_save(); _arc_aux_write(AUX_DC_FLSH, 1); /* wait for flush completion */ while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); cpu_unlock_restore(status); } /** * \brief flush the specific data cache line * \param[in] address memory address */ Inline void dcache_flush_line(uint32_t address) { if (!dcache_available()) return; uint32_t status; status = cpu_lock_save(); _arc_aux_write(AUX_DC_FLDL, address); while (_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); cpu_unlock_restore(status); } /** * \brief lock the specific data cache line * \param[in] address memory address * \return 0, succeeded, -1, failed */ Inline int dcache_lock_line(uint32_t address) { if (!dcache_available()) return -1; _arc_aux_write(AUX_DC_LDL, address); if(_arc_aux_read(AUX_DC_CTRL) & DC_CTRL_OP_SUCCEEDED) { return 0; } else { return -1; } } /** * \brief set dcache access mode * \param[in] mode, access mode, 1: indirect access 0:direct access */ Inline void dcache_access_mode(uint32_t mode) { if (!dcache_available()) return; if (mode) { _arc_aux_write(AUX_DC_CTRL, _arc_aux_read(AUX_DC_CTRL) | DC_CTRL_INDIRECT_ACCESS); } else { _arc_aux_write(AUX_DC_CTRL, _arc_aux_read(AUX_DC_CTRL) & (~DC_CTRL_INDIRECT_ACCESS)); } } /** @} */ #ifdef __cplusplus extern "C" { #endif /** * \name declarations of cache related functions * @{ */ extern int32_t icache_invalidate_mlines(uint32_t start_addr, uint32_t size); extern int32_t icache_lock_mlines(uint32_t start_addr, uint32_t size); extern int32_t icache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data); extern int32_t icache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data); extern int32_t icache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data); extern int32_t dcache_invalidate_mlines(uint32_t start_addr, uint32_t size); extern int32_t dcache_flush_mlines(uint32_t start_addr, uint32_t size); extern int32_t dcache_lock_mlines(uint32_t start_addr, uint32_t size); extern int32_t dcache_direct_write(uint32_t cache_addr, uint32_t tag, uint32_t data); extern int32_t dcache_direct_read(uint32_t cache_addr, uint32_t *tag, uint32_t *data); extern int32_t dcache_indirect_read(uint32_t mem_addr, uint32_t *tag, uint32_t *data); extern void arc_cache_init(void); #ifdef __cplusplus } #endif /** @} */ #endif /* _ARC_HAL_CACHE_H_ */