gic600ae_fmu_helpers.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <arch.h>
  9. #include <arch_helpers.h>
  10. #include <drivers/arm/gic600ae_fmu.h>
  11. #include <drivers/delay_timer.h>
  12. #include <lib/mmio.h>
  13. #define GICFMU_IDLE_TIMEOUT_US U(2000000)
  14. /* Macro to write 32-bit FMU registers */
  15. #define GIC_FMU_WRITE_32(base, reg, val) \
  16. do { \
  17. /* \
  18. * This register receives the unlock key that is required for \
  19. * writes to FMU registers to be successful. \
  20. */ \
  21. mmio_write_32(base + GICFMU_KEY, 0xBE); \
  22. /* Perform the actual write */ \
  23. mmio_write_32((base) + (reg), (val)); \
  24. } while (false)
  25. /* Macro to write 64-bit FMU registers */
  26. #define GIC_FMU_WRITE_64(base, reg, n, val) \
  27. do { \
  28. /* \
  29. * This register receives the unlock key that is required for \
  30. * writes to FMU registers to be successful. \
  31. */ \
  32. mmio_write_32(base + GICFMU_KEY, 0xBE); \
  33. /* \
  34. * APB bus is 32-bit wide; so split the 64-bit write into \
  35. * two 32-bit writes \
  36. */ \
  37. mmio_write_32((base) + reg##_LO + (n * 64), (val)); \
  38. mmio_write_32((base) + reg##_HI + (n * 64), (val)); \
  39. } while (false)
  40. /* Helper function to wait until FMU is ready to accept the next command */
  41. static void wait_until_fmu_is_idle(uintptr_t base)
  42. {
  43. uint32_t timeout_count = GICFMU_IDLE_TIMEOUT_US;
  44. uint64_t status;
  45. /* wait until status is 'busy' */
  46. do {
  47. status = (gic_fmu_read_status(base) & BIT(0));
  48. if (timeout_count-- == 0U) {
  49. ERROR("GIC600 AE FMU is not responding\n");
  50. panic();
  51. }
  52. udelay(1U);
  53. } while (status == U(0));
  54. }
  55. #define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \
  56. do { \
  57. /* Wait until FMU is ready */ \
  58. wait_until_fmu_is_idle(base); \
  59. /* Actual register write */ \
  60. GIC_FMU_WRITE_32(base, reg, val); \
  61. /* Wait until FMU is ready */ \
  62. wait_until_fmu_is_idle(base); \
  63. } while (false)
  64. #define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \
  65. do { \
  66. /* Wait until FMU is ready */ \
  67. wait_until_fmu_is_idle(base); \
  68. /* Actual register write */ \
  69. GIC_FMU_WRITE_64(base, reg, n, val); \
  70. /* Wait until FMU is ready */ \
  71. wait_until_fmu_is_idle(base); \
  72. } while (false)
  73. /*******************************************************************************
  74. * GIC FMU functions for accessing the Fault Management Unit registers
  75. ******************************************************************************/
  76. /*
  77. * Accessors to read the Error Record Feature Register bits corresponding
  78. * to an error record 'n'
  79. */
  80. uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n)
  81. {
  82. /*
  83. * APB bus is 32-bit wide; so split the 64-bit read into
  84. * two 32-bit reads
  85. */
  86. uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U);
  87. reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32);
  88. return reg_val;
  89. }
  90. /*
  91. * Accessors to read the Error Record Control Register bits corresponding
  92. * to an error record 'n'
  93. */
  94. uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n)
  95. {
  96. /*
  97. * APB bus is 32-bit wide; so split the 64-bit read into
  98. * two 32-bit reads
  99. */
  100. uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U);
  101. reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32);
  102. return reg_val;
  103. }
  104. /*
  105. * Accessors to read the Error Record Primary Status Register bits
  106. * corresponding to an error record 'n'
  107. */
  108. uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n)
  109. {
  110. /*
  111. * APB bus is 32-bit wide; so split the 64-bit read into
  112. * two 32-bit reads
  113. */
  114. uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U);
  115. reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32);
  116. return reg_val;
  117. }
  118. /*
  119. * Accessors to read the Error Group Status Register
  120. */
  121. uint64_t gic_fmu_read_errgsr(uintptr_t base)
  122. {
  123. /*
  124. * APB bus is 32-bit wide; so split the 64-bit read into
  125. * two 32-bit reads
  126. */
  127. uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO);
  128. reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32);
  129. return reg_val;
  130. }
  131. /*
  132. * Accessors to read the Ping Control Register
  133. */
  134. uint32_t gic_fmu_read_pingctlr(uintptr_t base)
  135. {
  136. return mmio_read_32(base + GICFMU_PINGCTLR);
  137. }
  138. /*
  139. * Accessors to read the Ping Now Register
  140. */
  141. uint32_t gic_fmu_read_pingnow(uintptr_t base)
  142. {
  143. return mmio_read_32(base + GICFMU_PINGNOW);
  144. }
  145. /*
  146. * Accessors to read the Ping Mask Register
  147. */
  148. uint64_t gic_fmu_read_pingmask(uintptr_t base)
  149. {
  150. /*
  151. * APB bus is 32-bit wide; so split the 64-bit read into
  152. * two 32-bit reads
  153. */
  154. uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO);
  155. reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32);
  156. return reg_val;
  157. }
  158. /*
  159. * Accessors to read the FMU Status Register
  160. */
  161. uint32_t gic_fmu_read_status(uintptr_t base)
  162. {
  163. return mmio_read_32(base + GICFMU_STATUS);
  164. }
  165. /*
  166. * Accessors to read the Error Record ID Register
  167. */
  168. uint32_t gic_fmu_read_erridr(uintptr_t base)
  169. {
  170. return mmio_read_32(base + GICFMU_ERRIDR);
  171. }
  172. /*
  173. * Accessors to write a 64 bit value to the Error Record Control Register
  174. */
  175. void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val)
  176. {
  177. GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val);
  178. }
  179. /*
  180. * Accessors to write a 64 bit value to the Error Record Primary Status
  181. * Register
  182. */
  183. void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val)
  184. {
  185. /* Wait until FMU is ready before writing */
  186. GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val);
  187. }
  188. /*
  189. * Accessors to write a 32 bit value to the Ping Control Register
  190. */
  191. void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val)
  192. {
  193. GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val);
  194. }
  195. /*
  196. * Accessors to write a 32 bit value to the Ping Now Register
  197. */
  198. void gic_fmu_write_pingnow(uintptr_t base, uint32_t val)
  199. {
  200. /* Wait until FMU is ready before writing */
  201. GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val);
  202. }
  203. /*
  204. * Accessors to write a 32 bit value to the Safety Mechanism Enable Register
  205. */
  206. void gic_fmu_write_smen(uintptr_t base, uint32_t val)
  207. {
  208. /* Wait until FMU is ready before writing */
  209. GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val);
  210. }
  211. /*
  212. * Accessors to write a 32 bit value to the Safety Mechanism Inject Error
  213. * Register
  214. */
  215. void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val)
  216. {
  217. /* Wait until FMU is ready before writing */
  218. GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val);
  219. }
  220. /*
  221. * Accessors to write a 64 bit value to the Ping Mask Register
  222. */
  223. void gic_fmu_write_pingmask(uintptr_t base, uint64_t val)
  224. {
  225. GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
  226. }
  227. /*
  228. * Helper function to disable all safety mechanisms for a given block
  229. */
  230. void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid)
  231. {
  232. uint32_t smen, max_smid = U(0);
  233. /* Sanity check block ID */
  234. assert((blkid >= FMU_BLK_GICD) && (blkid <= FMU_BLK_PPI31));
  235. /* Find the max safety mechanism ID for the block */
  236. switch (blkid) {
  237. case FMU_BLK_GICD:
  238. max_smid = FMU_SMID_GICD_MAX;
  239. break;
  240. case FMU_BLK_SPICOL:
  241. max_smid = FMU_SMID_SPICOL_MAX;
  242. break;
  243. case FMU_BLK_WAKERQ:
  244. max_smid = FMU_SMID_WAKERQ_MAX;
  245. break;
  246. case FMU_BLK_ITS0...FMU_BLK_ITS7:
  247. max_smid = FMU_SMID_ITS_MAX;
  248. break;
  249. case FMU_BLK_PPI0...FMU_BLK_PPI31:
  250. max_smid = FMU_SMID_PPI_MAX;
  251. break;
  252. default:
  253. assert(false);
  254. break;
  255. }
  256. /* Disable all Safety Mechanisms for a given block id */
  257. for (unsigned int i = 0U; i < max_smid; i++) {
  258. smen = (blkid << FMU_SMEN_BLK_SHIFT) | (i << FMU_SMEN_SMID_SHIFT);
  259. gic_fmu_write_smen(base, smen);
  260. }
  261. }