1 /******************************************************************************
2 *
3 * Copyright (C) 2014 Xilinx, Inc. All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 * @file xil_mpu.c
35 *
36 * This file provides APIs for enabling/disabling MPU and setting the memory
37 * attributes for sections, in the MPU translation table.
38 *
39 * <pre>
40 * MODIFICATION HISTORY:
41 *
42 * Ver Who Date Changes
43 * ----- ---- -------- ---------------------------------------------------
44 * 5.00 pkp 02/10/14 Initial version
45 * </pre>
46 *
47 * @note
48 *
49 * None.
50 *
51 ******************************************************************************/
53 /***************************** Include Files *********************************/
55 #include "xil_cache.h"
56 #include "xpseudo_asm.h"
57 #include "xil_types.h"
58 #include "xil_mpu.h"
59 #include "xdebug.h"
61 /***************** Macros (Inline Functions) Definitions *********************/
63 /**************************** Type Definitions *******************************/
65 /************************** Constant Definitions *****************************/
67 /************************** Variable Definitions *****************************/
69 static const struct {
70 u64 size;
71 unsigned int encoding;
72 }region_size[] = {
73 { 0x20, REGION_32B },
74 { 0x40, REGION_64B },
75 { 0x80, REGION_128B },
76 { 0x100, REGION_256B },
77 { 0x200, REGION_512B },
78 { 0x400, REGION_1K },
79 { 0x800, REGION_2K },
80 { 0x1000, REGION_4K },
81 { 0x2000, REGION_8K },
82 { 0x4000, REGION_16K },
83 { 0x8000, REGION_32K },
84 { 0x10000, REGION_64K },
85 { 0x20000, REGION_128K },
86 { 0x40000, REGION_256K },
87 { 0x80000, REGION_512K },
88 { 0x100000, REGION_1M },
89 { 0x200000, REGION_2M },
90 { 0x400000, REGION_4M },
91 { 0x800000, REGION_8M },
92 { 0x1000000, REGION_16M },
93 { 0x2000000, REGION_32M },
94 { 0x4000000, REGION_64M },
95 { 0x8000000, REGION_128M },
96 { 0x10000000, REGION_256M },
97 { 0x20000000, REGION_512M },
98 { 0x40000000, REGION_1G },
99 { 0x80000000, REGION_2G },
100 { 0x100000000, REGION_4G },
101 };
103 /************************** Function Prototypes ******************************/
105 /*****************************************************************************
106 *
107 * Set the memory attributes for a section of memory with starting address addr
108 * of the region size 1MB having attributes attrib
109 *
110 * @param addr is the address for which attributes are to be set.
111 * @param attrib specifies the attributes for that memory region.
112 * @return None.
113 *
114 *
115 ******************************************************************************/
116 void Xil_SetTlbAttributes(INTPTR addr, u32 attrib)
117 {
118 INTPTR Localaddr = addr;
119 Localaddr &= (~(0xFFFFFU));
120 /* Setting the MPU region with given attribute with 1MB size */
121 Xil_SetMPURegion(Localaddr, 0x100000, attrib);
122 }
124 /*****************************************************************************
125 *
126 * Set the memory attributes for a section of memory with starting address addr
127 * of the region size size and having attributes attrib
128 *
129 * @param addr is the address for which attributes are to be set.
130 * @param size is the size of the region.
131 * @param attrib specifies the attributes for that memory region.
132 * @return None.
133 *
134 *
135 ******************************************************************************/
136 void Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib)
137 {
138 u32 Regionsize = 0;
139 INTPTR Localaddr = addr;
140 u32 NextAvailableMemRegion;
141 unsigned int i;
143 Xil_DCacheFlush();
144 Xil_ICacheInvalidate();
145 NextAvailableMemRegion = mfcp(XREG_CP15_MPU_MEMORY_REG_NUMBER);
146 NextAvailableMemRegion++;
147 if (NextAvailableMemRegion > 16) {
148 xdbg_printf(DEBUG, "No regions available\r\n");
149 return;
150 }
151 mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,NextAvailableMemRegion);
152 isb();
154 /* Lookup the size. */
155 for (i = 0; i < sizeof region_size / sizeof region_size[0]; i++) {
156 if (size <= region_size[i].size) {
157 Regionsize = region_size[i].encoding;
158 break;
159 }
160 }
162 Localaddr &= ~(region_size[i].size - 1);
164 Regionsize <<= 1;
165 Regionsize |= REGION_EN;
166 dsb();
167 mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr); /* Set base address of a region */
168 mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib); /* Set the control attribute */
169 mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize); /* set the region size and enable it*/
170 dsb();
171 isb();
172 }
174 /*****************************************************************************
175 *
176 * Enable MPU for Cortex R5 processor. This function invalidates I cache and
177 * flush the D Caches before enabling the MPU.
178 *
179 *
180 * @param None.
181 * @return None.
182 *
183 ******************************************************************************/
184 void Xil_EnableMPU(void)
185 {
186 u32 CtrlReg, Reg;
187 s32 DCacheStatus=0, ICacheStatus=0;
188 /* enable caches only if they are disabled */
189 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
190 if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
191 DCacheStatus=1;
192 }
193 if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
194 ICacheStatus=1;
195 }
197 if(DCacheStatus != 0) {
198 Xil_DCacheDisable();
199 }
200 if(ICacheStatus != 0){
201 Xil_ICacheDisable();
202 }
203 Reg = mfcp(XREG_CP15_SYS_CONTROL);
204 Reg |= 0x00000001U;
205 dsb();
206 mtcp(XREG_CP15_SYS_CONTROL, Reg);
207 isb();
208 /* enable caches only if they are disabled in routine*/
209 if(DCacheStatus != 0) {
210 Xil_DCacheEnable();
211 }
212 if(ICacheStatus != 0) {
213 Xil_ICacheEnable();
214 }
215 }
217 /*****************************************************************************
218 *
219 * Disable MPU for Cortex R5 processors. This function invalidates I cache and
220 * flush the D Caches before disabling the MPU.
221 *
222 * @param None.
223 *
224 * @return None.
225 *
226 ******************************************************************************/
227 void Xil_DisableMPU(void)
228 {
229 u32 CtrlReg, Reg;
230 s32 DCacheStatus=0, ICacheStatus=0;
231 /* enable caches only if they are disabled */
232 CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
233 if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
234 DCacheStatus=1;
235 }
236 if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
237 ICacheStatus=1;
238 }
240 if(DCacheStatus != 0) {
241 Xil_DCacheDisable();
242 }
243 if(ICacheStatus != 0){
244 Xil_ICacheDisable();
245 }
247 mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0);
248 Reg = mfcp(XREG_CP15_SYS_CONTROL);
249 Reg &= ~(0x00000001U);
250 dsb();
251 mtcp(XREG_CP15_SYS_CONTROL, Reg);
252 isb();
253 /* enable caches only if they are disabled in routine*/
254 if(DCacheStatus != 0) {
255 Xil_DCacheEnable();
256 }
257 if(ICacheStatus != 0) {
258 Xil_ICacheEnable();
259 }
260 }