Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:05

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplClassicCache
0007  *
0008  * @brief This source file contains the Cache Manager implementation for
0009  *   devices using the ARM CP15.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2009, 2018 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <libcpu/arm-cp15.h>
0038 
0039 #include "cache-cp15.h"
0040 
0041 #define CPU_DATA_CACHE_ALIGNMENT 32
0042 
0043 #define CPU_INSTRUCTION_CACHE_ALIGNMENT 32
0044 
0045 #ifdef ARM_MULTILIB_CACHE_LINE_MAX_64
0046   #define CPU_MAXIMAL_CACHE_ALIGNMENT 64
0047 #endif
0048 
0049 #define CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS
0050 
0051 #define CPU_CACHE_SUPPORT_PROVIDES_CACHE_SIZE_FUNCTIONS
0052 
0053 #if __ARM_ARCH >= 7
0054   #define CPU_CACHE_SUPPORT_PROVIDES_DISABLE_DATA
0055 #endif
0056 
0057 #if __ARM_ARCH == 7 && __ARM_ARCH_PROFILE == 'R'
0058   #define CACHE_CP15_IS_CORTEX_R5
0059 #endif
0060 
0061 static inline void _CPU_cache_flush_1_data_line(const void *d_addr)
0062 {
0063   arm_cache_l1_flush_1_data_line(d_addr);
0064 }
0065 
0066 static inline void
0067 _CPU_cache_flush_data_range(
0068   const void *d_addr,
0069   size_t      n_bytes
0070 )
0071 {
0072   _ARM_Data_synchronization_barrier();
0073   arm_cache_l1_flush_data_range(
0074     d_addr,
0075     n_bytes
0076   );
0077 #if __ARM_ARCH < 7
0078   arm_cp15_drain_write_buffer();
0079 #endif
0080  _ARM_Data_synchronization_barrier();
0081 }
0082 
0083 static inline void _CPU_cache_invalidate_1_data_line(const void *d_addr)
0084 {
0085   arm_cache_l1_invalidate_1_data_line(d_addr);
0086 }
0087 
0088 static inline void
0089 _CPU_cache_invalidate_data_range(
0090   const void *addr_first,
0091   size_t     n_bytes
0092 )
0093 {
0094   arm_cache_l1_invalidate_data_range(
0095     addr_first,
0096     n_bytes
0097   );
0098 }
0099 
0100 static inline void _CPU_cache_freeze_data(void)
0101 {
0102   /* TODO */
0103 }
0104 
0105 static inline void _CPU_cache_unfreeze_data(void)
0106 {
0107   /* TODO */
0108 }
0109 
0110 static inline void _CPU_cache_invalidate_1_instruction_line(const void *d_addr)
0111 {
0112   arm_cache_l1_invalidate_1_instruction_line(d_addr);
0113 }
0114 
0115 static inline void
0116 _CPU_cache_invalidate_instruction_range( const void *i_addr, size_t n_bytes)
0117 {
0118   arm_cache_l1_invalidate_instruction_range( i_addr, n_bytes );
0119   _ARM_Instruction_synchronization_barrier();
0120 }
0121 
0122 static inline void _CPU_cache_freeze_instruction(void)
0123 {
0124   /* TODO */
0125 }
0126 
0127 static inline void _CPU_cache_unfreeze_instruction(void)
0128 {
0129   /* TODO */
0130 }
0131 
0132 static inline void _CPU_cache_flush_entire_data(void)
0133 {
0134   _ARM_Data_synchronization_barrier();
0135 #if defined(CACHE_CP15_IS_CORTEX_R5)
0136   arm_cp15_data_cache_clean_level(0);
0137 #elif __ARM_ARCH >= 7
0138   arm_cp15_data_cache_clean_all_levels();
0139 #else
0140   arm_cp15_data_cache_clean_and_invalidate();
0141   arm_cp15_drain_write_buffer();
0142 #endif
0143   _ARM_Data_synchronization_barrier();
0144 }
0145 
0146 static inline void _CPU_cache_invalidate_entire_data(void)
0147 {
0148 #if defined(CACHE_CP15_IS_CORTEX_R5)
0149   arm_cp15_data_cache_all_invalidate();
0150 #elif __ARM_ARCH >= 7
0151   arm_cp15_data_cache_invalidate_all_levels();
0152 #else
0153   arm_cp15_data_cache_invalidate();
0154 #endif
0155 }
0156 
0157 static inline void _CPU_cache_enable_data(void)
0158 {
0159   rtems_interrupt_level level;
0160   uint32_t ctrl;
0161 
0162   rtems_interrupt_local_disable(level);
0163   ctrl = arm_cp15_get_control();
0164   ctrl |= ARM_CP15_CTRL_C;
0165   arm_cp15_set_control(ctrl);
0166   rtems_interrupt_local_enable(level);
0167 }
0168 
0169 static inline void _CPU_cache_disable_data(void)
0170 {
0171   rtems_interrupt_level level;
0172   uint32_t ctrl;
0173 
0174   rtems_interrupt_local_disable(level);
0175   arm_cp15_data_cache_test_and_clean_and_invalidate();
0176   ctrl = arm_cp15_get_control();
0177   ctrl &= ~ARM_CP15_CTRL_C;
0178   arm_cp15_set_control(ctrl);
0179   rtems_interrupt_local_enable(level);
0180 }
0181 
0182 static inline void _CPU_cache_invalidate_entire_instruction(void)
0183 {
0184   arm_cache_l1_invalidate_entire_instruction();
0185   _ARM_Instruction_synchronization_barrier();
0186 }
0187 
0188 static inline void _CPU_cache_enable_instruction(void)
0189 {
0190   rtems_interrupt_level level;
0191   uint32_t ctrl;
0192 
0193   rtems_interrupt_local_disable(level);
0194   ctrl = arm_cp15_get_control();
0195   ctrl |= ARM_CP15_CTRL_I;
0196   arm_cp15_set_control(ctrl);
0197   rtems_interrupt_local_enable(level);
0198 }
0199 
0200 static inline void _CPU_cache_disable_instruction(void)
0201 {
0202   rtems_interrupt_level level;
0203   uint32_t ctrl;
0204 
0205   rtems_interrupt_local_disable(level);
0206   ctrl = arm_cp15_get_control();
0207   ctrl &= ~ARM_CP15_CTRL_I;
0208   arm_cp15_set_control(ctrl);
0209   rtems_interrupt_local_enable(level);
0210 }
0211 
0212 #if __ARM_ARCH >= 6
0213 static inline size_t arm_cp15_get_cache_size(
0214   uint32_t level,
0215   uint32_t which
0216 )
0217 {
0218   uint32_t clidr;
0219   uint32_t loc;
0220   uint32_t ccsidr;
0221 
0222   clidr = arm_cp15_get_cache_level_id();
0223   loc = arm_clidr_get_level_of_coherency(clidr);
0224 
0225   if (level == 0) {
0226     level = loc - 1;
0227   } else if (level - 1 >= loc) {
0228     return 0;
0229   } else {
0230     --level;
0231   }
0232 
0233   ccsidr = arm_cp15_get_cache_size_id_for_level(
0234     ARM_CP15_CACHE_CSS_LEVEL(level) | which
0235   );
0236 
0237   return (1U << arm_ccsidr_get_line_power(ccsidr))
0238     * arm_ccsidr_get_associativity(ccsidr)
0239     * arm_ccsidr_get_num_sets(ccsidr);
0240 }
0241 
0242 static inline size_t _CPU_cache_get_data_cache_size(uint32_t level)
0243 {
0244   return arm_cp15_get_cache_size(level, ARM_CP15_CACHE_CSS_ID_DATA);
0245 }
0246 
0247 static inline size_t _CPU_cache_get_instruction_cache_size(uint32_t level)
0248 {
0249   return arm_cp15_get_cache_size(level, ARM_CP15_CACHE_CSS_ID_INSTRUCTION);
0250 }
0251 #else
0252 static inline size_t _CPU_cache_get_data_cache_size(uint32_t level)
0253 {
0254   uint32_t cache_type;
0255 
0256   if (level > 0) {
0257     return 0;
0258   }
0259 
0260   cache_type = arm_cp15_get_cache_type();
0261   return 1U << (((cache_type >> (12 + 6)) & 0xf) + 9);
0262 }
0263 
0264 static inline size_t _CPU_cache_get_instruction_cache_size(uint32_t level)
0265 {
0266   uint32_t cache_type;
0267 
0268   if (level > 0) {
0269     return 0;
0270   }
0271 
0272   cache_type = arm_cp15_get_cache_type();
0273   return 1U << (((cache_type >> (0 + 6)) & 0xf) + 9);
0274 }
0275 #endif
0276 
0277 #include "../../shared/cache/cacheimpl.h"