gicdv2_helpers.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <drivers/arm/gic_common.h>
  8. #include <lib/mmio.h>
  9. #include "../common/gic_common_private.h"
  10. /*******************************************************************************
  11. * GIC Distributor interface accessors for reading entire registers
  12. ******************************************************************************/
  13. /*
  14. * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
  15. * `id`, 32 interrupt ids at a time.
  16. */
  17. unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
  18. {
  19. unsigned int n = id >> IGROUPR_SHIFT;
  20. return mmio_read_32(base + GICD_IGROUPR + (n << 2));
  21. }
  22. /*
  23. * Accessor to read the GIC Distributor ISENABLER corresponding to the
  24. * interrupt `id`, 32 interrupt ids at a time.
  25. */
  26. unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
  27. {
  28. unsigned int n = id >> ISENABLER_SHIFT;
  29. return mmio_read_32(base + GICD_ISENABLER + (n << 2));
  30. }
  31. /*
  32. * Accessor to read the GIC Distributor ICENABLER corresponding to the
  33. * interrupt `id`, 32 interrupt IDs at a time.
  34. */
  35. unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
  36. {
  37. unsigned int n = id >> ICENABLER_SHIFT;
  38. return mmio_read_32(base + GICD_ICENABLER + (n << 2));
  39. }
  40. /*
  41. * Accessor to read the GIC Distributor ISPENDR corresponding to the
  42. * interrupt `id`, 32 interrupt IDs at a time.
  43. */
  44. unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
  45. {
  46. unsigned int n = id >> ISPENDR_SHIFT;
  47. return mmio_read_32(base + GICD_ISPENDR + (n << 2));
  48. }
  49. /*
  50. * Accessor to read the GIC Distributor ICPENDR corresponding to the
  51. * interrupt `id`, 32 interrupt IDs at a time.
  52. */
  53. unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
  54. {
  55. unsigned int n = id >> ICPENDR_SHIFT;
  56. return mmio_read_32(base + GICD_ICPENDR + (n << 2));
  57. }
  58. /*
  59. * Accessor to read the GIC Distributor ISACTIVER corresponding to the
  60. * interrupt `id`, 32 interrupt IDs at a time.
  61. */
  62. unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
  63. {
  64. unsigned int n = id >> ISACTIVER_SHIFT;
  65. return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
  66. }
  67. /*
  68. * Accessor to read the GIC Distributor ICACTIVER corresponding to the
  69. * interrupt `id`, 32 interrupt IDs at a time.
  70. */
  71. unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
  72. {
  73. unsigned int n = id >> ICACTIVER_SHIFT;
  74. return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
  75. }
  76. /*
  77. * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
  78. * interrupt `id`, 4 interrupt IDs at a time.
  79. */
  80. unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
  81. {
  82. unsigned int n = id >> IPRIORITYR_SHIFT;
  83. return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
  84. }
  85. /*
  86. * Accessor to read the GIC Distributor ICGFR corresponding to the
  87. * interrupt `id`, 16 interrupt IDs at a time.
  88. */
  89. unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
  90. {
  91. unsigned int n = id >> ICFGR_SHIFT;
  92. return mmio_read_32(base + GICD_ICFGR + (n << 2));
  93. }
  94. /*
  95. * Accessor to read the GIC Distributor NSACR corresponding to the
  96. * interrupt `id`, 16 interrupt IDs at a time.
  97. */
  98. unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
  99. {
  100. unsigned int n = id >> NSACR_SHIFT;
  101. return mmio_read_32(base + GICD_NSACR + (n << 2));
  102. }
  103. /*******************************************************************************
  104. * GIC Distributor interface accessors for writing entire registers
  105. ******************************************************************************/
  106. /*
  107. * Accessor to write the GIC Distributor IGROUPR corresponding to the
  108. * interrupt `id`, 32 interrupt IDs at a time.
  109. */
  110. void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
  111. {
  112. unsigned int n = id >> IGROUPR_SHIFT;
  113. mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
  114. }
  115. /*
  116. * Accessor to write the GIC Distributor ISENABLER corresponding to the
  117. * interrupt `id`, 32 interrupt IDs at a time.
  118. */
  119. void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
  120. {
  121. unsigned int n = id >> ISENABLER_SHIFT;
  122. mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
  123. }
  124. /*
  125. * Accessor to write the GIC Distributor ICENABLER corresponding to the
  126. * interrupt `id`, 32 interrupt IDs at a time.
  127. */
  128. void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
  129. {
  130. unsigned int n = id >> ICENABLER_SHIFT;
  131. mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
  132. }
  133. /*
  134. * Accessor to write the GIC Distributor ISPENDR corresponding to the
  135. * interrupt `id`, 32 interrupt IDs at a time.
  136. */
  137. void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
  138. {
  139. unsigned int n = id >> ISPENDR_SHIFT;
  140. mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
  141. }
  142. /*
  143. * Accessor to write the GIC Distributor ICPENDR corresponding to the
  144. * interrupt `id`, 32 interrupt IDs at a time.
  145. */
  146. void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
  147. {
  148. unsigned int n = id >> ICPENDR_SHIFT;
  149. mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
  150. }
  151. /*
  152. * Accessor to write the GIC Distributor ISACTIVER corresponding to the
  153. * interrupt `id`, 32 interrupt IDs at a time.
  154. */
  155. void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
  156. {
  157. unsigned int n = id >> ISACTIVER_SHIFT;
  158. mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
  159. }
  160. /*
  161. * Accessor to write the GIC Distributor ICACTIVER corresponding to the
  162. * interrupt `id`, 32 interrupt IDs at a time.
  163. */
  164. void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
  165. {
  166. unsigned int n = id >> ICACTIVER_SHIFT;
  167. mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
  168. }
  169. /*
  170. * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
  171. * interrupt `id`, 4 interrupt IDs at a time.
  172. */
  173. void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
  174. {
  175. unsigned int n = id >> IPRIORITYR_SHIFT;
  176. mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
  177. }
  178. /*
  179. * Accessor to write the GIC Distributor ICFGR corresponding to the
  180. * interrupt `id`, 16 interrupt IDs at a time.
  181. */
  182. void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
  183. {
  184. unsigned int n = id >> ICFGR_SHIFT;
  185. mmio_write_32(base + GICD_ICFGR + (n << 2), val);
  186. }
  187. /*
  188. * Accessor to write the GIC Distributor NSACR corresponding to the
  189. * interrupt `id`, 16 interrupt IDs at a time.
  190. */
  191. void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
  192. {
  193. unsigned int n = id >> NSACR_SHIFT;
  194. mmio_write_32(base + GICD_NSACR + (n << 2), val);
  195. }
  196. /*******************************************************************************
  197. * GIC Distributor functions for accessing the GIC registers
  198. * corresponding to a single interrupt ID. These functions use bitwise
  199. * operations or appropriate register accesses to modify or return
  200. * the bit-field corresponding the single interrupt ID.
  201. ******************************************************************************/
  202. unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
  203. {
  204. unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
  205. unsigned int reg_val = gicd_read_igroupr(base, id);
  206. return (reg_val >> bit_num) & 0x1U;
  207. }
  208. void gicd_set_igroupr(uintptr_t base, unsigned int id)
  209. {
  210. unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
  211. unsigned int reg_val = gicd_read_igroupr(base, id);
  212. gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
  213. }
  214. void gicd_clr_igroupr(uintptr_t base, unsigned int id)
  215. {
  216. unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
  217. unsigned int reg_val = gicd_read_igroupr(base, id);
  218. gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
  219. }
  220. void gicd_set_isenabler(uintptr_t base, unsigned int id)
  221. {
  222. unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
  223. gicd_write_isenabler(base, id, (1U << bit_num));
  224. }
  225. void gicd_set_icenabler(uintptr_t base, unsigned int id)
  226. {
  227. unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
  228. gicd_write_icenabler(base, id, (1U << bit_num));
  229. }
  230. void gicd_set_ispendr(uintptr_t base, unsigned int id)
  231. {
  232. unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
  233. gicd_write_ispendr(base, id, (1U << bit_num));
  234. }
  235. void gicd_set_icpendr(uintptr_t base, unsigned int id)
  236. {
  237. unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
  238. gicd_write_icpendr(base, id, (1U << bit_num));
  239. }
  240. unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
  241. {
  242. unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
  243. unsigned int reg_val = gicd_read_isactiver(base, id);
  244. return (reg_val >> bit_num) & 0x1U;
  245. }
  246. void gicd_set_isactiver(uintptr_t base, unsigned int id)
  247. {
  248. unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
  249. gicd_write_isactiver(base, id, (1U << bit_num));
  250. }
  251. void gicd_set_icactiver(uintptr_t base, unsigned int id)
  252. {
  253. unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
  254. gicd_write_icactiver(base, id, (1U << bit_num));
  255. }
  256. void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
  257. {
  258. uint8_t val = pri & GIC_PRI_MASK;
  259. mmio_write_8(base + GICD_IPRIORITYR + id, val);
  260. }
  261. void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
  262. {
  263. /* Interrupt configuration is a 2-bit field */
  264. unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
  265. unsigned int bit_shift = bit_num << 1;
  266. uint32_t reg_val = gicd_read_icfgr(base, id);
  267. /* Clear the field, and insert required configuration */
  268. reg_val &= ~(GIC_CFG_MASK << bit_shift);
  269. reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
  270. gicd_write_icfgr(base, id, reg_val);
  271. }