xil_mpu.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved.
  4. * Copyright (C) 2021 WangHuachen. All rights reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. *
  24. *
  25. *
  26. ******************************************************************************/
  27. /*****************************************************************************/
  28. /**
  29. * @file xil_mpu.c
  30. *
  31. * This file provides APIs for enabling/disabling MPU and setting the memory
  32. * attributes for sections, in the MPU translation table.
  33. *
  34. * <pre>
  35. * MODIFICATION HISTORY:
  36. *
  37. * Ver Who Date Changes
  38. * ----- ---- -------- ---------------------------------------------------
  39. * 5.00 pkp 02/10/14 Initial version
  40. * 6.2 mus 01/27/17 Updated to support IAR compiler
  41. * 6.4 asa 08/16/17 Added many APIs for MPU access to make MPU usage
  42. * user-friendly. The APIs added are: Xil_UpdateMPUConfig,
  43. * Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
  44. * Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
  45. * Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
  46. * Xil_InitializeExistingMPURegConfig.
  47. * Added a new array of structure of type XMpuConfig to
  48. * represent the MPU configuration table.
  49. * 6.8 aru 07/02/18 Returned the pointer instead of address
  50. * of that pointer in Xil_MemMap().
  51. * </pre>
  52. *
  53. *
  54. ******************************************************************************/
  55. /***************************** Include Files *********************************/
  56. #include "xil_cache.h"
  57. #include "xpseudo_asm_gcc.h"
  58. #include "xil_types.h"
  59. #include "xil_mpu.h"
  60. // #include "xdebug.h"
  61. #include "xreg_cortexr5.h"
  62. #include "xstatus.h"
  63. #include <rtthread.h>
  64. #define DBG_TAG "xil_mpu"
  65. #define DBG_LVL DBG_INFO
  66. #include <rtdbg.h>
  67. extern void Xil_DCacheFlush(void);
  68. extern void Xil_ICacheInvalidate(void);
  69. extern void Xil_DCacheDisable(void);
  70. extern void Xil_ICacheDisable(void);
  71. extern void Xil_DCacheEnable(void);
  72. extern void Xil_ICacheEnable(void);
  73. /***************** Macros (Inline Functions) Definitions *********************/
  74. /**************************** Type Definitions *******************************/
  75. /************************** Constant Definitions *****************************/
  76. #define MPU_REGION_SIZE_MIN 0x20
  77. /************************** Variable Definitions *****************************/
  78. static const struct {
  79. u64 size;
  80. unsigned int encoding;
  81. }region_size[] = {
  82. { 0x20, REGION_32B },
  83. { 0x40, REGION_64B },
  84. { 0x80, REGION_128B },
  85. { 0x100, REGION_256B },
  86. { 0x200, REGION_512B },
  87. { 0x400, REGION_1K },
  88. { 0x800, REGION_2K },
  89. { 0x1000, REGION_4K },
  90. { 0x2000, REGION_8K },
  91. { 0x4000, REGION_16K },
  92. { 0x8000, REGION_32K },
  93. { 0x10000, REGION_64K },
  94. { 0x20000, REGION_128K },
  95. { 0x40000, REGION_256K },
  96. { 0x80000, REGION_512K },
  97. { 0x100000, REGION_1M },
  98. { 0x200000, REGION_2M },
  99. { 0x400000, REGION_4M },
  100. { 0x800000, REGION_8M },
  101. { 0x1000000, REGION_16M },
  102. { 0x2000000, REGION_32M },
  103. { 0x4000000, REGION_64M },
  104. { 0x8000000, REGION_128M },
  105. { 0x10000000, REGION_256M },
  106. { 0x20000000, REGION_512M },
  107. { 0x40000000, REGION_1G },
  108. { 0x80000000, REGION_2G },
  109. { 0x100000000, REGION_4G },
  110. };
  111. XMpu_Config Mpu_Config;
  112. /************************** Function Prototypes ******************************/
  113. void Xil_InitializeExistingMPURegConfig(void);
  114. /*****************************************************************************/
  115. /**
  116. * @brief This function sets the memory attributes for a section covering
  117. * 1MB, of memory in the translation table.
  118. *
  119. * @param Addr: 32-bit address for which memory attributes need to be set.
  120. * @param attrib: Attribute for the given memory region.
  121. * @return None.
  122. *
  123. *
  124. ******************************************************************************/
  125. void Xil_SetTlbAttributes(INTPTR addr, u32 attrib)
  126. {
  127. INTPTR Localaddr = addr;
  128. Localaddr &= (~(0xFFFFFU));
  129. /* Setting the MPU region with given attribute with 1MB size */
  130. Xil_SetMPURegion(Localaddr, 0x100000, attrib);
  131. }
  132. /*****************************************************************************/
  133. /**
  134. * @brief Set the memory attributes for a section of memory in the
  135. * translation table.
  136. *
  137. * @param Addr: 32-bit address for which memory attributes need to be set..
  138. * @param size: size is the size of the region.
  139. * @param attrib: Attribute for the given memory region.
  140. * @return None.
  141. *
  142. *
  143. ******************************************************************************/
  144. u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib)
  145. {
  146. u32 Regionsize = 0;
  147. INTPTR Localaddr = addr;
  148. u32 NextAvailableMemRegion;
  149. unsigned int i;
  150. NextAvailableMemRegion = Xil_GetNextMPURegion();
  151. if (NextAvailableMemRegion == 0xFF) {
  152. LOG_E("No regions available\r\n");
  153. return XST_FAILURE;
  154. }
  155. Xil_DCacheFlush();
  156. Xil_ICacheInvalidate();
  157. mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,NextAvailableMemRegion);
  158. isb();
  159. /* Lookup the size. */
  160. for (i = 0; i < sizeof region_size / sizeof region_size[0]; i++) {
  161. if (size <= region_size[i].size) {
  162. Regionsize = region_size[i].encoding;
  163. break;
  164. }
  165. }
  166. Localaddr &= ~(region_size[i].size - 1);
  167. Regionsize <<= 1;
  168. Regionsize |= REGION_EN;
  169. dsb();
  170. mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr); /* Set base address of a region */
  171. mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib); /* Set the control attribute */
  172. mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize); /* set the region size and enable it*/
  173. dsb();
  174. isb();
  175. Xil_UpdateMPUConfig(NextAvailableMemRegion, Localaddr, Regionsize, attrib);
  176. return XST_SUCCESS;
  177. }
  178. /*****************************************************************************/
  179. /**
  180. * @brief Enable MPU for Cortex R5 processor. This function invalidates I
  181. * cache and flush the D Caches, and then enables the MPU.
  182. *
  183. *
  184. * @param None.
  185. * @return None.
  186. *
  187. ******************************************************************************/
  188. void Xil_EnableMPU(void)
  189. {
  190. u32 CtrlReg, Reg;
  191. s32 DCacheStatus=0, ICacheStatus=0;
  192. /* enable caches only if they are disabled */
  193. #if defined (__GNUC__)
  194. CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
  195. #elif defined (__ICCARM__)
  196. mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
  197. #endif
  198. if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
  199. DCacheStatus=1;
  200. }
  201. if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
  202. ICacheStatus=1;
  203. }
  204. if(DCacheStatus != 0) {
  205. Xil_DCacheDisable();
  206. }
  207. if(ICacheStatus != 0){
  208. Xil_ICacheDisable();
  209. }
  210. #if defined (__GNUC__)
  211. Reg = mfcp(XREG_CP15_SYS_CONTROL);
  212. #elif defined (__ICCARM__)
  213. mfcp(XREG_CP15_SYS_CONTROL,Reg);
  214. #endif
  215. Reg |= 0x00000001U;
  216. dsb();
  217. mtcp(XREG_CP15_SYS_CONTROL, Reg);
  218. isb();
  219. /* enable caches only if they are disabled in routine*/
  220. if(DCacheStatus != 0) {
  221. Xil_DCacheEnable();
  222. }
  223. if(ICacheStatus != 0) {
  224. Xil_ICacheEnable();
  225. }
  226. }
  227. /*****************************************************************************/
  228. /**
  229. * @brief Disable MPU for Cortex R5 processors. This function invalidates I
  230. * cache and flush the D Caches, and then disabes the MPU.
  231. *
  232. * @param None.
  233. *
  234. * @return None.
  235. *
  236. ******************************************************************************/
  237. void Xil_DisableMPU(void)
  238. {
  239. u32 CtrlReg, Reg;
  240. s32 DCacheStatus=0, ICacheStatus=0;
  241. /* enable caches only if they are disabled */
  242. #if defined (__GNUC__)
  243. CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
  244. #elif defined (__ICCARM__)
  245. mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
  246. #endif
  247. if ((CtrlReg & XREG_CP15_CONTROL_C_BIT) != 0x00000000U) {
  248. DCacheStatus=1;
  249. }
  250. if ((CtrlReg & XREG_CP15_CONTROL_I_BIT) != 0x00000000U) {
  251. ICacheStatus=1;
  252. }
  253. if(DCacheStatus != 0) {
  254. Xil_DCacheDisable();
  255. }
  256. if(ICacheStatus != 0){
  257. Xil_ICacheDisable();
  258. }
  259. mtcp(XREG_CP15_INVAL_BRANCH_ARRAY, 0);
  260. #if defined (__GNUC__)
  261. Reg = mfcp(XREG_CP15_SYS_CONTROL);
  262. #elif defined (__ICCARM__)
  263. mfcp(XREG_CP15_SYS_CONTROL,Reg);
  264. #endif
  265. Reg &= ~(0x00000001U);
  266. dsb();
  267. mtcp(XREG_CP15_SYS_CONTROL, Reg);
  268. isb();
  269. /* enable caches only if they are disabled in routine*/
  270. if(DCacheStatus != 0) {
  271. Xil_DCacheEnable();
  272. }
  273. if(ICacheStatus != 0) {
  274. Xil_ICacheEnable();
  275. }
  276. }
  277. /*****************************************************************************/
  278. /**
  279. * @brief Update the MPU configuration for the requested region number in
  280. * the global MPU configuration table.
  281. *
  282. * @param reg_num: The requested region number to be updated information for.
  283. * @param address: 32 bit address for start of the region.
  284. * @param size: Requested size of the region.
  285. * @param attrib: Attribute for the corresponding region.
  286. * @return XST_FAILURE: When the requested region number if 16 or more.
  287. * XST_SUCCESS: When the MPU configuration table is updated.
  288. *
  289. *
  290. ******************************************************************************/
  291. u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib)
  292. {
  293. u32 ReturnVal = XST_SUCCESS;
  294. u32 Tempsize = size;
  295. u32 Index;
  296. if (reg_num >= MAX_POSSIBLE_MPU_REGS) {
  297. LOG_E("Invalid region number\r\n");
  298. ReturnVal = XST_FAILURE;
  299. goto exit;
  300. }
  301. if (size & REGION_EN) {
  302. Mpu_Config[reg_num].RegionStatus = MPU_REG_ENABLED;
  303. Mpu_Config[reg_num].BaseAddress = address;
  304. Tempsize &= (~REGION_EN);
  305. Tempsize >>= 1;
  306. /* Lookup the size. */
  307. for (Index = 0; Index <
  308. sizeof region_size / sizeof region_size[0]; Index++) {
  309. if (Tempsize <= region_size[Index].encoding) {
  310. Mpu_Config[reg_num].Size = region_size[Index].size;
  311. break;
  312. }
  313. }
  314. Mpu_Config[reg_num].Attribute = attrib;
  315. } else {
  316. Mpu_Config[reg_num].RegionStatus = 0U;
  317. Mpu_Config[reg_num].BaseAddress = 0U;
  318. Mpu_Config[reg_num].Size = 0U;
  319. Mpu_Config[reg_num].Attribute = 0U;
  320. }
  321. exit:
  322. return ReturnVal;
  323. }
  324. /*****************************************************************************/
  325. /**
  326. * @brief The MPU configuration table is passed to the caller.
  327. *
  328. * @param mpuconfig: This is of type XMpu_Config which is an array of
  329. * 16 entries of type structure representing the MPU config table
  330. * @return none
  331. *
  332. *
  333. ******************************************************************************/
  334. void Xil_GetMPUConfig (XMpu_Config mpuconfig) {
  335. u32 Index = 0U;
  336. while (Index < MAX_POSSIBLE_MPU_REGS) {
  337. mpuconfig[Index].RegionStatus = Mpu_Config[Index].RegionStatus;
  338. mpuconfig[Index].BaseAddress = Mpu_Config[Index].BaseAddress;
  339. mpuconfig[Index].Attribute = Mpu_Config[Index].Attribute;
  340. mpuconfig[Index].Size = Mpu_Config[Index].Size;
  341. Index++;
  342. }
  343. }
  344. /*****************************************************************************/
  345. /**
  346. * @brief Returns the total number of free MPU regions available.
  347. *
  348. * @param none
  349. * @return Number of free regions available to users
  350. *
  351. *
  352. ******************************************************************************/
  353. u32 Xil_GetNumOfFreeRegions (void) {
  354. u32 Index = 0U;
  355. int NumofFreeRegs = 0U;
  356. while (Index < MAX_POSSIBLE_MPU_REGS) {
  357. if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) {
  358. NumofFreeRegs++;
  359. }
  360. Index++;
  361. }
  362. return NumofFreeRegs;
  363. }
  364. /*****************************************************************************/
  365. /**
  366. * @brief Returns the total number of free MPU regions available in the form
  367. * of a mask. A bit of 1 in the returned 16 bit value represents the
  368. * corresponding region number to be available.
  369. * For example, if this function returns 0xC0000, this would mean, the
  370. * regions 14 and 15 are available to users.
  371. *
  372. * @param none
  373. * @return The free region mask as a 16 bit value
  374. *
  375. *
  376. ******************************************************************************/
  377. u16 Xil_GetMPUFreeRegMask (void) {
  378. u32 Index = 0U;
  379. u16 FreeRegMask = 0U;
  380. while (Index < MAX_POSSIBLE_MPU_REGS) {
  381. if (MPU_REG_DISABLED == Mpu_Config[Index].RegionStatus) {
  382. FreeRegMask |= (1U << Index);
  383. }
  384. Index++;
  385. }
  386. return FreeRegMask;
  387. }
  388. /*****************************************************************************/
  389. /**
  390. * @brief Disables the corresponding region number as passed by the user.
  391. *
  392. * @param reg_num: The region number to be disabled
  393. * @return XST_SUCCESS: If the region could be disabled successfully
  394. * XST_FAILURE: If the requested region number is 16 or more.
  395. *
  396. *
  397. ******************************************************************************/
  398. u32 Xil_DisableMPURegionByRegNum (u32 reg_num) {
  399. u32 Temp = 0U;
  400. u32 ReturnVal = XST_FAILURE;
  401. if (reg_num >= 16U) {
  402. LOG_E("Invalid region number\r\n");
  403. goto exit1;
  404. }
  405. Xil_DCacheFlush();
  406. Xil_ICacheInvalidate();
  407. mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
  408. #if defined (__GNUC__)
  409. Temp = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
  410. #elif defined (__ICCARM__)
  411. mfcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
  412. #endif
  413. Temp &= (~REGION_EN);
  414. dsb();
  415. mtcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
  416. dsb();
  417. isb();
  418. Xil_UpdateMPUConfig(reg_num, 0U, 0U, 0U);
  419. ReturnVal = XST_SUCCESS;
  420. exit1:
  421. return ReturnVal;
  422. }
  423. /*****************************************************************************/
  424. /**
  425. * @brief Enables the corresponding region number as passed by the user.
  426. *
  427. * @param reg_num: The region number to be enabled
  428. * @param address: 32 bit address for start of the region.
  429. * @param size: Requested size of the region.
  430. * @param attrib: Attribute for the corresponding region.
  431. * @return XST_SUCCESS: If the region could be created successfully
  432. * XST_FAILURE: If the requested region number is 16 or more.
  433. *
  434. *
  435. ******************************************************************************/
  436. u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib)
  437. {
  438. u32 ReturnVal = XST_SUCCESS;
  439. INTPTR Localaddr = addr;
  440. u32 Regionsize = 0;
  441. u32 Index;
  442. if (reg_num >= 16U) {
  443. LOG_E("Invalid region number\r\n");
  444. ReturnVal = XST_FAILURE;
  445. goto exit2;
  446. }
  447. if (Mpu_Config[reg_num].RegionStatus == MPU_REG_ENABLED) {
  448. LOG_E("Region already enabled\r\n");
  449. ReturnVal = XST_FAILURE;
  450. goto exit2;
  451. }
  452. Xil_DCacheFlush();
  453. Xil_ICacheInvalidate();
  454. mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
  455. isb();
  456. /* Lookup the size. */
  457. for (Index = 0; Index <
  458. sizeof region_size / sizeof region_size[0]; Index++) {
  459. if (size <= region_size[Index].size) {
  460. Regionsize = region_size[Index].encoding;
  461. break;
  462. }
  463. }
  464. Localaddr &= ~(region_size[Index].size - 1);
  465. Regionsize <<= 1;
  466. Regionsize |= REGION_EN;
  467. dsb();
  468. mtcp(XREG_CP15_MPU_REG_BASEADDR, Localaddr);
  469. mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL, attrib);
  470. mtcp(XREG_CP15_MPU_REG_SIZE_EN, Regionsize);
  471. dsb();
  472. isb();
  473. Xil_UpdateMPUConfig(reg_num, Localaddr, Regionsize, attrib);
  474. exit2:
  475. return ReturnVal;
  476. }
  477. /*****************************************************************************/
  478. /**
  479. * @brief Initializes the MPU configuration table that are setup in the
  480. * R5 boot code in the Init_Mpu function called before C main.
  481. *
  482. * @param none
  483. * @return none
  484. *
  485. *
  486. ******************************************************************************/
  487. void Xil_InitializeExistingMPURegConfig(void)
  488. {
  489. u32 Index = 0U;
  490. u32 Index1 = 0U;
  491. u32 MPURegSize;
  492. INTPTR MPURegBA;
  493. u32 MPURegAttrib;
  494. u32 Tempsize;
  495. while (Index < MAX_POSSIBLE_MPU_REGS) {
  496. mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,Index);
  497. #if defined (__GNUC__)
  498. MPURegSize = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
  499. MPURegBA = mfcp(XREG_CP15_MPU_REG_BASEADDR);
  500. MPURegAttrib = mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL);
  501. #elif defined (__ICCARM__)
  502. mfcp(XREG_CP15_MPU_REG_SIZE_EN,MPURegSize);
  503. mfcp(XREG_CP15_MPU_REG_BASEADDR, MPURegBA);
  504. mfcp(XREG_CP15_MPU_REG_ACCESS_CTRL, MPURegAttrib);
  505. #endif
  506. if (MPURegSize & REGION_EN) {
  507. Mpu_Config[Index].RegionStatus = MPU_REG_ENABLED;
  508. Mpu_Config[Index].BaseAddress = MPURegBA;
  509. Mpu_Config[Index].Attribute = MPURegAttrib;
  510. Tempsize = MPURegSize & (~REGION_EN);
  511. Tempsize >>= 1;
  512. for (Index1 = 0; Index1 <
  513. (sizeof (region_size) / sizeof (region_size[0])); Index1++) {
  514. if (Tempsize <= region_size[Index1].encoding) {
  515. Mpu_Config[Index].Size = region_size[Index1].size;
  516. break;
  517. }
  518. }
  519. }
  520. Index++;
  521. }
  522. }
  523. /*****************************************************************************/
  524. /**
  525. * @brief Returns the next available free MPU region
  526. *
  527. * @param none
  528. * @return The free MPU region available
  529. *
  530. *
  531. ******************************************************************************/
  532. u32 Xil_GetNextMPURegion(void)
  533. {
  534. u32 Index = 0U;
  535. u32 NextAvailableReg = 0xFF;
  536. while (Index < MAX_POSSIBLE_MPU_REGS) {
  537. if (Mpu_Config[Index].RegionStatus != MPU_REG_ENABLED) {
  538. NextAvailableReg = Index;
  539. break;
  540. }
  541. Index++;
  542. }
  543. return NextAvailableReg;
  544. }
  545. /*****************************************************************************/
  546. /**
  547. * @brief Memory mapping for Cortex r5.
  548. *
  549. * @param Physaddr is base physical address at which to start mapping.
  550. * NULL in Physaddr masks possible mapping errors.
  551. * @param size of region to be mapped.
  552. * @param flags used to set translation table.
  553. *
  554. * @return Physaddr on success, NULL on error. Ambiguous if Physaddr==NULL
  555. *
  556. * @note: u32overflow() is defined for readability and (for __GNUC__) to
  557. * - force the type of the check to be the same as the first argument
  558. * - hide the otherwise unused third argument of the builtin
  559. * - improve safety by choosing the explicit _uadd_ version.
  560. * Consider __builtin_add_overflow_p() when available.
  561. * Use an alternative (less optimal?) for compilers w/o the builtin.
  562. *
  563. ******************************************************************************/
  564. #ifdef __GNUC__
  565. #define u32overflow(a, b) ({typeof(a) s; __builtin_uadd_overflow(a, b, &s); })
  566. #else
  567. #define u32overflow(a, b) ((a) > ((a) + (b)))
  568. #endif /* __GNUC__ */
  569. void *Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags)
  570. {
  571. size_t Regionsize = MPU_REGION_SIZE_MIN;
  572. UINTPTR Basephysaddr = 0, end = Physaddr + size;
  573. if (!flags)
  574. return (void *)Physaddr;
  575. if (u32overflow(Physaddr, size))
  576. return NULL;
  577. for ( ; Regionsize != 0; Regionsize <<= 1) {
  578. if (Regionsize >= size) {
  579. Basephysaddr = Physaddr & ~(Regionsize - 1);
  580. if (u32overflow(Basephysaddr, Regionsize))
  581. break;
  582. if ((Basephysaddr + Regionsize) >= end)
  583. return Xil_SetMPURegion(Basephysaddr,
  584. Regionsize, flags) == XST_SUCCESS ?
  585. (void *)Physaddr : NULL;
  586. }
  587. }
  588. return NULL;
  589. }