You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

340 regels
14 KiB

  1. /*
  2. * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2020 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_sysmpu.h"
  9. /* Component ID definition, used by tools. */
  10. #ifndef FSL_COMPONENT_ID
  11. #define FSL_COMPONENT_ID "platform.drivers.sysmpu"
  12. #endif
  13. /*******************************************************************************
  14. * Variables
  15. ******************************************************************************/
  16. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  17. static const clock_ip_name_t g_sysmpuClock[] = SYSMPU_CLOCKS;
  18. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  19. /*******************************************************************************
  20. * Codes
  21. ******************************************************************************/
  22. /*!
  23. * brief Initializes the SYSMPU with the user configuration structure.
  24. *
  25. * This function configures the SYSMPU module with the user-defined configuration.
  26. *
  27. * param base SYSMPU peripheral base address.
  28. * param config The pointer to the configuration structure.
  29. */
  30. void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config)
  31. {
  32. assert(config);
  33. uint8_t count;
  34. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  35. /* Un-gate SYSMPU clock */
  36. CLOCK_EnableClock(g_sysmpuClock[0]);
  37. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  38. /* Initializes the regions. */
  39. for (count = 1; count < (uint32_t)FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT; count++)
  40. {
  41. base->WORD[count][3] = 0; /* VLD/VID+PID. */
  42. base->WORD[count][0] = 0; /* Start address. */
  43. base->WORD[count][1] = 0; /* End address. */
  44. base->WORD[count][2] = 0; /* Access rights. */
  45. base->RGDAAC[count] = 0; /* Alternate access rights. */
  46. }
  47. /* SYSMPU configure. */
  48. while (config != NULL)
  49. {
  50. SYSMPU_SetRegionConfig(base, &(config->regionConfig));
  51. config = config->next;
  52. }
  53. /* Enable SYSMPU. */
  54. SYSMPU_Enable(base, true);
  55. }
  56. /*!
  57. * brief Deinitializes the SYSMPU regions.
  58. *
  59. * param base SYSMPU peripheral base address.
  60. */
  61. void SYSMPU_Deinit(SYSMPU_Type *base)
  62. {
  63. /* Disable SYSMPU. */
  64. SYSMPU_Enable(base, false);
  65. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  66. /* Gate the clock. */
  67. CLOCK_DisableClock(g_sysmpuClock[0]);
  68. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  69. }
  70. /*!
  71. * brief Gets the SYSMPU basic hardware information.
  72. *
  73. * param base SYSMPU peripheral base address.
  74. * param hardwareInform The pointer to the SYSMPU hardware information structure. See "sysmpu_hardware_info_t".
  75. */
  76. void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform)
  77. {
  78. assert(hardwareInform);
  79. uint32_t cesReg = base->CESR;
  80. uint32_t regionsNumber_temp = (cesReg & SYSMPU_CESR_NRGD_MASK) >> SYSMPU_CESR_NRGD_SHIFT;
  81. hardwareInform->hardwareRevisionLevel = (uint8_t)((cesReg & SYSMPU_CESR_HRL_MASK) >> SYSMPU_CESR_HRL_SHIFT);
  82. hardwareInform->slavePortsNumbers = (uint8_t)((cesReg & SYSMPU_CESR_NSP_MASK) >> SYSMPU_CESR_NSP_SHIFT);
  83. hardwareInform->regionsNumbers = (sysmpu_region_total_num_t)(regionsNumber_temp);
  84. }
  85. /*!
  86. * brief Sets the SYSMPU region.
  87. *
  88. * Note: Due to the SYSMPU protection, the region number 0 does not allow writes from
  89. * core to affect the start and end address nor the permissions associated with
  90. * the debugger. It can only write the permission fields associated
  91. * with the other masters.
  92. *
  93. * param base SYSMPU peripheral base address.
  94. * param regionConfig The pointer to the SYSMPU user configuration structure. See "sysmpu_region_config_t".
  95. */
  96. void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig)
  97. {
  98. assert(regionConfig);
  99. assert(regionConfig->regionNum < (uint32_t)FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT);
  100. uint32_t wordReg = 0;
  101. uint8_t msPortNum;
  102. uint8_t regNumber = (uint8_t)regionConfig->regionNum;
  103. /* The start and end address of the region descriptor. */
  104. base->WORD[regNumber][0] = regionConfig->startAddress;
  105. base->WORD[regNumber][1] = regionConfig->endAddress;
  106. /* Set the privilege rights for master 0 ~ master 3. */
  107. for (msPortNum = 0; msPortNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum++)
  108. {
  109. wordReg |= SYSMPU_REGION_RWXRIGHTS_MASTER(
  110. msPortNum, (((uint32_t)regionConfig->accessRights1[msPortNum].superAccessRights << 3U) |
  111. (uint32_t)regionConfig->accessRights1[msPortNum].userAccessRights));
  112. #if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER
  113. wordReg |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE(msPortNum,
  114. regionConfig->accessRights1[msPortNum].processIdentifierEnable);
  115. #endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */
  116. }
  117. #if FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT
  118. /* Set the normal read write rights for master 4 ~ master 7. */
  119. for (msPortNum = SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum < (uint32_t)FSL_FEATURE_SYSMPU_MASTER_COUNT;
  120. msPortNum++)
  121. {
  122. wordReg |= SYSMPU_REGION_RWRIGHTS_MASTER(
  123. msPortNum,
  124. ((uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].readEnable << 1U |
  125. (uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].writeEnable));
  126. }
  127. #endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT */
  128. /* Set region descriptor access rights. */
  129. base->WORD[regNumber][2] = wordReg;
  130. wordReg = SYSMPU_WORD_VLD(1);
  131. #if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER
  132. wordReg |= SYSMPU_WORD_PID(regionConfig->processIdentifier) | SYSMPU_WORD_PIDMASK(regionConfig->processIdMask);
  133. #endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */
  134. base->WORD[regNumber][3] = wordReg;
  135. }
  136. /*!
  137. * brief Sets the region start and end address.
  138. *
  139. * Memory region start address. Note: bit0 ~ bit4 is always marked as 0 by SYSMPU.
  140. * The actual start address by SYSMPU is 0-modulo-32 byte address.
  141. * Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU.
  142. * The end address used by the SYSMPU is 31-modulo-32 byte address.
  143. * Note: Due to the SYSMPU protection, the startAddr and endAddr can't be
  144. * changed by the core when regionNum is 0.
  145. *
  146. * param base SYSMPU peripheral base address.
  147. * param regionNum SYSMPU region number. The range is from 0 to
  148. * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1.
  149. * param startAddr Region start address.
  150. * param endAddr Region end address.
  151. */
  152. void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr)
  153. {
  154. assert(regionNum < (uint32_t)FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT);
  155. base->WORD[regionNum][0] = startAddr;
  156. base->WORD[regionNum][1] = endAddr;
  157. }
  158. /*!
  159. * brief Sets the SYSMPU region access rights for masters with read, write, and execute rights.
  160. * The SYSMPU access rights depend on two board classifications of bus masters.
  161. * The privilege rights masters and the normal rights masters.
  162. * The privilege rights masters have the read, write, and execute access rights.
  163. * Except the normal read and write rights, the execute rights are also
  164. * allowed for these masters. The privilege rights masters normally range from
  165. * bus masters 0 - 3. However, the maximum master number is device-specific.
  166. * See the "SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX".
  167. * The normal rights masters access rights control see
  168. * "SYSMPU_SetRegionRwMasterAccessRights()".
  169. *
  170. * param base SYSMPU peripheral base address.
  171. * param regionNum SYSMPU region number. Should range from 0 to
  172. * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1.
  173. * param masterNum SYSMPU bus master number. Should range from 0 to
  174. * SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX.
  175. * param accessRights The pointer to the SYSMPU access rights configuration. See
  176. * "sysmpu_rwxrights_master_access_control_t".
  177. */
  178. void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base,
  179. uint32_t regionNum,
  180. uint32_t masterNum,
  181. const sysmpu_rwxrights_master_access_control_t *accessRights)
  182. {
  183. assert(accessRights);
  184. assert(regionNum < (uint32_t)FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT);
  185. assert(masterNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT);
  186. uint32_t mask = SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(masterNum);
  187. uint32_t right = base->RGDAAC[regionNum];
  188. #if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER
  189. mask |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(masterNum);
  190. #endif
  191. /* Build rights control value. */
  192. right &= ~mask;
  193. right |= SYSMPU_REGION_RWXRIGHTS_MASTER(
  194. masterNum, (((uint32_t)accessRights->superAccessRights << 3U) | (uint32_t)accessRights->userAccessRights));
  195. #if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER
  196. right |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE(masterNum, accessRights->processIdentifierEnable);
  197. #endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */
  198. /* Set low master region access rights. */
  199. base->RGDAAC[regionNum] = right;
  200. }
  201. #if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4
  202. /*!
  203. * brief Sets the SYSMPU region access rights for masters with read and write rights.
  204. * The SYSMPU access rights depend on two board classifications of bus masters.
  205. * The privilege rights masters and the normal rights masters.
  206. * The normal rights masters only have the read and write access permissions.
  207. * The privilege rights access control see "SYSMPU_SetRegionRwxMasterAccessRights".
  208. *
  209. * param base SYSMPU peripheral base address.
  210. * param regionNum SYSMPU region number. The range is from 0 to
  211. * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1.
  212. * param masterNum SYSMPU bus master number. Should range from SYSMPU_MASTER_RWATTRIBUTE_START_PORT
  213. * to ~ FSL_FEATURE_SYSMPU_MASTER_COUNT - 1.
  214. * param accessRights The pointer to the SYSMPU access rights configuration. See
  215. * "sysmpu_rwrights_master_access_control_t".
  216. */
  217. void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base,
  218. uint32_t regionNum,
  219. uint32_t masterNum,
  220. const sysmpu_rwrights_master_access_control_t *accessRights)
  221. {
  222. assert(accessRights);
  223. assert(regionNum < (uint32_t)FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT);
  224. assert(masterNum >= SYSMPU_MASTER_RWATTRIBUTE_START_PORT);
  225. assert(masterNum <= ((uint32_t)FSL_FEATURE_SYSMPU_MASTER_COUNT - 1U));
  226. uint32_t mask = SYSMPU_REGION_RWRIGHTS_MASTER_MASK(masterNum);
  227. uint32_t right = base->RGDAAC[regionNum];
  228. /* Build rights control value. */
  229. right &= ~mask;
  230. right |= SYSMPU_REGION_RWRIGHTS_MASTER(
  231. masterNum, (((uint32_t)accessRights->readEnable << 1U) | (uint32_t)accessRights->writeEnable));
  232. /* Set low master region access rights. */
  233. base->RGDAAC[regionNum] = right;
  234. }
  235. #endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */
  236. /*!
  237. * brief Gets the numbers of slave ports where errors occur.
  238. *
  239. * param base SYSMPU peripheral base address.
  240. * param slaveNum SYSMPU slave port number.
  241. * return The slave ports error status.
  242. * true - error happens in this slave port.
  243. * false - error didn't happen in this slave port.
  244. */
  245. bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum)
  246. {
  247. uint8_t sperr;
  248. sperr = (uint8_t)(((base->CESR & SYSMPU_CESR_SPERR_MASK) >> SYSMPU_CESR_SPERR_SHIFT) &
  249. (0x1U << ((uint32_t)FSL_FEATURE_SYSMPU_SLAVE_COUNT - (uint32_t)slaveNum - 1U)));
  250. return (sperr != 0U) ? true : false;
  251. }
  252. /*!
  253. * brief Gets the SYSMPU detailed error access information.
  254. *
  255. * param base SYSMPU peripheral base address.
  256. * param slaveNum SYSMPU slave port number.
  257. * param errInform The pointer to the SYSMPU access error information. See "sysmpu_access_err_info_t".
  258. */
  259. void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform)
  260. {
  261. assert(errInform);
  262. uint32_t value;
  263. uint32_t cesReg;
  264. uint32_t attributes_temp;
  265. uint32_t accessType_temp;
  266. /* Error address. */
  267. errInform->address = base->SP[slaveNum].EAR;
  268. /* Error detail information. */
  269. value = (base->SP[slaveNum].EDR & SYSMPU_EDR_EACD_MASK) >> SYSMPU_EDR_EACD_SHIFT;
  270. if (value == 0U)
  271. {
  272. errInform->accessControl = kSYSMPU_NoRegionHit;
  273. }
  274. else if ((value & (uint16_t)(value - 1U)) == 0U)
  275. {
  276. errInform->accessControl = kSYSMPU_NoneOverlappRegion;
  277. }
  278. else
  279. {
  280. errInform->accessControl = kSYSMPU_OverlappRegion;
  281. }
  282. value = base->SP[slaveNum].EDR & (~SYSMPU_EDR_EACD_MASK);
  283. attributes_temp = (value & SYSMPU_EDR_EATTR_MASK) >> SYSMPU_EDR_EATTR_SHIFT;
  284. accessType_temp = (value & SYSMPU_EDR_ERW_MASK) >> SYSMPU_EDR_ERW_SHIFT;
  285. errInform->master = (value & SYSMPU_EDR_EMN_MASK) >> SYSMPU_EDR_EMN_SHIFT;
  286. errInform->attributes = (sysmpu_err_attributes_t)attributes_temp;
  287. errInform->accessType = (sysmpu_err_access_type_t)accessType_temp;
  288. #if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER
  289. errInform->processorIdentification = (uint8_t)((value & SYSMPU_EDR_EPID_MASK) >> SYSMPU_EDR_EPID_SHIFT);
  290. #endif
  291. /* Clears error slave port bit. */
  292. cesReg =
  293. (base->CESR & ~SYSMPU_CESR_SPERR_MASK) |
  294. ((0x1UL << ((uint32_t)FSL_FEATURE_SYSMPU_SLAVE_COUNT - (uint32_t)slaveNum - 1U)) << SYSMPU_CESR_SPERR_SHIFT);
  295. base->CESR = cesReg;
  296. }