gic_v2.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * Redistributions of source code must retain the above copyright notice, this
  8. * list of conditions and the following disclaimer.
  9. *
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * Neither the name of ARM nor the names of its contributors may be used
  15. * to endorse or promote products derived from this software without specific
  16. * prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include <assert.h>
  31. #include <gic.h>
  32. #include <mmio.h>
  33. /*******************************************************************************
  34. * GIC Distributor interface accessors for reading entire registers
  35. ******************************************************************************/
  36. unsigned int gicd_read_igroupr(unsigned int base, unsigned int id)
  37. {
  38. unsigned n = id >> IGROUPR_SHIFT;
  39. return mmio_read_32(base + GICD_IGROUPR + (n << 2));
  40. }
  41. unsigned int gicd_read_isenabler(unsigned int base, unsigned int id)
  42. {
  43. unsigned n = id >> ISENABLER_SHIFT;
  44. return mmio_read_32(base + GICD_ISENABLER + (n << 2));
  45. }
  46. unsigned int gicd_read_icenabler(unsigned int base, unsigned int id)
  47. {
  48. unsigned n = id >> ICENABLER_SHIFT;
  49. return mmio_read_32(base + GICD_ICENABLER + (n << 2));
  50. }
  51. unsigned int gicd_read_ispendr(unsigned int base, unsigned int id)
  52. {
  53. unsigned n = id >> ISPENDR_SHIFT;
  54. return mmio_read_32(base + GICD_ISPENDR + (n << 2));
  55. }
  56. unsigned int gicd_read_icpendr(unsigned int base, unsigned int id)
  57. {
  58. unsigned n = id >> ICPENDR_SHIFT;
  59. return mmio_read_32(base + GICD_ICPENDR + (n << 2));
  60. }
  61. unsigned int gicd_read_isactiver(unsigned int base, unsigned int id)
  62. {
  63. unsigned n = id >> ISACTIVER_SHIFT;
  64. return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
  65. }
  66. unsigned int gicd_read_icactiver(unsigned int base, unsigned int id)
  67. {
  68. unsigned n = id >> ICACTIVER_SHIFT;
  69. return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
  70. }
  71. unsigned int gicd_read_ipriorityr(unsigned int base, unsigned int id)
  72. {
  73. unsigned n = id >> IPRIORITYR_SHIFT;
  74. return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
  75. }
  76. unsigned int gicd_read_itargetsr(unsigned int base, unsigned int id)
  77. {
  78. unsigned n = id >> ITARGETSR_SHIFT;
  79. return mmio_read_32(base + GICD_ITARGETSR + (n << 2));
  80. }
  81. unsigned int gicd_read_icfgr(unsigned int base, unsigned int id)
  82. {
  83. unsigned n = id >> ICFGR_SHIFT;
  84. return mmio_read_32(base + GICD_ICFGR + (n << 2));
  85. }
  86. unsigned int gicd_read_cpendsgir(unsigned int base, unsigned int id)
  87. {
  88. unsigned n = id >> CPENDSGIR_SHIFT;
  89. return mmio_read_32(base + GICD_CPENDSGIR + (n << 2));
  90. }
  91. unsigned int gicd_read_spendsgir(unsigned int base, unsigned int id)
  92. {
  93. unsigned n = id >> SPENDSGIR_SHIFT;
  94. return mmio_read_32(base + GICD_SPENDSGIR + (n << 2));
  95. }
  96. /*******************************************************************************
  97. * GIC Distributor interface accessors for writing entire registers
  98. ******************************************************************************/
  99. void gicd_write_igroupr(unsigned int base, unsigned int id, unsigned int val)
  100. {
  101. unsigned n = id >> IGROUPR_SHIFT;
  102. mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
  103. }
  104. void gicd_write_isenabler(unsigned int base, unsigned int id, unsigned int val)
  105. {
  106. unsigned n = id >> ISENABLER_SHIFT;
  107. mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
  108. }
  109. void gicd_write_icenabler(unsigned int base, unsigned int id, unsigned int val)
  110. {
  111. unsigned n = id >> ICENABLER_SHIFT;
  112. mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
  113. }
  114. void gicd_write_ispendr(unsigned int base, unsigned int id, unsigned int val)
  115. {
  116. unsigned n = id >> ISPENDR_SHIFT;
  117. mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
  118. }
  119. void gicd_write_icpendr(unsigned int base, unsigned int id, unsigned int val)
  120. {
  121. unsigned n = id >> ICPENDR_SHIFT;
  122. mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
  123. }
  124. void gicd_write_isactiver(unsigned int base, unsigned int id, unsigned int val)
  125. {
  126. unsigned n = id >> ISACTIVER_SHIFT;
  127. mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
  128. }
  129. void gicd_write_icactiver(unsigned int base, unsigned int id, unsigned int val)
  130. {
  131. unsigned n = id >> ICACTIVER_SHIFT;
  132. mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
  133. }
  134. void gicd_write_ipriorityr(unsigned int base, unsigned int id, unsigned int val)
  135. {
  136. unsigned n = id >> IPRIORITYR_SHIFT;
  137. mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
  138. }
  139. void gicd_write_itargetsr(unsigned int base, unsigned int id, unsigned int val)
  140. {
  141. unsigned n = id >> ITARGETSR_SHIFT;
  142. mmio_write_32(base + GICD_ITARGETSR + (n << 2), val);
  143. }
  144. void gicd_write_icfgr(unsigned int base, unsigned int id, unsigned int val)
  145. {
  146. unsigned n = id >> ICFGR_SHIFT;
  147. mmio_write_32(base + GICD_ICFGR + (n << 2), val);
  148. }
  149. void gicd_write_cpendsgir(unsigned int base, unsigned int id, unsigned int val)
  150. {
  151. unsigned n = id >> CPENDSGIR_SHIFT;
  152. mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val);
  153. }
  154. void gicd_write_spendsgir(unsigned int base, unsigned int id, unsigned int val)
  155. {
  156. unsigned n = id >> SPENDSGIR_SHIFT;
  157. mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val);
  158. }
  159. /*******************************************************************************
  160. * GIC Distributor interface accessors for individual interrupt manipulation
  161. ******************************************************************************/
  162. unsigned int gicd_get_igroupr(unsigned int base, unsigned int id)
  163. {
  164. unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
  165. unsigned int reg_val = gicd_read_igroupr(base, id);
  166. return (reg_val >> bit_num) & 0x1;
  167. }
  168. void gicd_set_igroupr(unsigned int base, unsigned int id)
  169. {
  170. unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
  171. unsigned int reg_val = gicd_read_igroupr(base, id);
  172. gicd_write_igroupr(base, id, reg_val | (1 << bit_num));
  173. }
  174. void gicd_clr_igroupr(unsigned int base, unsigned int id)
  175. {
  176. unsigned bit_num = id & ((1 << IGROUPR_SHIFT) - 1);
  177. unsigned int reg_val = gicd_read_igroupr(base, id);
  178. gicd_write_igroupr(base, id, reg_val & ~(1 << bit_num));
  179. }
  180. void gicd_set_isenabler(unsigned int base, unsigned int id)
  181. {
  182. unsigned bit_num = id & ((1 << ISENABLER_SHIFT) - 1);
  183. unsigned int reg_val = gicd_read_isenabler(base, id);
  184. gicd_write_isenabler(base, id, reg_val | (1 << bit_num));
  185. }
  186. void gicd_set_icenabler(unsigned int base, unsigned int id)
  187. {
  188. unsigned bit_num = id & ((1 << ICENABLER_SHIFT) - 1);
  189. unsigned int reg_val = gicd_read_icenabler(base, id);
  190. gicd_write_icenabler(base, id, reg_val & ~(1 << bit_num));
  191. }
  192. void gicd_set_ispendr(unsigned int base, unsigned int id)
  193. {
  194. unsigned bit_num = id & ((1 << ISPENDR_SHIFT) - 1);
  195. unsigned int reg_val = gicd_read_ispendr(base, id);
  196. gicd_write_ispendr(base, id, reg_val | (1 << bit_num));
  197. }
  198. void gicd_set_icpendr(unsigned int base, unsigned int id)
  199. {
  200. unsigned bit_num = id & ((1 << ICPENDR_SHIFT) - 1);
  201. unsigned int reg_val = gicd_read_icpendr(base, id);
  202. gicd_write_icpendr(base, id, reg_val & ~(1 << bit_num));
  203. }
  204. void gicd_set_isactiver(unsigned int base, unsigned int id)
  205. {
  206. unsigned bit_num = id & ((1 << ISACTIVER_SHIFT) - 1);
  207. unsigned int reg_val = gicd_read_isactiver(base, id);
  208. gicd_write_isactiver(base, id, reg_val | (1 << bit_num));
  209. }
  210. void gicd_set_icactiver(unsigned int base, unsigned int id)
  211. {
  212. unsigned bit_num = id & ((1 << ICACTIVER_SHIFT) - 1);
  213. unsigned int reg_val = gicd_read_icactiver(base, id);
  214. gicd_write_icactiver(base, id, reg_val & ~(1 << bit_num));
  215. }
  216. /*
  217. * Make sure that the interrupt's group is set before expecting
  218. * this function to do its job correctly.
  219. */
  220. void gicd_set_ipriorityr(unsigned int base, unsigned int id, unsigned int pri)
  221. {
  222. unsigned int reg = base + GICD_IPRIORITYR + (id & ~3);
  223. unsigned int shift = (id & 3) << 3;
  224. unsigned int reg_val = mmio_read_32(reg);
  225. /*
  226. * Enforce ARM recommendation to manage priority values such
  227. * that group1 interrupts always have a lower priority than
  228. * group0 interrupts.
  229. * Note, lower numerical values are higher priorities so the comparison
  230. * checks below are reversed from what might be expected.
  231. */
  232. assert(gicd_get_igroupr(base, id) == GRP1 ?
  233. pri >= GIC_HIGHEST_NS_PRIORITY &&
  234. pri <= GIC_LOWEST_NS_PRIORITY :
  235. pri >= GIC_HIGHEST_SEC_PRIORITY &&
  236. pri <= GIC_LOWEST_SEC_PRIORITY);
  237. reg_val &= ~(GIC_PRI_MASK << shift);
  238. reg_val |= (pri & GIC_PRI_MASK) << shift;
  239. mmio_write_32(reg, reg_val);
  240. }
  241. void gicd_set_itargetsr(unsigned int base, unsigned int id, unsigned int iface)
  242. {
  243. unsigned byte_off = id & ((1 << ITARGETSR_SHIFT) - 1);
  244. unsigned int reg_val = gicd_read_itargetsr(base, id);
  245. gicd_write_itargetsr(base, id, reg_val |
  246. (1 << iface) << (byte_off << 3));
  247. }