diff options
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_l2_cache.c')
-rw-r--r-- | FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_l2_cache.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_l2_cache.c b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_l2_cache.c new file mode 100644 index 000000000..d51efed04 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_l2_cache.c @@ -0,0 +1,297 @@ +/******************************************************************************* + * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions. + * + * SPDX-License-Identifier: MIT + * + * MPFS HAL Embedded Software + * + */ +/******************************************************************************* + * @file mss_l2_cache.c + * @author Microchip-FPGA Embedded Systems Solutions + * @brief The code in this file is executed before any code/data sections are + * copied. This code must not rely sdata/data section content. Hence, global + * variables should not be used unless they are constants. + * + */ +/*============================================================================== + * + */ + +#include <stdio.h> +#include <string.h> +#include "mpfs_hal/mss_hal.h" +#include "mss_l2_cache.h" + +/*============================================================================== + * Local defines + */ +#if (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) +static const uint64_t g_init_marker = INIT_MARKER; +#endif + +/*============================================================================== + * Local functions. + */ +static void check_config_l2_scratchpad(void); + + +/*============================================================================== + * This code should only be executed from E51 to be functional. + * Configure the L2 cache memory: + * - Set the number of cache ways used as cache based on the MSS Configurator + * settings. + * - Configure some of the enabled ways as scratchpad based on linker + * configuration and space allocated by configurator. + */ +__attribute__((weak)) void config_l2_cache(void) +{ + ASSERT(LIBERO_SETTING_WAY_ENABLE < 16U); + + /* + * Set the number of ways that will be shared between cache and scratchpad. + */ + CACHE_CTRL->WAY_ENABLE = LIBERO_SETTING_WAY_ENABLE; + + /* + * shutdown L2 as directed + */ + SYSREG->L2_SHUTDOWN_CR = LIBERO_SETTING_L2_SHUTDOWN_CR; + + /* The scratchpad has already been set-up, first check enough space before copying */ + check_config_l2_scratchpad(); + + /* If you are not using scratchpad, no need to include the following code */ + + ASSERT(LIBERO_SETTING_WAY_ENABLE >= LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS); + + + + /* + * Compute the mask used to specify ways that will be used by the + * scratchpad. + */ + + uint32_t scratchpad_ways_mask = 0U; +#if (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) + uint32_t inc; + uint32_t seed_ways_mask = 0x1U << LIBERO_SETTING_WAY_ENABLE; + for(inc = 0; inc < LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS; ++inc) + { + scratchpad_ways_mask |= (seed_ways_mask >> inc) ; + } +#else + (void)scratchpad_ways_mask; +#endif + + /* + * Make sure ways are masked if being used as scratchpad + */ + ASSERT((LIBERO_SETTING_WAY_MASK_DMA & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_0 & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_1 & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_2 & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_AXI4_PORT_3 & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_E51_DCACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_E51_ICACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_1_DCACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_2_DCACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_3_DCACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_4_DCACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_1_ICACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_2_ICACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_3_ICACHE & scratchpad_ways_mask) == 0UL); + ASSERT((LIBERO_SETTING_WAY_MASK_U54_4_ICACHE & scratchpad_ways_mask) == 0UL); + + /* + * Setup all masters, apart from one we are using to setup scratch + */ + CACHE_CTRL->WAY_MASK_DMA = LIBERO_SETTING_WAY_MASK_DMA; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_0 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_0; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_1 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_1; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_2 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_2; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_3 = LIBERO_SETTING_WAY_MASK_AXI4_PORT_3; + CACHE_CTRL->WAY_MASK_E51_ICACHE = LIBERO_SETTING_WAY_MASK_E51_ICACHE; + CACHE_CTRL->WAY_MASK_U54_1_DCACHE = LIBERO_SETTING_WAY_MASK_U54_1_DCACHE; + CACHE_CTRL->WAY_MASK_U54_1_ICACHE = LIBERO_SETTING_WAY_MASK_U54_1_ICACHE; + CACHE_CTRL->WAY_MASK_U54_2_DCACHE = LIBERO_SETTING_WAY_MASK_U54_2_DCACHE; + CACHE_CTRL->WAY_MASK_U54_2_ICACHE = LIBERO_SETTING_WAY_MASK_U54_2_ICACHE; + CACHE_CTRL->WAY_MASK_U54_3_DCACHE = LIBERO_SETTING_WAY_MASK_U54_3_DCACHE; + CACHE_CTRL->WAY_MASK_U54_3_ICACHE = LIBERO_SETTING_WAY_MASK_U54_3_ICACHE; + CACHE_CTRL->WAY_MASK_U54_4_DCACHE = LIBERO_SETTING_WAY_MASK_U54_4_DCACHE; + CACHE_CTRL->WAY_MASK_U54_4_ICACHE = LIBERO_SETTING_WAY_MASK_U54_4_ICACHE; + +#if (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) + /* + * Assign ways to Zero Device + */ + uint64_t * p_scratchpad = (uint64_t *)ZERO_DEVICE_BOTTOM; + uint32_t ways_inc; + uint64_t current_way = 0x1U << (((LIBERO_SETTING_WAY_ENABLE + 1U) - LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS) ); + for(ways_inc = 0; ways_inc < LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS; ++ways_inc) + { + /* + * Populate the scratchpad memory one way at a time. + */ + CACHE_CTRL->WAY_MASK_E51_DCACHE = current_way; + mb(); + /* + * Write to the first 64-bit location of each cache block. + */ + for(inc = 0; inc < (WAY_BYTE_LENGTH / CACHE_BLOCK_BYTE_LENGTH); ++inc) + { + *p_scratchpad = g_init_marker + inc; + p_scratchpad += CACHE_BLOCK_BYTE_LENGTH / UINT64_BYTE_LENGTH; + } + current_way = current_way << 1U; + mb(); + } +#endif /* (LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS != 0) */ + /* + * Prevent E51 from evicting from scratchpad ways. + */ + CACHE_CTRL->WAY_MASK_E51_DCACHE = LIBERO_SETTING_WAY_MASK_E51_DCACHE; + mb(); + +} + + +/*============================================================================== + * Configure the L2 scratchpad based on linker symbols: + * __l2_scratchpad_vma_start + * __l2_scratchpad_vma_end + * + * These linker symbols specify the start address and length of the scratchpad. + * The scratchpad must be located within the Zero Device memory range. + */ +static void check_config_l2_scratchpad(void) +{ + extern char __l2_scratchpad_vma_start; + extern char __l2_scratchpad_vma_end; + + uint8_t n_scratchpad_ways; + const uint64_t end = (const uint64_t)&__l2_scratchpad_vma_end; + const uint64_t start = (const uint64_t)&__l2_scratchpad_vma_start; + uint64_t modulo; + + ASSERT(start >= (uint64_t)ZERO_DEVICE_BOTTOM); + ASSERT(end < (uint64_t)ZERO_DEVICE_TOP); + ASSERT(end >= start); + + /* + * Figure out how many cache ways will be required from linker script + * symbols. + */ + n_scratchpad_ways = (uint8_t)((end - start) / WAY_BYTE_LENGTH); + modulo = (end - start) % WAY_BYTE_LENGTH; + if(modulo > 0) + { + ++n_scratchpad_ways; + } + + ASSERT(LIBERO_SETTING_NUM_SCRATCH_PAD_WAYS >= n_scratchpad_ways); +} + +#if 0 // todo - remove, no longer used + + +/*============================================================================== + * Reserve a number of cache ways to be used as scratchpad memory. + * + * @param nways + * Number of ways to be used as scratchpad. One way is 128Kbytes. + * + * @param scratchpad_start + * Start address within the Zero Device memory range in which the scratchpad + * will be located. + */ +static void reserve_scratchpad_ways(uint8_t nways, uint64_t * scratchpad_start) +{ + uint8_t way_enable; + uint64_t available_ways = 1; + uint64_t scratchpad_ways = 0; + uint64_t non_scratchpad_ways; + uint32_t inc; + + ASSERT(scratchpad_start >= (uint64_t *)ZERO_DEVICE_BOTTOM); + ASSERT(scratchpad_start < (uint64_t *)ZERO_DEVICE_TOP); + + /* + * Ensure at least one way remains available as cache. + */ + way_enable = CACHE_CTRL->WAY_ENABLE; + ASSERT(nways <= way_enable); + if(nways <= way_enable) + { + /* + * Compute the mask used to specify ways that will be used by the + * scratchpad. + */ + + for(inc = 0; inc < way_enable; ++inc) + { + available_ways = (available_ways << 1) | (uint64_t)0x01; + if(inc < nways) + { + scratchpad_ways = (scratchpad_ways << 1) | (uint64_t)0x01; + } + } + + /* + * Prevent other masters from evicting cache lines from scratchpad ways. + * Only allow E51 to evict from scratchpad ways. + */ + non_scratchpad_ways = available_ways & ~scratchpad_ways; + + CACHE_CTRL->WAY_MASK_DMA = non_scratchpad_ways; + + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_0 = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_1 = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_2 = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_AXI4_SLAVE_PORT_3 = non_scratchpad_ways; + + CACHE_CTRL->WAY_MASK_E51_ICACHE = non_scratchpad_ways; + + CACHE_CTRL->WAY_MASK_U54_1_DCACHE = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_U54_1_ICACHE = non_scratchpad_ways; + + CACHE_CTRL->WAY_MASK_U54_2_DCACHE = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_U54_2_ICACHE = non_scratchpad_ways; + + CACHE_CTRL->WAY_MASK_U54_3_DCACHE = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_U54_3_ICACHE = non_scratchpad_ways; + + CACHE_CTRL->WAY_MASK_U54_4_DCACHE = non_scratchpad_ways; + CACHE_CTRL->WAY_MASK_U54_4_ICACHE = non_scratchpad_ways; + + /* + * Assign ways to Zero Device + */ + uint64_t * p_scratchpad = scratchpad_start; + int ways_inc; + uint64_t current_way = 1; + for(ways_inc = 0; ways_inc < nways; ++ways_inc) + { + /* + * Populate the scratchpad memory one way at a time. + */ + CACHE_CTRL->WAY_MASK_E51_DCACHE = current_way; + /* + * Write to the first 64-bit location of each cache block. + */ + for(inc = 0; inc < (WAY_BYTE_LENGTH / CACHE_BLOCK_BYTE_LENGTH); ++inc) + { + *p_scratchpad = g_init_marker + inc; + p_scratchpad += CACHE_BLOCK_BYTE_LENGTH / UINT64_BYTE_LENGTH; + } + current_way = current_way << 1U; + mb(); + } + + /* + * Prevent E51 from evicting from scratchpad ways. + */ + CACHE_CTRL->WAY_MASK_E51_DCACHE = non_scratchpad_ways; + } +} +#endif |