diff options
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_mpu.c')
-rw-r--r-- | FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_mpu.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_mpu.c b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_mpu.c new file mode 100644 index 000000000..1e5b55e76 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_mpu.c @@ -0,0 +1,327 @@ +/******************************************************************************* + * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions. + * + * SPDX-License-Identifier: MIT + * + * MPFS HAL Embedded Software + * + */ +/******************************************************************************* + * @file mss_mpu.c + * @author Microchip-FPGA Embedded Systems Solutions + * @brief PolarFire SoC MSS MPU driver for configuring access regions for the + * external masters. + * + */ +/*=========================================================================*//** + + *//*=========================================================================*/ +#include <stdio.h> +#include <string.h> +#include "mpfs_hal/mss_hal.h" + +#ifndef SIFIVE_HIFIVE_UNLEASHED + +static uint64_t pmp_get_napot_base_and_range(uint64_t reg, uint64_t *range); + +uint8_t num_pmp_lut[10U] = {16U,16U,8U,4U,8U,8U,4U,4U,8U,2U}; + +/** + * \brief MPU configuration from Libero for FIC0 + * + */ +const uint64_t mpu_fic0_values[] = { + LIBERO_SETTING_FIC0_MPU_CFG_PMP0, + LIBERO_SETTING_FIC0_MPU_CFG_PMP1, + LIBERO_SETTING_FIC0_MPU_CFG_PMP2, + LIBERO_SETTING_FIC0_MPU_CFG_PMP3, + LIBERO_SETTING_FIC0_MPU_CFG_PMP4, + LIBERO_SETTING_FIC0_MPU_CFG_PMP5, + LIBERO_SETTING_FIC0_MPU_CFG_PMP6, + LIBERO_SETTING_FIC0_MPU_CFG_PMP7, + LIBERO_SETTING_FIC0_MPU_CFG_PMP8, + LIBERO_SETTING_FIC0_MPU_CFG_PMP9, + LIBERO_SETTING_FIC0_MPU_CFG_PMP10, + LIBERO_SETTING_FIC0_MPU_CFG_PMP11, + LIBERO_SETTING_FIC0_MPU_CFG_PMP12, + LIBERO_SETTING_FIC0_MPU_CFG_PMP13, + LIBERO_SETTING_FIC0_MPU_CFG_PMP14, + LIBERO_SETTING_FIC0_MPU_CFG_PMP15 +}; + +/** + * \brief MPU configuration from Libero for FIC1 + * + */ +const uint64_t mpu_fic1_values[] = { + LIBERO_SETTING_FIC1_MPU_CFG_PMP0, + LIBERO_SETTING_FIC1_MPU_CFG_PMP1, + LIBERO_SETTING_FIC1_MPU_CFG_PMP2, + LIBERO_SETTING_FIC1_MPU_CFG_PMP3, + LIBERO_SETTING_FIC1_MPU_CFG_PMP4, + LIBERO_SETTING_FIC1_MPU_CFG_PMP5, + LIBERO_SETTING_FIC1_MPU_CFG_PMP6, + LIBERO_SETTING_FIC1_MPU_CFG_PMP7, + LIBERO_SETTING_FIC1_MPU_CFG_PMP8, + LIBERO_SETTING_FIC1_MPU_CFG_PMP9, + LIBERO_SETTING_FIC1_MPU_CFG_PMP10, + LIBERO_SETTING_FIC1_MPU_CFG_PMP11, + LIBERO_SETTING_FIC1_MPU_CFG_PMP12, + LIBERO_SETTING_FIC1_MPU_CFG_PMP13, + LIBERO_SETTING_FIC1_MPU_CFG_PMP14, + LIBERO_SETTING_FIC1_MPU_CFG_PMP15 +}; + +/** + * \brief MPU configuration from Libero for FIC2 + * + */ +const uint64_t mpu_fic2_values[] = { + LIBERO_SETTING_FIC2_MPU_CFG_PMP0, + LIBERO_SETTING_FIC2_MPU_CFG_PMP1, + LIBERO_SETTING_FIC2_MPU_CFG_PMP2, + LIBERO_SETTING_FIC2_MPU_CFG_PMP3, + LIBERO_SETTING_FIC2_MPU_CFG_PMP4, + LIBERO_SETTING_FIC2_MPU_CFG_PMP5, + LIBERO_SETTING_FIC2_MPU_CFG_PMP6, + LIBERO_SETTING_FIC2_MPU_CFG_PMP7, +}; + +/** + * \brief MPU configuration from Libero for ATHENA + * + */ +const uint64_t mpu_crypto_values[] = { + LIBERO_SETTING_CRYPTO_MPU_CFG_PMP0, + LIBERO_SETTING_CRYPTO_MPU_CFG_PMP1, + LIBERO_SETTING_CRYPTO_MPU_CFG_PMP2, + LIBERO_SETTING_CRYPTO_MPU_CFG_PMP3, +}; + +/** + * \brief MPU configuration from Libero for GEM0 + * + */ +const uint64_t mpu_gem0_values[] = { + LIBERO_SETTING_GEM0_MPU_CFG_PMP0, + LIBERO_SETTING_GEM0_MPU_CFG_PMP1, + LIBERO_SETTING_GEM0_MPU_CFG_PMP2, + LIBERO_SETTING_GEM0_MPU_CFG_PMP3, + LIBERO_SETTING_GEM0_MPU_CFG_PMP4, + LIBERO_SETTING_GEM0_MPU_CFG_PMP5, + LIBERO_SETTING_GEM0_MPU_CFG_PMP6, + LIBERO_SETTING_GEM0_MPU_CFG_PMP7, +}; + +/** + * \brief MPU configuration from Libero for GEM1 + * + */ +const uint64_t mpu_gem1_values[] = { + LIBERO_SETTING_GEM1_MPU_CFG_PMP0, + LIBERO_SETTING_GEM1_MPU_CFG_PMP1, + LIBERO_SETTING_GEM1_MPU_CFG_PMP2, + LIBERO_SETTING_GEM1_MPU_CFG_PMP3, + LIBERO_SETTING_GEM1_MPU_CFG_PMP4, + LIBERO_SETTING_GEM1_MPU_CFG_PMP5, + LIBERO_SETTING_GEM1_MPU_CFG_PMP6, + LIBERO_SETTING_GEM1_MPU_CFG_PMP7, +}; + +/** + * \brief MPU configuration from Libero for MMC + * + */ +const uint64_t mpu_mmc_values[] = { + LIBERO_SETTING_MMC_MPU_CFG_PMP0, + LIBERO_SETTING_MMC_MPU_CFG_PMP1, + LIBERO_SETTING_MMC_MPU_CFG_PMP2, + LIBERO_SETTING_MMC_MPU_CFG_PMP3, +}; + +/** + * \brief MPU configuration from Libero for SCB + * + */ +const uint64_t mpu_scb_values[] = { + LIBERO_SETTING_SCB_MPU_CFG_PMP0, + LIBERO_SETTING_SCB_MPU_CFG_PMP1, + LIBERO_SETTING_SCB_MPU_CFG_PMP2, + LIBERO_SETTING_SCB_MPU_CFG_PMP3, + LIBERO_SETTING_SCB_MPU_CFG_PMP4, + LIBERO_SETTING_SCB_MPU_CFG_PMP5, + LIBERO_SETTING_SCB_MPU_CFG_PMP6, + LIBERO_SETTING_SCB_MPU_CFG_PMP7, +}; + +/** + * \brief MPU configuration from Libero for USB + * + */ +const uint64_t mpu_usb_values[] = { + LIBERO_SETTING_USB_MPU_CFG_PMP0, + LIBERO_SETTING_USB_MPU_CFG_PMP1, + LIBERO_SETTING_USB_MPU_CFG_PMP2, + LIBERO_SETTING_USB_MPU_CFG_PMP3, +}; + +/** + * \brief MPU configuration from Libero for TRACE + * + */ +const uint64_t mpu_trace_values[] = { + LIBERO_SETTING_TRACE_MPU_CFG_PMP0, + LIBERO_SETTING_TRACE_MPU_CFG_PMP1, +}; + + +/***************************************************************************//** + * MSS_MPU_auto_configure() + * Set MPU's up with configuration from Libero + * + * + * @return + */ +uint8_t mpu_configure(void) +{ + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_FIC0)->PMPCFG)), + &(mpu_fic0_values), + sizeof(mpu_fic0_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_FIC1)->PMPCFG)), + &(mpu_fic1_values), + sizeof(mpu_fic1_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_FIC2)->PMPCFG)), + &(mpu_fic2_values), + sizeof(mpu_fic2_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_CRYPTO)->PMPCFG)), + &(mpu_crypto_values), + sizeof(mpu_crypto_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_GEM0)->PMPCFG)), + &(mpu_gem0_values), + sizeof(mpu_gem0_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_GEM1)->PMPCFG)), + &(mpu_gem1_values), + sizeof(mpu_gem1_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_USB)->PMPCFG)), + &(mpu_usb_values), + sizeof(mpu_usb_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_MMC)->PMPCFG)), + &(mpu_mmc_values), + sizeof(mpu_mmc_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_SCB)->PMPCFG)), + &(mpu_scb_values), + sizeof(mpu_scb_values)); + + config_64_copy((void *)(&(MSS_MPU(MSS_MPU_TRACE)->PMPCFG)), + &(mpu_trace_values), + sizeof(mpu_trace_values)); + + return(0); +} + + + + + +/***************************************************************************//** +*/ +uint8_t MSS_MPU_configure(mss_mpu_mport_t master_port, + mss_mpu_pmp_region_t pmp_region, + uint64_t base, + uint64_t size, + uint8_t permission, + mss_mpu_addrm_t matching_mode, + uint8_t lock_en) +{ + uint64_t temp = size, cnt=0ULL; + uint64_t range; + + /*size must be minimum 4k + Size must be power of 2 + different masters have different number of regions*/ + if((size >= 4096ULL) && (0U == (size & (size - 1U))) && (pmp_region < num_pmp_lut[master_port])) + { + while((0 == (temp & 0x01U))) + { + cnt++; + temp >>= 1U; + } + + range = (1ULL << (cnt-1U))-1U; + + MSS_MPU(master_port)->PMPCFG[pmp_region].raw = (base | range) >> 2U; + + MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode = (uint8_t)(permission | + (uint8_t)(matching_mode << 3U) | + (lock_en << 0x7U)); + + return ((uint8_t)0); + } + else + { + return ((uint8_t)1); + } +} + +uint8_t MSS_MPU_get_config(mss_mpu_mport_t master_port, + mss_mpu_pmp_region_t pmp_region, + uint64_t* base, + uint64_t* size, + uint8_t* permission, + mss_mpu_addrm_t* matching_mode, + uint8_t* lock_en) +{ + uint64_t reg; + + /*All AXI external masters dont have same number of PMP regions*/ + if(pmp_region < num_pmp_lut[master_port]) + { + reg = MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.pmp; + *base = pmp_get_napot_base_and_range(reg, size); + + reg = MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode; + *lock_en = ( reg >> 0x7U) & 0x1U; + *matching_mode = (mss_mpu_addrm_t)( (reg >> 3ULL) & 0x3U); + *permission = reg & 0x7U; + + return ((uint8_t)0); + } + else + { + return ((uint8_t)1); + } +} + +static uint64_t pmp_get_napot_base_and_range(uint64_t reg, uint64_t *range) +{ + /* construct a mask of all bits bar the top bit */ + uint64_t mask = 0U; + uint64_t base = reg; + uint64_t numbits = (sizeof(uint64_t) * 8U) + 2U; + mask = (mask - 1U) >> 1U; + + while (mask) + { + if ((reg & mask) == mask) + { + /* this is the mask to use */ + base = reg & ~mask; + break; + } + mask >>= 1U; + numbits--; + } + + *range = (1LU << numbits); + return (base << 2U); +} + +#endif |