forked from Imagelibrary/rtems
bsps/xil: Import Xilinx Cortex-R5 support
This imports Xilinx support code for the MPU and cache on Cortex-R5 cores. This was imported as specified in bsps/shared/xil/VERSION.
This commit is contained in:
committed by
Joel Sherrill
parent
b8f1988f15
commit
7ea60d29d8
117
bsps/include/xil/arm/cortexr5/xil_mpu.h
Normal file
117
bsps/include/xil/arm/cortexr5/xil_mpu.h
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @file xil_mmu.h
|
||||||
|
*
|
||||||
|
* @addtogroup r5_mpu_apis Cortex R5 Processor MPU specific APIs
|
||||||
|
*
|
||||||
|
* MPU functions provides access to MPU operations such as enable MPU, disable
|
||||||
|
* MPU and set attribute for section of memory.
|
||||||
|
* Boot code invokes Init_MPU function to configure the MPU. A total of 10 MPU
|
||||||
|
* regions are allocated with another 6 being free for users. Overview of the
|
||||||
|
* memory attributes for different MPU regions is as given below,
|
||||||
|
*
|
||||||
|
*| | Memory Range | Attributes of MPURegion |
|
||||||
|
*|-----------------------|-------------------------|-----------------------------|
|
||||||
|
*| DDR | 0x00000000 - 0x7FFFFFFF | Normal write-back Cacheable |
|
||||||
|
*| PL | 0x80000000 - 0xBFFFFFFF | Strongly Ordered |
|
||||||
|
*| QSPI | 0xC0000000 - 0xDFFFFFFF | Device Memory |
|
||||||
|
*| PCIe | 0xE0000000 - 0xEFFFFFFF | Device Memory |
|
||||||
|
*| STM_CORESIGHT | 0xF8000000 - 0xF8FFFFFF | Device Memory |
|
||||||
|
*| RPU_R5_GIC | 0xF9000000 - 0xF90FFFFF | Device memory |
|
||||||
|
*| FPS | 0xFD000000 - 0xFDFFFFFF | Device Memory |
|
||||||
|
*| LPS | 0xFE000000 - 0xFFFFFFFF | Device Memory |
|
||||||
|
*| OCM | 0xFFFC0000 - 0xFFFFFFFF | Normal write-back Cacheable |
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* For a system where DDR is less than 2GB, region after DDR and before PL is
|
||||||
|
* marked as undefined in translation table. Memory range 0xFE000000-0xFEFFFFFF is
|
||||||
|
* allocated for upper LPS slaves, where as memory region 0xFF000000-0xFFFFFFFF is
|
||||||
|
* allocated for lower LPS slaves.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* <pre>
|
||||||
|
* MODIFICATION HISTORY:
|
||||||
|
*
|
||||||
|
* Ver Who Date Changes
|
||||||
|
* ----- ---- -------- ---------------------------------------------------
|
||||||
|
* 5.00 pkp 02/10/14 Initial version
|
||||||
|
* 6.4 asa 08/16/17 Added many APIs for MPU access to make MPU usage
|
||||||
|
* user-friendly. The APIs added are: Xil_UpdateMPUConfig,
|
||||||
|
* Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
|
||||||
|
* Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
|
||||||
|
* Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
|
||||||
|
* Xil_InitializeExistingMPURegConfig.
|
||||||
|
* Added a new array of structure of type XMpuConfig to
|
||||||
|
* represent the MPU configuration table.
|
||||||
|
* 7.7 sk 01/10/22 Modify Xil_SetTlbAttributes function argument name to fix
|
||||||
|
* misra_c_2012_rule_8_3 violation.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
/**
|
||||||
|
*@cond nocomments
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XIL_MPU_H
|
||||||
|
#define XIL_MPU_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#include "xil_types.h"
|
||||||
|
/***************************** Include Files *********************************/
|
||||||
|
|
||||||
|
/***************** Macros (Inline Functions) Definitions *********************/
|
||||||
|
#define MPU_REG_DISABLED 0U
|
||||||
|
#define MPU_REG_ENABLED 1U
|
||||||
|
#define MAX_POSSIBLE_MPU_REGS 16U
|
||||||
|
/**************************** Type Definitions *******************************/
|
||||||
|
struct XMpuConfig{
|
||||||
|
u32 RegionStatus; /* Enabled or disabled */
|
||||||
|
INTPTR BaseAddress;/* MPU region base address */
|
||||||
|
u64 Size; /* MPU region size address */
|
||||||
|
u32 Attribute; /* MPU region size attribute */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct XMpuConfig XMpu_Config[MAX_POSSIBLE_MPU_REGS];
|
||||||
|
|
||||||
|
extern XMpu_Config Mpu_Config;
|
||||||
|
/************************** Constant Definitions *****************************/
|
||||||
|
|
||||||
|
/************************** Variable Definitions *****************************/
|
||||||
|
|
||||||
|
/************************** Function Prototypes ******************************/
|
||||||
|
/**
|
||||||
|
*@endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Xil_SetTlbAttributes(INTPTR addr, u32 attrib);
|
||||||
|
void Xil_EnableMPU(void);
|
||||||
|
void Xil_DisableMPU(void);
|
||||||
|
u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib);
|
||||||
|
u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib);
|
||||||
|
void Xil_GetMPUConfig (XMpu_Config mpuconfig);
|
||||||
|
u32 Xil_GetNumOfFreeRegions (void);
|
||||||
|
u32 Xil_GetNextMPURegion(void);
|
||||||
|
u32 Xil_DisableMPURegionByRegNum (u32 reg_num);
|
||||||
|
u16 Xil_GetMPUFreeRegMask (void);
|
||||||
|
u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib);
|
||||||
|
void* Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* XIL_MPU_H */
|
||||||
|
/**
|
||||||
|
* @} End of "addtogroup r5_mpu_apis".
|
||||||
|
*/
|
||||||
561
bsps/shared/xil/arm/cortexr5/xil_cache.c
Normal file
561
bsps/shared/xil/arm/cortexr5/xil_cache.c
Normal file
@@ -0,0 +1,561 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @file xil_cache.c
|
||||||
|
*
|
||||||
|
* Contains required functions for the ARM cache functionality.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MODIFICATION HISTORY:
|
||||||
|
*
|
||||||
|
* Ver Who Date Changes
|
||||||
|
* ----- ---- -------- -----------------------------------------------
|
||||||
|
* 5.00 pkp 02/20/14 First release
|
||||||
|
* 6.2 mus 01/27/17 Updated to support IAR compiler
|
||||||
|
* 7.3 dp 06/25/20 Updated to support armclang compiler
|
||||||
|
* 7.7 sk 01/10/22 Update IRQ_FIQ_MASK macro from signed to unsigned
|
||||||
|
* to fix misra_c_2012_rule_10_4 violation.
|
||||||
|
* 7.7 sk 01/10/22 Typecast to fix wider essential type misra_c_2012_rule_10_7
|
||||||
|
* violation.
|
||||||
|
* 7.7 mus 02/21/22 Existing note in cache API's says, "bottom 4 bits of input
|
||||||
|
* address are forced to 0 as per architecture". As cache line
|
||||||
|
* length is of 32 byte, bottom 5 bits of input address would
|
||||||
|
* be forced to 0. Updated note to have correct details.
|
||||||
|
* It fixes CR#1122561.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/***************************** Include Files *********************************/
|
||||||
|
|
||||||
|
#include "xil_cache.h"
|
||||||
|
#include "xil_io.h"
|
||||||
|
#include "xpseudo_asm.h"
|
||||||
|
#include "xparameters.h"
|
||||||
|
#include "xreg_cortexr5.h"
|
||||||
|
#include "xil_exception.h"
|
||||||
|
|
||||||
|
|
||||||
|
/************************** Variable Definitions *****************************/
|
||||||
|
|
||||||
|
#define IRQ_FIQ_MASK 0xC0U /* Mask IRQ and FIQ interrupts in cpsr */
|
||||||
|
|
||||||
|
#if defined (__clang__)
|
||||||
|
extern s32 Image$$ARM_LIB_STACK$$Limit;
|
||||||
|
extern s32 Image$$ARM_UNDEF_STACK$$Base;
|
||||||
|
#elif defined (__GNUC__)
|
||||||
|
extern s32 _stack_end;
|
||||||
|
extern s32 __undef_stack;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/************************** Function Prototypes ******************************/
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Enable the Data cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheEnable(void)
|
||||||
|
{
|
||||||
|
register u32 CtrlReg;
|
||||||
|
|
||||||
|
/* enable caches only if they are disabled */
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
|
||||||
|
#endif
|
||||||
|
if ((CtrlReg & XREG_CP15_CONTROL_C_BIT)==0x00000000U) {
|
||||||
|
/* invalidate the Data cache */
|
||||||
|
Xil_DCacheInvalidate();
|
||||||
|
|
||||||
|
/* enable the Data cache */
|
||||||
|
CtrlReg |= (XREG_CP15_CONTROL_C_BIT);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Disable the Data cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheDisable(void)
|
||||||
|
{
|
||||||
|
register u32 CtrlReg;
|
||||||
|
|
||||||
|
/* clean and invalidate the Data cache */
|
||||||
|
Xil_DCacheFlush();
|
||||||
|
|
||||||
|
/* disable the Data cache */
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Invalidate the entire Data cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheInvalidate(void)
|
||||||
|
{
|
||||||
|
u32 currmask;
|
||||||
|
u32 stack_start,stack_end,stack_size;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
#if defined (__clang__)
|
||||||
|
stack_end = (u32 )&Image$$ARM_LIB_STACK$$Limit;
|
||||||
|
stack_start = (u32 )&Image$$ARM_UNDEF_STACK$$Base;
|
||||||
|
#elif defined (__GNUC__)
|
||||||
|
stack_end = (u32 )&_stack_end;
|
||||||
|
stack_start = (u32 )&__undef_stack;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
stack_size = stack_start-stack_end;
|
||||||
|
|
||||||
|
/* Flush stack memory to save return address */
|
||||||
|
Xil_DCacheFlushRange(stack_end, stack_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
|
||||||
|
|
||||||
|
/*invalidate all D cache*/
|
||||||
|
mtcp(XREG_CP15_INVAL_DC_ALL, 0);
|
||||||
|
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Invalidate a Data cache line. If the byte specified by the
|
||||||
|
* address (adr) is cached by the data cache, the cacheline
|
||||||
|
* containing that byte is invalidated.If the cacheline is modified
|
||||||
|
* (dirty), the modified contents are lost and are NOT written
|
||||||
|
* to system memory before the line is invalidated.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param adr: 32bit address of the data to be flushed.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
* @note The bottom 5 bits are set to 0, forced by architecture.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheInvalidateLine(INTPTR adr)
|
||||||
|
{
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
|
||||||
|
mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
|
||||||
|
|
||||||
|
/* Wait for invalidate to complete */
|
||||||
|
dsb();
|
||||||
|
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Invalidate the Data cache for the given address range.
|
||||||
|
* If the bytes specified by the address (adr) are cached by the
|
||||||
|
* Data cache,the cacheline containing that byte is invalidated.
|
||||||
|
* If the cacheline is modified (dirty), the modified contents are
|
||||||
|
* lost and are NOT written to system memory before the line is
|
||||||
|
* invalidated.
|
||||||
|
*
|
||||||
|
* @param adr: 32bit start address of the range to be invalidated.
|
||||||
|
* @param len: Length of range to be invalidated in bytes.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
|
||||||
|
{
|
||||||
|
const u32 cacheline = 32U;
|
||||||
|
u32 end;
|
||||||
|
u32 tempadr = adr;
|
||||||
|
u32 tempend;
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
if (len != 0U) {
|
||||||
|
end = tempadr + len;
|
||||||
|
tempend = end;
|
||||||
|
/* Select L1 Data cache in CSSR */
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
|
||||||
|
|
||||||
|
if ((tempadr & (cacheline-1U)) != 0U) {
|
||||||
|
tempadr &= (~(cacheline - 1U));
|
||||||
|
|
||||||
|
Xil_DCacheFlushLine(tempadr);
|
||||||
|
}
|
||||||
|
if ((tempend & (cacheline-1U)) != 0U) {
|
||||||
|
tempend &= (~(cacheline - 1U));
|
||||||
|
|
||||||
|
Xil_DCacheFlushLine(tempend);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (tempadr < tempend) {
|
||||||
|
|
||||||
|
/* Invalidate Data cache line */
|
||||||
|
asm_inval_dc_line_mva_poc(tempadr);
|
||||||
|
|
||||||
|
tempadr += cacheline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Flush the entire Data cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheFlush(void)
|
||||||
|
{
|
||||||
|
register u32 CsidReg, C7Reg;
|
||||||
|
u32 CacheSize, LineSize, NumWays;
|
||||||
|
u32 Way, WayIndex, Set, SetIndex, NumSet;
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
/* Select cache level 0 and D cache in CSSR */
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
|
||||||
|
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_CACHE_SIZE_ID,CsidReg);
|
||||||
|
#endif
|
||||||
|
/* Determine Cache Size */
|
||||||
|
|
||||||
|
CacheSize = (CsidReg >> 13U) & 0x000001FFU;
|
||||||
|
CacheSize += 0x00000001U;
|
||||||
|
CacheSize *= (u32)128; /* to get number of bytes */
|
||||||
|
|
||||||
|
/* Number of Ways */
|
||||||
|
NumWays = (CsidReg & 0x000003ffU) >> 3U;
|
||||||
|
NumWays += 0x00000001U;
|
||||||
|
|
||||||
|
/* Get the cacheline size, way size, index size from csidr */
|
||||||
|
LineSize = (CsidReg & 0x00000007U) + 0x00000004U;
|
||||||
|
|
||||||
|
NumSet = CacheSize/NumWays;
|
||||||
|
NumSet /= (((u32)0x00000001U) << LineSize);
|
||||||
|
|
||||||
|
Way = 0U;
|
||||||
|
Set = 0U;
|
||||||
|
|
||||||
|
/* Invalidate all the cachelines */
|
||||||
|
for (WayIndex = 0U; WayIndex < NumWays; WayIndex++) {
|
||||||
|
for (SetIndex = 0U; SetIndex < NumSet; SetIndex++) {
|
||||||
|
C7Reg = Way | Set;
|
||||||
|
/* Flush by Set/Way */
|
||||||
|
asm_clean_inval_dc_line_sw(C7Reg);
|
||||||
|
|
||||||
|
Set += (((u32)0x00000001U) << LineSize);
|
||||||
|
}
|
||||||
|
Set = 0U;
|
||||||
|
Way += 0x40000000U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for flush to complete */
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Flush a Data cache line. If the byte specified by the address (adr)
|
||||||
|
* is cached by the Data cache, the cacheline containing that byte is
|
||||||
|
* invalidated. If the cacheline is modified (dirty), the entire
|
||||||
|
* contents of the cacheline are written to system memory before the
|
||||||
|
* line is invalidated.
|
||||||
|
*
|
||||||
|
* @param adr: 32bit address of the data to be flushed.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
* @note The bottom 5 bits are set to 0, forced by architecture.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheFlushLine(INTPTR adr)
|
||||||
|
{
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
|
||||||
|
|
||||||
|
/* Wait for flush to complete */
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Flush the Data cache for the given address range.
|
||||||
|
* If the bytes specified by the address (adr) are cached by the
|
||||||
|
* Data cache, the cacheline containing those bytes is invalidated.If
|
||||||
|
* the cacheline is modified (dirty), the written to system memory
|
||||||
|
* before the lines are invalidated.
|
||||||
|
*
|
||||||
|
* @param adr: 32bit start address of the range to be flushed.
|
||||||
|
* @param len: Length of the range to be flushed in bytes
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheFlushRange(INTPTR adr, u32 len)
|
||||||
|
{
|
||||||
|
u32 LocalAddr = adr;
|
||||||
|
const u32 cacheline = 32U;
|
||||||
|
u32 end;
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
if (len != 0x00000000U) {
|
||||||
|
/* Back the starting address up to the start of a cache line
|
||||||
|
* perform cache operations until adr+len
|
||||||
|
*/
|
||||||
|
end = LocalAddr + len;
|
||||||
|
LocalAddr &= ~(cacheline - 1U);
|
||||||
|
|
||||||
|
while (LocalAddr < end) {
|
||||||
|
/* Flush Data cache line */
|
||||||
|
asm_clean_inval_dc_line_mva_poc(LocalAddr);
|
||||||
|
|
||||||
|
LocalAddr += cacheline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Store a Data cache line. If the byte specified by the address
|
||||||
|
* (adr) is cached by the Data cache and the cacheline is modified
|
||||||
|
* (dirty), the entire contents of the cacheline are written to
|
||||||
|
* system memory.After the store completes, the cacheline is marked
|
||||||
|
* as unmodified (not dirty).
|
||||||
|
*
|
||||||
|
* @param adr: 32bit address of the data to be stored
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
* @note The bottom 5 bits are set to 0, forced by architecture.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_DCacheStoreLine(INTPTR adr)
|
||||||
|
{
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
|
||||||
|
mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F)));
|
||||||
|
|
||||||
|
/* Wait for store to complete */
|
||||||
|
dsb();
|
||||||
|
isb();
|
||||||
|
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Enable the instruction cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_ICacheEnable(void)
|
||||||
|
{
|
||||||
|
register u32 CtrlReg;
|
||||||
|
|
||||||
|
/* enable caches only if they are disabled */
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL, CtrlReg);
|
||||||
|
#endif
|
||||||
|
if ((CtrlReg & XREG_CP15_CONTROL_I_BIT)==0x00000000U) {
|
||||||
|
/* invalidate the instruction cache */
|
||||||
|
mtcp(XREG_CP15_INVAL_IC_POU, 0);
|
||||||
|
|
||||||
|
/* enable the instruction cache */
|
||||||
|
CtrlReg |= (XREG_CP15_CONTROL_I_BIT);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Disable the instruction cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_ICacheDisable(void)
|
||||||
|
{
|
||||||
|
register u32 CtrlReg;
|
||||||
|
|
||||||
|
dsb();
|
||||||
|
|
||||||
|
/* invalidate the instruction cache */
|
||||||
|
mtcp(XREG_CP15_INVAL_IC_POU, 0);
|
||||||
|
|
||||||
|
/* disable the instruction cache */
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CtrlReg &= ~(XREG_CP15_CONTROL_I_BIT);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Invalidate the entire instruction cache.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_ICacheInvalidate(void)
|
||||||
|
{
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
|
||||||
|
|
||||||
|
/* invalidate the instruction cache */
|
||||||
|
mtcp(XREG_CP15_INVAL_IC_POU, 0);
|
||||||
|
|
||||||
|
/* Wait for invalidate to complete */
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Invalidate an instruction cache line.If the instruction specified
|
||||||
|
* by the address is cached by the instruction cache, the
|
||||||
|
* cacheline containing that instruction is invalidated.
|
||||||
|
*
|
||||||
|
* @param adr: 32bit address of the instruction to be invalidated.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
* @note The bottom 5 bits are set to 0, forced by architecture.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_ICacheInvalidateLine(INTPTR adr)
|
||||||
|
{
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 1);
|
||||||
|
mtcp(XREG_CP15_INVAL_IC_LINE_MVA_POU, (adr & (~0x1F)));
|
||||||
|
|
||||||
|
/* Wait for invalidate to complete */
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Invalidate the instruction cache for the given address range.
|
||||||
|
* If the bytes specified by the address (adr) are cached by the
|
||||||
|
* Data cache, the cacheline containing that byte is invalidated.
|
||||||
|
* If the cachelineis modified (dirty), the modified contents are
|
||||||
|
* lost and are NOT written to system memory before the line is
|
||||||
|
* invalidated.
|
||||||
|
*
|
||||||
|
* @param adr: 32bit start address of the range to be invalidated.
|
||||||
|
* @param len: Length of the range to be invalidated in bytes.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
|
||||||
|
{
|
||||||
|
u32 LocalAddr = adr;
|
||||||
|
const u32 cacheline = 32U;
|
||||||
|
u32 end;
|
||||||
|
u32 currmask;
|
||||||
|
|
||||||
|
currmask = mfcpsr();
|
||||||
|
mtcpsr(currmask | IRQ_FIQ_MASK);
|
||||||
|
if (len != 0x00000000U) {
|
||||||
|
/* Back the starting address up to the start of a cache line
|
||||||
|
* perform cache operations until adr+len
|
||||||
|
*/
|
||||||
|
end = LocalAddr + len;
|
||||||
|
LocalAddr = LocalAddr & ~(cacheline - 1U);
|
||||||
|
|
||||||
|
/* Select cache L0 I-cache in CSSR */
|
||||||
|
mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
|
||||||
|
|
||||||
|
while (LocalAddr < end) {
|
||||||
|
|
||||||
|
/* Invalidate L1 I-cache line */
|
||||||
|
asm_inval_ic_line_mva_pou(LocalAddr);
|
||||||
|
|
||||||
|
LocalAddr += cacheline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for invalidate to complete */
|
||||||
|
dsb();
|
||||||
|
mtcpsr(currmask);
|
||||||
|
}
|
||||||
641
bsps/shared/xil/arm/cortexr5/xil_mpu.c
Normal file
641
bsps/shared/xil/arm/cortexr5/xil_mpu.c
Normal file
@@ -0,0 +1,641 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) 2014 - 2022 Xilinx, Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @file xil_mpu.c
|
||||||
|
*
|
||||||
|
* This file provides APIs for enabling/disabling MPU and setting the memory
|
||||||
|
* attributes for sections, in the MPU translation table.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* MODIFICATION HISTORY:
|
||||||
|
*
|
||||||
|
* Ver Who Date Changes
|
||||||
|
* ----- ---- -------- ---------------------------------------------------
|
||||||
|
* 5.00 pkp 02/10/14 Initial version
|
||||||
|
* 6.2 mus 01/27/17 Updated to support IAR compiler
|
||||||
|
* 6.4 asa 08/16/17 Added many APIs for MPU access to make MPU usage
|
||||||
|
* user-friendly. The APIs added are: Xil_UpdateMPUConfig,
|
||||||
|
* Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
|
||||||
|
* Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
|
||||||
|
* Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
|
||||||
|
* Xil_InitializeExistingMPURegConfig.
|
||||||
|
* Added a new array of structure of type XMpuConfig to
|
||||||
|
* represent the MPU configuration table.
|
||||||
|
* 6.8 aru 07/02/18 Returned the pointer instead of address
|
||||||
|
* of that pointer in Xil_MemMap().
|
||||||
|
* 7.5 asa 03/01/21 Ensure that Mpu_Config does not stay in .boot/.vector
|
||||||
|
* sections which generally should be executable code
|
||||||
|
* which can be allocated and not written.
|
||||||
|
* Mpu_Config array is populated during boot time, hence
|
||||||
|
* cannot be placed in .bss or .data section. Putting
|
||||||
|
* Mpu_Config in a new .bootdata section.
|
||||||
|
* 7.7 sk 01/10/22 Update int to u32 to fix misrac misra_c_2012_directive_4_6
|
||||||
|
* violations.
|
||||||
|
* 7.7 sk 01/10/22 Typecast variables from signed to unsigned to fix
|
||||||
|
* misra_c_2012_rule_10_4 violation.
|
||||||
|
* 7.7 sk 01/10/22 Add explicit parentheses for region_size and region_size[0]
|
||||||
|
* to fix misra_c_2012_rule_12_1 violation.
|
||||||
|
* 7.7 sk 01/10/22 Remove unsigned sign to fix misra_c_2012_rule_10_3 violation.
|
||||||
|
* 7.7 sk 01/10/22 Modify if condition to fix misra_c_2012_rule_10_1 violation.
|
||||||
|
* 7.7 sk 01/10/22 Typecast to fix wider essential type misra_c_2012_rule_10_7
|
||||||
|
* violation.
|
||||||
|
* 7.7 sk 01/10/22 Update conditional expression to fix misra_c_2012_rule_14_4
|
||||||
|
* violation.
|
||||||
|
* 7.7 sk 01/10/22 Add braces for the if statement to make it a compound
|
||||||
|
* statement to fix misra_c_2012_rule_15_6 violation.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Origin: https://github.com/Xilinx/embeddedsw/blob/master/lib/bsp/standalone/src/arm/cortexr5/xil_mpu.c
|
||||||
|
* __rtems__ changes:
|
||||||
|
* - un-include xdebug.h and add macro for xdbg_printf
|
||||||
|
* - relocate XMpu_Config
|
||||||
|
* - form Xilinx link script section(".bootdata")
|
||||||
|
* - to RTEMS link script section(".bsp_start_data")
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************** Include Files *********************************/
|
||||||
|
|
||||||
|
#include "xil_cache.h"
|
||||||
|
#include "xpseudo_asm.h"
|
||||||
|
#include "xil_types.h"
|
||||||
|
#include "xil_mpu.h"
|
||||||
|
#ifndef __rtems__
|
||||||
|
#include "xdebug.h"
|
||||||
|
#else
|
||||||
|
#define xdbg_printf(...)
|
||||||
|
#endif
|
||||||
|
#include "xstatus.h"
|
||||||
|
/***************** Macros (Inline Functions) Definitions *********************/
|
||||||
|
|
||||||
|
/**************************** Type Definitions *******************************/
|
||||||
|
|
||||||
|
/************************** Constant Definitions *****************************/
|
||||||
|
#define MPU_REGION_SIZE_MIN 0x20
|
||||||
|
/************************** Variable Definitions *****************************/
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
u64 size;
|
||||||
|
u32 encoding;
|
||||||
|
}region_size[] = {
|
||||||
|
{ 0x20, REGION_32B },
|
||||||
|
{ 0x40, REGION_64B },
|
||||||
|
{ 0x80, REGION_128B },
|
||||||
|
{ 0x100, REGION_256B },
|
||||||
|
{ 0x200, REGION_512B },
|
||||||
|
{ 0x400, REGION_1K },
|
||||||
|
{ 0x800, REGION_2K },
|
||||||
|
{ 0x1000, REGION_4K },
|
||||||
|
{ 0x2000, REGION_8K },
|
||||||
|
{ 0x4000, REGION_16K },
|
||||||
|
{ 0x8000, REGION_32K },
|
||||||
|
{ 0x10000, REGION_64K },
|
||||||
|
{ 0x20000, REGION_128K },
|
||||||
|
{ 0x40000, REGION_256K },
|
||||||
|
{ 0x80000, REGION_512K },
|
||||||
|
{ 0x100000, REGION_1M },
|
||||||
|
{ 0x200000, REGION_2M },
|
||||||
|
{ 0x400000, REGION_4M },
|
||||||
|
{ 0x800000, REGION_8M },
|
||||||
|
{ 0x1000000, REGION_16M },
|
||||||
|
{ 0x2000000, REGION_32M },
|
||||||
|
{ 0x4000000, REGION_64M },
|
||||||
|
{ 0x8000000, REGION_128M },
|
||||||
|
{ 0x10000000, REGION_256M },
|
||||||
|
{ 0x20000000, REGION_512M },
|
||||||
|
{ 0x40000000, REGION_1G },
|
||||||
|
{ 0x80000000, REGION_2G },
|
||||||
|
{ 0x100000000, REGION_4G },
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
XMpu_Config Mpu_Config __attribute__((section(".bootdata")));
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
#pragma default_function_attributes = @ ".bootdata"
|
||||||
|
XMpu_Config Mpu_Config;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************** Function Prototypes ******************************/
|
||||||
|
void Xil_InitializeExistingMPURegConfig(void);
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief This function sets the memory attributes for a section covering
|
||||||
|
* 1MB, of memory in the translation table.
|
||||||
|
*
|
||||||
|
* @param addr: 32-bit address for which memory attributes need to be set.
|
||||||
|
* @param attrib: Attribute for the given memory region.
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void Xil_SetTlbAttributes(INTPTR addr, u32 attrib)
|
||||||
|
{
|
||||||
|
INTPTR Localaddr = addr;
|
||||||
|
Localaddr &= (INTPTR)(~(0xFFFFFU));
|
||||||
|
/* Setting the MPU region with given attribute with 1MB size */
|
||||||
|
Xil_SetMPURegion(Localaddr, 0x100000, attrib);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Set the memory attributes for a section of memory in the
|
||||||
|
* translation table.
|
||||||
|
*
|
||||||
|
* @param addr: 32-bit address for which memory attributes need to be set..
|
||||||
|
* @param size: size is the size of the region.
|
||||||
|
* @param attrib: Attribute for the given memory region.
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib)
|
||||||
|
{
|
||||||
|
u32 Regionsize = 0;
|
||||||
|
INTPTR Localaddr = addr;
|
||||||
|
u32 NextAvailableMemRegion;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
NextAvailableMemRegion = Xil_GetNextMPURegion();
|
||||||
|
if (NextAvailableMemRegion == 0xFFU) {
|
||||||
|
xdbg_printf(DEBUG, "No regions available\r\n");
|
||||||
|
return XST_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Xil_DCacheFlush();
|
||||||
|
Xil_ICacheInvalidate();
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,NextAvailableMemRegion);
|
||||||
|
isb();
|
||||||
|
|
||||||
|
/* Lookup the size. */
|
||||||
|
for (i = 0; i < (sizeof (region_size) / sizeof (region_size[0])); i++) {
|
||||||
|
if (size <= region_size[i].size) {
|
||||||
|
Regionsize = region_size[i].encoding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Localaddr &= (INTPTR)(~(region_size[i].size - 1U));
|
||||||
|
|
||||||
|
Regionsize <<= 1;
|
||||||
|
Regionsize |= REGION_EN;
|
||||||
|
dsb();
|
||||||
|
mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr); /* Set base address of a region */
|
||||||
|
mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib); /* Set the control attribute */
|
||||||
|
mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize); /* set the region size and enable it*/
|
||||||
|
dsb();
|
||||||
|
isb();
|
||||||
|
Xil_UpdateMPUConfig(NextAvailableMemRegion, Localaddr, Regionsize, attrib);
|
||||||
|
return XST_SUCCESS;
|
||||||
|
}
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Enable MPU for Cortex R5 processor. This function invalidates I
|
||||||
|
* cache and flush the D Caches, and then enables the MPU.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void Xil_EnableMPU(void)
|
||||||
|
{
|
||||||
|
u32 CtrlReg, Reg;
|
||||||
|
s32 DCacheStatus=0, ICacheStatus=0;
|
||||||
|
/* enable caches only if they are disabled */
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
|
||||||
|
#endif
|
||||||
|
if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
|
||||||
|
DCacheStatus=1;
|
||||||
|
}
|
||||||
|
if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
|
||||||
|
ICacheStatus=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DCacheStatus != 0) {
|
||||||
|
Xil_DCacheDisable();
|
||||||
|
}
|
||||||
|
if(ICacheStatus != 0){
|
||||||
|
Xil_ICacheDisable();
|
||||||
|
}
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
Reg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,Reg);
|
||||||
|
#endif
|
||||||
|
Reg |= 0x00000001U;
|
||||||
|
dsb();
|
||||||
|
mtcp(XREG_CP15_SYS_CONTROL, Reg);
|
||||||
|
isb();
|
||||||
|
/* enable caches only if they are disabled in routine*/
|
||||||
|
if(DCacheStatus != 0) {
|
||||||
|
Xil_DCacheEnable();
|
||||||
|
}
|
||||||
|
if(ICacheStatus != 0) {
|
||||||
|
Xil_ICacheEnable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Disable MPU for Cortex R5 processors. This function invalidates I
|
||||||
|
* cache and flush the D Caches, and then disabes the MPU.
|
||||||
|
*
|
||||||
|
* @return None.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void Xil_DisableMPU(void)
|
||||||
|
{
|
||||||
|
u32 CtrlReg, Reg;
|
||||||
|
s32 DCacheStatus=0, ICacheStatus=0;
|
||||||
|
/* enable caches only if they are disabled */
|
||||||
|
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
|
||||||
|
#endif
|
||||||
|
if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
|
||||||
|
DCacheStatus=1;
|
||||||
|
}
|
||||||
|
if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
|
||||||
|
ICacheStatus=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DCacheStatus != 0) {
|
||||||
|
Xil_DCacheDisable();
|
||||||
|
}
|
||||||
|
if(ICacheStatus != 0){
|
||||||
|
Xil_ICacheDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0);
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
Reg = mfcp(XREG_CP15_SYS_CONTROL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_SYS_CONTROL,Reg);
|
||||||
|
#endif
|
||||||
|
Reg &= ~(0x00000001U);
|
||||||
|
dsb();
|
||||||
|
mtcp(XREG_CP15_SYS_CONTROL, Reg);
|
||||||
|
isb();
|
||||||
|
/* enable caches only if they are disabled in routine*/
|
||||||
|
if(DCacheStatus != 0) {
|
||||||
|
Xil_DCacheEnable();
|
||||||
|
}
|
||||||
|
if(ICacheStatus != 0) {
|
||||||
|
Xil_ICacheEnable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Update the MPU configuration for the requested region number in
|
||||||
|
* the global MPU configuration table.
|
||||||
|
*
|
||||||
|
* @param reg_num: The requested region number to be updated information for.
|
||||||
|
* @param address: 32 bit address for start of the region.
|
||||||
|
* @param size: Requested size of the region.
|
||||||
|
* @param attrib: Attribute for the corresponding region.
|
||||||
|
* @return XST_FAILURE: When the requested region number if 16 or more.
|
||||||
|
* XST_SUCCESS: When the MPU configuration table is updated.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib)
|
||||||
|
{
|
||||||
|
u32 ReturnVal = XST_SUCCESS;
|
||||||
|
u32 Tempsize = size;
|
||||||
|
u32 Index;
|
||||||
|
|
||||||
|
if (reg_num >= MAX_POSSIBLE_MPU_REGS) {
|
||||||
|
xdbg_printf(DEBUG, "Invalid region number\r\n");
|
||||||
|
ReturnVal = XST_FAILURE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size & REGION_EN) != 0) {
|
||||||
|
Mpu_Config[reg_num].RegionStatus = MPU_REG_ENABLED;
|
||||||
|
Mpu_Config[reg_num].BaseAddress = address;
|
||||||
|
Tempsize &= (~REGION_EN);
|
||||||
|
Tempsize >>= 1;
|
||||||
|
/* Lookup the size. */
|
||||||
|
for (Index = 0; Index <
|
||||||
|
(sizeof (region_size) / sizeof (region_size[0])); Index++) {
|
||||||
|
if (Tempsize <= region_size[Index].encoding) {
|
||||||
|
Mpu_Config[reg_num].Size = region_size[Index].size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mpu_Config[reg_num].Attribute = attrib;
|
||||||
|
} else {
|
||||||
|
Mpu_Config[reg_num].RegionStatus = 0U;
|
||||||
|
Mpu_Config[reg_num].BaseAddress = 0;
|
||||||
|
Mpu_Config[reg_num].Size = 0U;
|
||||||
|
Mpu_Config[reg_num].Attribute = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return ReturnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief The MPU configuration table is passed to the caller.
|
||||||
|
*
|
||||||
|
* @param mpuconfig: This is of type XMpu_Config which is an array of
|
||||||
|
* 16 entries of type structure representing the MPU config table
|
||||||
|
* @return none
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void Xil_GetMPUConfig (XMpu_Config mpuconfig) {
|
||||||
|
u32 Index = 0U;
|
||||||
|
|
||||||
|
while (Index < MAX_POSSIBLE_MPU_REGS) {
|
||||||
|
mpuconfig[Index].RegionStatus = Mpu_Config[Index].RegionStatus;
|
||||||
|
mpuconfig[Index].BaseAddress = Mpu_Config[Index].BaseAddress;
|
||||||
|
mpuconfig[Index].Attribute = Mpu_Config[Index].Attribute;
|
||||||
|
mpuconfig[Index].Size = Mpu_Config[Index].Size;
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Returns the total number of free MPU regions available.
|
||||||
|
*
|
||||||
|
* @return Number of free regions available to users
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u32 Xil_GetNumOfFreeRegions (void) {
|
||||||
|
u32 Index = 0U;
|
||||||
|
u32 NumofFreeRegs = 0U;
|
||||||
|
|
||||||
|
while (Index < MAX_POSSIBLE_MPU_REGS) {
|
||||||
|
if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) {
|
||||||
|
NumofFreeRegs++;
|
||||||
|
}
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
return NumofFreeRegs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Returns the total number of free MPU regions available in the form
|
||||||
|
* of a mask. A bit of 1 in the returned 16 bit value represents the
|
||||||
|
* corresponding region number to be available.
|
||||||
|
* For example, if this function returns 0xC0000, this would mean, the
|
||||||
|
* regions 14 and 15 are available to users.
|
||||||
|
*
|
||||||
|
* @return The free region mask as a 16 bit value
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u16 Xil_GetMPUFreeRegMask (void) {
|
||||||
|
u32 Index = 0U;
|
||||||
|
u16 FreeRegMask = 0U;
|
||||||
|
|
||||||
|
while (Index < MAX_POSSIBLE_MPU_REGS) {
|
||||||
|
if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) {
|
||||||
|
FreeRegMask |= ((u16)1U << Index);
|
||||||
|
}
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
return FreeRegMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Disables the corresponding region number as passed by the user.
|
||||||
|
*
|
||||||
|
* @param reg_num: The region number to be disabled
|
||||||
|
* @return XST_SUCCESS: If the region could be disabled successfully
|
||||||
|
* XST_FAILURE: If the requested region number is 16 or more.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u32 Xil_DisableMPURegionByRegNum (u32 reg_num) {
|
||||||
|
u32 Temp = 0U;
|
||||||
|
u32 ReturnVal = XST_FAILURE;
|
||||||
|
|
||||||
|
if (reg_num >= 16U) {
|
||||||
|
xdbg_printf(DEBUG, "Invalid region number\r\n");
|
||||||
|
goto exit1;
|
||||||
|
}
|
||||||
|
Xil_DCacheFlush();
|
||||||
|
Xil_ICacheInvalidate();
|
||||||
|
|
||||||
|
mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
Temp = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
|
||||||
|
#endif
|
||||||
|
Temp &= (~REGION_EN);
|
||||||
|
dsb();
|
||||||
|
mtcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
|
||||||
|
dsb();
|
||||||
|
isb();
|
||||||
|
Xil_UpdateMPUConfig(reg_num, 0, 0U, 0U);
|
||||||
|
ReturnVal = XST_SUCCESS;
|
||||||
|
|
||||||
|
exit1:
|
||||||
|
return ReturnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Enables the corresponding region number as passed by the user.
|
||||||
|
*
|
||||||
|
* @param reg_num: The region number to be enabled
|
||||||
|
* @param addr: 32 bit address for start of the region.
|
||||||
|
* @param size: Requested size of the region.
|
||||||
|
* @param attrib: Attribute for the corresponding region.
|
||||||
|
* @return XST_SUCCESS: If the region could be created successfully
|
||||||
|
* XST_FAILURE: If the requested region number is 16 or more.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib)
|
||||||
|
{
|
||||||
|
u32 ReturnVal = XST_SUCCESS;
|
||||||
|
INTPTR Localaddr = addr;
|
||||||
|
u32 Regionsize = 0;
|
||||||
|
u32 Index;
|
||||||
|
|
||||||
|
if (reg_num >= 16U) {
|
||||||
|
xdbg_printf(DEBUG, "Invalid region number\r\n");
|
||||||
|
ReturnVal = XST_FAILURE;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mpu_Config[reg_num].RegionStatus == MPU_REG_ENABLED) {
|
||||||
|
xdbg_printf(DEBUG, "Region already enabled\r\n");
|
||||||
|
ReturnVal = XST_FAILURE;
|
||||||
|
goto exit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Xil_DCacheFlush();
|
||||||
|
Xil_ICacheInvalidate();
|
||||||
|
mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
|
||||||
|
isb();
|
||||||
|
|
||||||
|
/* Lookup the size. */
|
||||||
|
for (Index = 0; Index <
|
||||||
|
(sizeof (region_size) / sizeof (region_size[0])); Index++) {
|
||||||
|
if (size <= region_size[Index].size) {
|
||||||
|
Regionsize = region_size[Index].encoding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Localaddr &= (INTPTR)(~(region_size[Index].size - 1U));
|
||||||
|
Regionsize <<= 1;
|
||||||
|
Regionsize |= REGION_EN;
|
||||||
|
dsb();
|
||||||
|
mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr);
|
||||||
|
mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib);
|
||||||
|
mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize);
|
||||||
|
dsb();
|
||||||
|
isb();
|
||||||
|
Xil_UpdateMPUConfig(reg_num, Localaddr, Regionsize, attrib);
|
||||||
|
exit2:
|
||||||
|
return ReturnVal;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Initializes the MPU configuration table that are setup in the
|
||||||
|
* R5 boot code in the Init_Mpu function called before C main.
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void Xil_InitializeExistingMPURegConfig(void)
|
||||||
|
{
|
||||||
|
u32 Index = 0U;
|
||||||
|
u32 Index1 = 0U;
|
||||||
|
u32 MPURegSize;
|
||||||
|
INTPTR MPURegBA;
|
||||||
|
u32 MPURegAttrib;
|
||||||
|
u32 Tempsize;
|
||||||
|
|
||||||
|
while (Index < MAX_POSSIBLE_MPU_REGS) {
|
||||||
|
mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,Index);
|
||||||
|
#if defined (__GNUC__)
|
||||||
|
MPURegSize = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
|
||||||
|
MPURegBA = mfcp(XREG_CP15_MPU_REG_BASEADDR);
|
||||||
|
MPURegAttrib = mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL);
|
||||||
|
#elif defined (__ICCARM__)
|
||||||
|
mfcp(XREG_CP15_MPU_REG_SIZE_EN,MPURegSize);
|
||||||
|
mfcp(XREG_CP15_MPU_REG_BASEADDR, MPURegBA);
|
||||||
|
mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL, MPURegAttrib);
|
||||||
|
#endif
|
||||||
|
if ((MPURegSize & REGION_EN) != 0) {
|
||||||
|
Mpu_Config[Index].RegionStatus = MPU_REG_ENABLED;
|
||||||
|
Mpu_Config[Index].BaseAddress = MPURegBA;
|
||||||
|
Mpu_Config[Index].Attribute = MPURegAttrib;
|
||||||
|
Tempsize = MPURegSize & (~REGION_EN);
|
||||||
|
Tempsize >>= 1;
|
||||||
|
for (Index1 = 0; Index1 <
|
||||||
|
(sizeof (region_size) / sizeof (region_size[0])); Index1++) {
|
||||||
|
if (Tempsize <= region_size[Index1].encoding) {
|
||||||
|
Mpu_Config[Index].Size = region_size[Index1].size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Returns the next available free MPU region
|
||||||
|
*
|
||||||
|
* @return The free MPU region available
|
||||||
|
*
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
u32 Xil_GetNextMPURegion(void)
|
||||||
|
{
|
||||||
|
u32 Index = 0U;
|
||||||
|
u32 NextAvailableReg = 0xFF;
|
||||||
|
while (Index < MAX_POSSIBLE_MPU_REGS) {
|
||||||
|
if (Mpu_Config[Index].RegionStatus != MPU_REG_ENABLED) {
|
||||||
|
NextAvailableReg = Index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
return NextAvailableReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define u32overflow(a, b) ({typeof(a) s; __builtin_uadd_overflow(a, b, &s); })
|
||||||
|
#else
|
||||||
|
#define u32overflow(a, b) ((a) > ((a) + (b)))
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Memory mapping for Cortex-R5F. If successful, the mapped
|
||||||
|
* region will include all of the memory requested, but may
|
||||||
|
* include more. Specifically, it will be a power of 2 in
|
||||||
|
* size, aligned on a boundary of that size.
|
||||||
|
*
|
||||||
|
* @param Physaddr is base physical address at which to start mapping.
|
||||||
|
* NULL in Physaddr masks possible mapping errors.
|
||||||
|
* @param size of region to be mapped.
|
||||||
|
* @param flags used to set translation table.
|
||||||
|
*
|
||||||
|
* @return Physaddr on success, NULL on error. Ambiguous if Physaddr==NULL
|
||||||
|
*
|
||||||
|
* @cond Xil_MemMap_internal
|
||||||
|
* @note: u32overflow() is defined for readability and (for __GNUC__) to
|
||||||
|
* - force the type of the check to be the same as the first argument
|
||||||
|
* - hide the otherwise unused third argument of the builtin
|
||||||
|
* - improve safety by choosing the explicit _uadd_ version.
|
||||||
|
* Consider __builtin_add_overflow_p() when available.
|
||||||
|
* Use an alternative (less optimal?) for compilers w/o the builtin.
|
||||||
|
* @endcond
|
||||||
|
******************************************************************************/
|
||||||
|
void *Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags)
|
||||||
|
{
|
||||||
|
size_t Regionsize = MPU_REGION_SIZE_MIN;
|
||||||
|
UINTPTR Basephysaddr = 0, end = Physaddr + size;
|
||||||
|
|
||||||
|
if (flags == 0U) {
|
||||||
|
return (void *)Physaddr;
|
||||||
|
}
|
||||||
|
if (u32overflow(Physaddr, size)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for ( ; Regionsize != 0U; Regionsize <<= 1) {
|
||||||
|
if (Regionsize >= size) {
|
||||||
|
Basephysaddr = Physaddr & ~(Regionsize - 1U);
|
||||||
|
if (u32overflow(Basephysaddr, Regionsize)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((Basephysaddr + Regionsize) >= end) {
|
||||||
|
return ((Xil_SetMPURegion(Basephysaddr,
|
||||||
|
Regionsize, flags) == XST_SUCCESS) ?
|
||||||
|
(void *)Physaddr : NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user