1 /******************************************************************************* 2 * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions. 3 * 4 * SPDX-License-Identifier: MIT 5 * 6 * MPFS HAL Embedded Software 7 * 8 */ 9 /******************************************************************************* 10 * @file mss_l2_cache.c 11 * @author Microchip-FPGA Embedded Systems Solutions 12 * @brief The code in this file is executed before any code/data sections are 13 * copied. This code must not rely sdata/data section content. Hence, global 14 * variables should not be used unless they are constants. 15 * 16 */ 17 /*============================================================================== 18 * 19 */ 20 21 #include <stdio.h> 22 #include <string.h> 23 #include "mpfs_hal/mss_hal.h" 24 #include "mss_l2_cache.h" 25 26 /*============================================================================== 27 * Local defines 28 */ 29 #if (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) 30 static const uint64_t g_init_marker = INIT_MARKER; 31 #endif 32 33 /*============================================================================== 34 * Local functions. 35 */ 36 static void check_config_l2_scratchpad(void); 37 38 39 /*============================================================================== 40 * This code should only be executed from E51 to be functional. 41 * Configure the L2 cache memory: 42 * - Set the number of cache ways used as cache based on the MSS Configurator 43 * settings. 44 * - Configure some of the enabled ways as scratchpad based on linker 45 * configuration and space allocated by configurator. 46 */ config_l2_cache(void)47__attribute__((weak)) void config_l2_cache(void) 48 { 49 ASSERT(LIBERO_SETTING_WAY_ENABLE < 16U); 50 51 /* 52 * Set the number of ways that will be shared between cache and scratchpad. 53 */ 54 CACHE_CTRL->WAY_ENABLE = LIBERO_SETTING_WAY_ENABLE; 55 56 /* 57 * shutdown L2 as directed 58 */ 59 SYSREG->L2_SHUTDOWN_CR = LIBERO_SETTING_L2_SHUTDOWN_CR; 60 61 /* The scratchpad has already been set-up, first check enough space before copying */ 62 check_config_l2_scratchpad(); 63 64 /* If you are not using scratchpad, no need to include the following code */ 65 66 ASSERT(LIBERO_SETTING_WAY_ENABLE >= LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS); 67 68 69 70 /* 71 * Compute the mask used to specify ways that will be used by the 72 * scratchpad. 73 */ 74 75 uint32_t scratchpad_ways_mask = 0U; 76 #if (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) 77 uint32_t inc; 78 uint32_t seed_ways_mask = 0x1U << LIBERO_SETTING_WAY_ENABLE; 79 for(inc = 0; inc < LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS; ++inc) 80 { 81 scratchpad_ways_mask |= (seed_ways_mask >> inc) ; 82 } 83 #else 84 (void)scratchpad_ways_mask; 85 #endif 86 87 /* 88 * Make sure ways are masked if being used as scratchpad 89 */ 90 ASSERT((LIBERO_SETTING_WAY_MASK_DMA & scratchpad_ways_mask) == 0UL); 91 ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_0 & scratchpad_ways_mask) == 0UL); 92 ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_1 & scratchpad_ways_mask) == 0UL); 93 ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_2 & scratchpad_ways_mask) == 0UL); 94 ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_3 & scratchpad_ways_mask) == 0UL); 95 ASSERT((LIBERO_SETTING_WAY_MASK_E51_DCACHE & scratchpad_ways_mask) == 0UL); 96 ASSERT((LIBERO_SETTING_WAY_MASK_E51_ICACHE & scratchpad_ways_mask) == 0UL); 97 ASSERT((LIBERO_SETTING_WAY_MASK_U54_1_DCACHE & scratchpad_ways_mask) == 0UL); 98 ASSERT((LIBERO_SETTING_WAY_MASK_U54_2_DCACHE & scratchpad_ways_mask) == 0UL); 99 ASSERT((LIBERO_SETTING_WAY_MASK_U54_3_DCACHE & scratchpad_ways_mask) == 0UL); 100 ASSERT((LIBERO_SETTING_WAY_MASK_U54_4_DCACHE & scratchpad_ways_mask) == 0UL); 101 ASSERT((LIBERO_SETTING_WAY_MASK_U54_1_ICACHE & scratchpad_ways_mask) == 0UL); 102 ASSERT((LIBERO_SETTING_WAY_MASK_U54_2_ICACHE & scratchpad_ways_mask) == 0UL); 103 ASSERT((LIBERO_SETTING_WAY_MASK_U54_3_ICACHE & scratchpad_ways_mask) == 0UL); 104 ASSERT((LIBERO_SETTING_WAY_MASK_U54_4_ICACHE & scratchpad_ways_mask) == 0UL); 105 106 /* 107 * Setup all masters, apart from one we are using to setup scratch 108 */ 109 CACHE_CTRL->WAY_MASK_DMA = LIBERO_SETTING_WAY_MASK_DMA; 110 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_0 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_0; 111 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_1 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_1; 112 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_2 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_2; 113 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_3 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_3; 114 CACHE_CTRL->WAY_MASK_E51_ICACHE = LIBERO_SETTING_WAY_MASK_E51_ICACHE; 115 CACHE_CTRL->WAY_MASK_U54_1_DCACHE = LIBERO_SETTING_WAY_MASK_U54_1_DCACHE; 116 CACHE_CTRL->WAY_MASK_U54_1_ICACHE = LIBERO_SETTING_WAY_MASK_U54_1_ICACHE; 117 CACHE_CTRL->WAY_MASK_U54_2_DCACHE = LIBERO_SETTING_WAY_MASK_U54_2_DCACHE; 118 CACHE_CTRL->WAY_MASK_U54_2_ICACHE = LIBERO_SETTING_WAY_MASK_U54_2_ICACHE; 119 CACHE_CTRL->WAY_MASK_U54_3_DCACHE = LIBERO_SETTING_WAY_MASK_U54_3_DCACHE; 120 CACHE_CTRL->WAY_MASK_U54_3_ICACHE = LIBERO_SETTING_WAY_MASK_U54_3_ICACHE; 121 CACHE_CTRL->WAY_MASK_U54_4_DCACHE = LIBERO_SETTING_WAY_MASK_U54_4_DCACHE; 122 CACHE_CTRL->WAY_MASK_U54_4_ICACHE = LIBERO_SETTING_WAY_MASK_U54_4_ICACHE; 123 124 #if (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) 125 /* 126 * Assign ways to Zero Device 127 */ 128 uint64_t * p_scratchpad = (uint64_t *)ZERO_DEVICE_BOTTOM; 129 uint32_t ways_inc; 130 uint64_t current_way = 0x1U << (((LIBERO_SETTING_WAY_ENABLE + 1U) - LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS) ); 131 for(ways_inc = 0; ways_inc < LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS; ++ways_inc) 132 { 133 /* 134 * Populate the scratchpad memory one way at a time. 135 */ 136 CACHE_CTRL->WAY_MASK_E51_DCACHE = current_way; 137 mb(); 138 /* 139 * Write to the first 64-bit location of each cache block. 140 */ 141 for(inc = 0; inc < (WAY_BYTE_LENGTH / CACHE_BLOCK_BYTE_LENGTH); ++inc) 142 { 143 *p_scratchpad = g_init_marker + inc; 144 p_scratchpad += CACHE_BLOCK_BYTE_LENGTH / UINT64_BYTE_LENGTH; 145 } 146 current_way = current_way << 1U; 147 mb(); 148 } 149 #endif /* (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) */ 150 /* 151 * Prevent E51 from evicting from scratchpad ways. 152 */ 153 CACHE_CTRL->WAY_MASK_E51_DCACHE = LIBERO_SETTING_WAY_MASK_E51_DCACHE; 154 mb(); 155 156 } 157 158 159 /*============================================================================== 160 * Configure the L2 scratchpad based on linker symbols: 161 * __l2_scratchpad_vma_start 162 * __l2_scratchpad_vma_end 163 * 164 * These linker symbols specify the start address and length of the scratchpad. 165 * The scratchpad must be located within the Zero Device memory range. 166 */ check_config_l2_scratchpad(void)167static void check_config_l2_scratchpad(void) 168 { 169 extern char __l2_scratchpad_vma_start; 170 extern char __l2_scratchpad_vma_end; 171 172 uint8_t n_scratchpad_ways; 173 const uint64_t end = (const uint64_t)&__l2_scratchpad_vma_end; 174 const uint64_t start = (const uint64_t)&__l2_scratchpad_vma_start; 175 uint64_t modulo; 176 177 ASSERT(start >= (uint64_t)ZERO_DEVICE_BOTTOM); 178 ASSERT(end < (uint64_t)ZERO_DEVICE_TOP); 179 ASSERT(end >= start); 180 181 /* 182 * Figure out how many cache ways will be required from linker script 183 * symbols. 184 */ 185 n_scratchpad_ways = (uint8_t)((end - start) / WAY_BYTE_LENGTH); 186 modulo = (end - start) % WAY_BYTE_LENGTH; 187 if(modulo > 0) 188 { 189 ++n_scratchpad_ways; 190 } 191 192 ASSERT(LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS >= n_scratchpad_ways); 193 } 194 195 #if 0 // todo - remove, no longer used 196 197 198 /*============================================================================== 199 * Reserve a number of cache ways to be used as scratchpad memory. 200 * 201 * @param nways 202 * Number of ways to be used as scratchpad. One way is 128Kbytes. 203 * 204 * @param scratchpad_start 205 * Start address within the Zero Device memory range in which the scratchpad 206 * will be located. 207 */ 208 static void reserve_scratchpad_ways(uint8_t nways, uint64_t * scratchpad_start) 209 { 210 uint8_t way_enable; 211 uint64_t available_ways = 1; 212 uint64_t scratchpad_ways = 0; 213 uint64_t non_scratchpad_ways; 214 uint32_t inc; 215 216 ASSERT(scratchpad_start >= (uint64_t *)ZERO_DEVICE_BOTTOM); 217 ASSERT(scratchpad_start < (uint64_t *)ZERO_DEVICE_TOP); 218 219 /* 220 * Ensure at least one way remains available as cache. 221 */ 222 way_enable = CACHE_CTRL->WAY_ENABLE; 223 ASSERT(nways <= way_enable); 224 if(nways <= way_enable) 225 { 226 /* 227 * Compute the mask used to specify ways that will be used by the 228 * scratchpad. 229 */ 230 231 for(inc = 0; inc < way_enable; ++inc) 232 { 233 available_ways = (available_ways << 1) | (uint64_t)0x01; 234 if(inc < nways) 235 { 236 scratchpad_ways = (scratchpad_ways << 1) | (uint64_t)0x01; 237 } 238 } 239 240 /* 241 * Prevent other masters from evicting cache lines from scratchpad ways. 242 * Only allow E51 to evict from scratchpad ways. 243 */ 244 non_scratchpad_ways = available_ways & ~scratchpad_ways; 245 246 CACHE_CTRL->WAY_MASK_DMA = non_scratchpad_ways; 247 248 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_0 = non_scratchpad_ways; 249 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_1 = non_scratchpad_ways; 250 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_2 = non_scratchpad_ways; 251 CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_3 = non_scratchpad_ways; 252 253 CACHE_CTRL->WAY_MASK_E51_ICACHE = non_scratchpad_ways; 254 255 CACHE_CTRL->WAY_MASK_U54_1_DCACHE = non_scratchpad_ways; 256 CACHE_CTRL->WAY_MASK_U54_1_ICACHE = non_scratchpad_ways; 257 258 CACHE_CTRL->WAY_MASK_U54_2_DCACHE = non_scratchpad_ways; 259 CACHE_CTRL->WAY_MASK_U54_2_ICACHE = non_scratchpad_ways; 260 261 CACHE_CTRL->WAY_MASK_U54_3_DCACHE = non_scratchpad_ways; 262 CACHE_CTRL->WAY_MASK_U54_3_ICACHE = non_scratchpad_ways; 263 264 CACHE_CTRL->WAY_MASK_U54_4_DCACHE = non_scratchpad_ways; 265 CACHE_CTRL->WAY_MASK_U54_4_ICACHE = non_scratchpad_ways; 266 267 /* 268 * Assign ways to Zero Device 269 */ 270 uint64_t * p_scratchpad = scratchpad_start; 271 int ways_inc; 272 uint64_t current_way = 1; 273 for(ways_inc = 0; ways_inc < nways; ++ways_inc) 274 { 275 /* 276 * Populate the scratchpad memory one way at a time. 277 */ 278 CACHE_CTRL->WAY_MASK_E51_DCACHE = current_way; 279 /* 280 * Write to the first 64-bit location of each cache block. 281 */ 282 for(inc = 0; inc < (WAY_BYTE_LENGTH / CACHE_BLOCK_BYTE_LENGTH); ++inc) 283 { 284 *p_scratchpad = g_init_marker + inc; 285 p_scratchpad += CACHE_BLOCK_BYTE_LENGTH / UINT64_BYTE_LENGTH; 286 } 287 current_way = current_way << 1U; 288 mb(); 289 } 290 291 /* 292 * Prevent E51 from evicting from scratchpad ways. 293 */ 294 CACHE_CTRL->WAY_MASK_E51_DCACHE = non_scratchpad_ways; 295 } 296 } 297 #endif 298