diff options
| author | Wang-Huachen <[email protected]> | 2021-05-13 16:33:40 +0800 |
|---|---|---|
| committer | Wang-Huachen <[email protected]> | 2021-05-13 16:33:40 +0800 |
| commit | d205721462ca448b8710098f83118620ef2399e9 (patch) | |
| tree | 4520de5c645e2db3859c5d630cf41a6328e5658c /libcpu | |
| parent | e58ea3ded4302bd2abad84a803f12f14e0990109 (diff) | |
add ethernet driver for zynqmp-r5-axu4ev
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/arm/zynqmp-r5/cache.c | 297 | ||||
| -rw-r--r-- | libcpu/arm/zynqmp-r5/start_gcc.S | 4 | ||||
| -rw-r--r-- | libcpu/arm/zynqmp-r5/xil_mmu.h | 54 | ||||
| -rw-r--r-- | libcpu/arm/zynqmp-r5/xil_mpu.c | 637 | ||||
| -rw-r--r-- | libcpu/arm/zynqmp-r5/xil_mpu.h | 129 |
5 files changed, 1094 insertions, 27 deletions
diff --git a/libcpu/arm/zynqmp-r5/cache.c b/libcpu/arm/zynqmp-r5/cache.c index d6e7cd2d6d..ed0efa4824 100644 --- a/libcpu/arm/zynqmp-r5/cache.c +++ b/libcpu/arm/zynqmp-r5/cache.c @@ -1,11 +1,13 @@ /* * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved. + * Copyright (c) 2021 WangHuachen. All rights reserved. + * SPDX-License-Identifier: MIT * * Change Logs: * Date Author Notes * 2020-03-19 WangHuachen first version + * 2021-05-10 WangHuachen add more functions */ #include <rthw.h> #include <rtdef.h> @@ -44,41 +46,85 @@ typedef rt_uint32_t u32; XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param)) #endif +void Xil_DCacheEnable(void); +void Xil_DCacheDisable(void); +void Xil_DCacheInvalidate(void); +void Xil_DCacheInvalidateRange(INTPTR adr, u32 len); +void Xil_DCacheFlush(void); +void Xil_DCacheFlushRange(INTPTR adr, u32 len); +void Xil_DCacheInvalidateLine(INTPTR adr); +void Xil_DCacheFlushLine(INTPTR adr); +void Xil_DCacheStoreLine(INTPTR adr); +void Xil_ICacheEnable(void); +void Xil_ICacheDisable(void); +void Xil_ICacheInvalidate(void); +void Xil_ICacheInvalidateRange(INTPTR adr, u32 len); +void Xil_ICacheInvalidateLine(INTPTR adr); -void Xil_ICacheInvalidateRange(INTPTR adr, u32 len) +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); + } +} + +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); +} + +void Xil_DCacheInvalidate(void) { - 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) { +#if 0 + stack_end = (u32 )&_stack_end; + stack_start = (u32 )&__undef_stack; + stack_size = stack_start-stack_end; - /* Invalidate L1 I-cache line */ - asm_inval_ic_line_mva_pou(LocalAddr); + /* Flush stack memory to save return address */ + Xil_DCacheFlushRange(stack_end, stack_size); +#endif + mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); - LocalAddr += cacheline; - } - } + /*invalidate all D cache*/ + mtcp(XREG_CP15_INVAL_DC_ALL, 0); - /* Wait for invalidate to complete */ - dsb(); mtcpsr(currmask); } -void Xil_DCacheFlushLine(INTPTR adr) +void Xil_DCacheInvalidateLine(INTPTR adr) { u32 currmask; @@ -86,11 +132,11 @@ void Xil_DCacheFlushLine(INTPTR adr) mtcpsr(currmask | IRQ_FIQ_MASK); mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); + mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); - mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); - - /* Wait for flush to complete */ + /* Wait for invalidate to complete */ dsb(); + mtcpsr(currmask); } @@ -135,6 +181,79 @@ void Xil_DCacheInvalidateRange(INTPTR adr, u32 len) mtcpsr(currmask); } +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 /= (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 += (0x00000001U << LineSize); + } + Set = 0U; + Way += 0x40000000U; + } + + /* Wait for flush to complete */ + dsb(); + mtcpsr(currmask); + + mtcpsr(currmask); +} + +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); +} + void Xil_DCacheFlushRange(INTPTR adr, u32 len) { u32 LocalAddr = adr; @@ -163,6 +282,130 @@ void Xil_DCacheFlushRange(INTPTR adr, u32 len) mtcpsr(currmask); } +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); +} + +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); + } +} + +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); +} + +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); +} + +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); +} + +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); +} + void rt_hw_cpu_icache_ops(int ops, void *addr, int size) { if (ops == RT_HW_CACHE_INVALIDATE) diff --git a/libcpu/arm/zynqmp-r5/start_gcc.S b/libcpu/arm/zynqmp-r5/start_gcc.S index faea0022be..7e99c9e82b 100644 --- a/libcpu/arm/zynqmp-r5/start_gcc.S +++ b/libcpu/arm/zynqmp-r5/start_gcc.S @@ -6,6 +6,9 @@ * Change Logs: * Date Author Notes * 2020-03-19 WangHuachen first version + * 2021-05-11 WangHuachen Added call to Xil_InitializeExistingMPURegConfig to + * initialize the MPU configuration table with the MPU + * configurations already set in Init_Mpu function. */ .equ Mode_USR, 0x10 @@ -234,6 +237,7 @@ ctor_loop: b ctor_loop ctor_end: + bl Xil_InitializeExistingMPURegConfig /* Initialize MPU config */ /* start RT-Thread Kernel */ ldr pc, _entry diff --git a/libcpu/arm/zynqmp-r5/xil_mmu.h b/libcpu/arm/zynqmp-r5/xil_mmu.h new file mode 100644 index 0000000000..99e019c6f5 --- /dev/null +++ b/libcpu/arm/zynqmp-r5/xil_mmu.h @@ -0,0 +1,54 @@ +/****************************************************************************** +* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved. +* SPDX-License-Identifier: MIT +******************************************************************************/ + +/*****************************************************************************/ +/** +* @file xil_mmu.h +* This file only includes xil_mpu.h which contains Xil_SetTlbAttributes API +* defined for MPU in R5. R5 does not have mmu and for usage of similar API +* the file has been created. +* +* +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- --------------------------------------------------- +* 5.0 pkp 2/12/15 Initial version +* </pre> +* +* @note +* +* None. +* +******************************************************************************/ + +#ifndef XIL_MMU_H +#define XIL_MMU_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/***************************** Include Files *********************************/ + +#include "xil_mpu.h" + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* XIL_MMU_H */ diff --git a/libcpu/arm/zynqmp-r5/xil_mpu.c b/libcpu/arm/zynqmp-r5/xil_mpu.c new file mode 100644 index 0000000000..7115bbb0a6 --- /dev/null +++ b/libcpu/arm/zynqmp-r5/xil_mpu.c @@ -0,0 +1,637 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved. +* Copyright (C) 2021 WangHuachen. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @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(). +* </pre> +* +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xil_cache.h" +#include "xpseudo_asm_gcc.h" +#include "xil_types.h" +#include "xil_mpu.h" +// #include "xdebug.h" +#include "xreg_cortexr5.h" +#include "xstatus.h" + +#include <rtthread.h> +#define DBG_TAG "xil_mpu" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +extern void Xil_DCacheFlush(void); +extern void Xil_ICacheInvalidate(void); +extern void Xil_DCacheDisable(void); +extern void Xil_ICacheDisable(void); +extern void Xil_DCacheEnable(void); +extern void Xil_ICacheEnable(void); + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Constant Definitions *****************************/ +#define MPU_REGION_SIZE_MIN 0x20 +/************************** Variable Definitions *****************************/ + +static const struct { + u64 size; + unsigned int 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 }, +}; + +XMpu_Config Mpu_Config; + +/************************** 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 &= (~(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; + unsigned int i; + + NextAvailableMemRegion = Xil_GetNextMPURegion(); + if (NextAvailableMemRegion == 0xFF) { + LOG_E("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 &= ~(region_size[i].size - 1); + + 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. +* +* +* @param None. +* @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. +* +* @param None. +* +* @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) { + LOG_E("Invalid region number\r\n"); + ReturnVal = XST_FAILURE; + goto exit; + } + + if (size & REGION_EN) { + 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 = 0U; + 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. +* +* @param none +* @return Number of free regions available to users +* +* +******************************************************************************/ +u32 Xil_GetNumOfFreeRegions (void) { + u32 Index = 0U; + int 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. +* +* @param none +* @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 |= (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) { + LOG_E("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, 0U, 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 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_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) { + LOG_E("Invalid region number\r\n"); + ReturnVal = XST_FAILURE; + goto exit2; + } + + if (Mpu_Config[reg_num].RegionStatus == MPU_REG_ENABLED) { + LOG_E("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 &= ~(region_size[Index].size - 1); + 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. +* +* @param none +* @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) { + 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 +* +* @param none +* @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; +} + +/*****************************************************************************/ +/** +* @brief Memory mapping for Cortex r5. +* +* @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 +* +* @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. +* +******************************************************************************/ +#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__ */ +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) + return (void *)Physaddr; + if (u32overflow(Physaddr, size)) + return NULL; + for ( ; Regionsize != 0; Regionsize <<= 1) { + if (Regionsize >= size) { + Basephysaddr = Physaddr & ~(Regionsize - 1); + if (u32overflow(Basephysaddr, Regionsize)) + break; + if ((Basephysaddr + Regionsize) >= end) + return Xil_SetMPURegion(Basephysaddr, + Regionsize, flags) == XST_SUCCESS ? + (void *)Physaddr : NULL; + } + } + return NULL; +} diff --git a/libcpu/arm/zynqmp-r5/xil_mpu.h b/libcpu/arm/zynqmp-r5/xil_mpu.h new file mode 100644 index 0000000000..1afa6f76f7 --- /dev/null +++ b/libcpu/arm/zynqmp-r5/xil_mpu.h @@ -0,0 +1,129 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @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. +* </pre> +* + +* +* +******************************************************************************/ + +#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 ******************************/ + +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". +*/ |
