gsi_emulation.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include "gsi_emulation.h"
  6. /*
  7. * *****************************************************************************
  8. * The following used to set up the EMULATION interrupt controller...
  9. * *****************************************************************************
  10. */
  11. int setup_emulator_cntrlr(
  12. void __iomem *intcntrlr_base,
  13. u32 intcntrlr_mem_size)
  14. {
  15. uint32_t val, ver, intrCnt, rangeCnt, range;
  16. val = gsi_emu_readl(intcntrlr_base + GE_INT_CTL_VER_CNT);
  17. intrCnt = val & 0xFFFF;
  18. ver = (val >> 16) & 0xFFFF;
  19. rangeCnt = intrCnt / 32;
  20. GSIDBG(
  21. "CTL_VER_CNT reg val(0x%x) intr cnt(%u) cntrlr ver(0x%x) rangeCnt(%u)\n",
  22. val, intrCnt, ver, rangeCnt);
  23. /*
  24. * Verify the interrupt controller version
  25. */
  26. if (ver == 0 || ver == 0xFFFF || ver < DEO_IC_INT_CTL_VER_MIN) {
  27. GSIERR(
  28. "Error: invalid interrupt controller version 0x%x\n",
  29. ver);
  30. return -GSI_STATUS_INVALID_PARAMS;
  31. }
  32. /*
  33. * Verify the interrupt count
  34. *
  35. * NOTE: intrCnt must be at least one block and multiple of 32
  36. */
  37. if ((intrCnt % 32) != 0) {
  38. GSIERR(
  39. "Invalid interrupt count read from HW 0x%04x\n",
  40. intrCnt);
  41. return -GSI_STATUS_ERROR;
  42. }
  43. /*
  44. * Calculate number of ranges used, each range handles 32 int lines
  45. */
  46. if (rangeCnt > DEO_IC_MAX_RANGE_CNT) {
  47. GSIERR(
  48. "SW interrupt limit(%u) passed, increase DEO_IC_MAX_RANGE_CNT(%u)\n",
  49. rangeCnt,
  50. DEO_IC_MAX_RANGE_CNT);
  51. return -GSI_STATUS_ERROR;
  52. }
  53. /*
  54. * Let's take the last register offset minus the first
  55. * register offset (ie. range) and compare it to the interrupt
  56. * controller's dtsi defined memory size. The range better
  57. * fit within the size.
  58. */
  59. val = GE_SOFT_INT_n(rangeCnt-1) - GE_INT_CTL_VER_CNT;
  60. if (val > intcntrlr_mem_size) {
  61. GSIERR(
  62. "Interrupt controller register range (%u) exceeds dtsi provisioned size (%u)\n",
  63. val, intcntrlr_mem_size);
  64. return -GSI_STATUS_ERROR;
  65. }
  66. /*
  67. * The following will disable the emulators interrupt controller,
  68. * so that we can config it...
  69. */
  70. GSIDBG("Writing GE_INT_MASTER_ENABLE\n");
  71. gsi_emu_writel(
  72. 0x0,
  73. intcntrlr_base + GE_INT_MASTER_ENABLE);
  74. /*
  75. * Init register maps of all ranges
  76. */
  77. for (range = 0; range < rangeCnt; range++) {
  78. /*
  79. * Disable all int sources by setting all enable clear bits
  80. */
  81. GSIDBG("Writing GE_INT_ENABLE_CLEAR_n(%u)\n", range);
  82. gsi_emu_writel(
  83. 0xFFFFFFFF,
  84. intcntrlr_base + GE_INT_ENABLE_CLEAR_n(range));
  85. /*
  86. * Clear all raw statuses
  87. */
  88. GSIDBG("Writing GE_INT_CLEAR_n(%u)\n", range);
  89. gsi_emu_writel(
  90. 0xFFFFFFFF,
  91. intcntrlr_base + GE_INT_CLEAR_n(range));
  92. /*
  93. * Init all int types
  94. */
  95. GSIDBG("Writing GE_INT_TYPE_n(%u)\n", range);
  96. gsi_emu_writel(
  97. 0x0,
  98. intcntrlr_base + GE_INT_TYPE_n(range));
  99. }
  100. /*
  101. * The following tells the interrupt controller to interrupt us
  102. * when it sees interrupts from ipa and/or gsi.
  103. *
  104. * Interrupts:
  105. * ===================================================================
  106. * DUT0 [ 63 : 16 ]
  107. * ipa_irq [ 3 : 0 ] <---HERE
  108. * ipa_gsi_bam_irq [ 7 : 4 ] <---HERE
  109. * ipa_bam_apu_sec_error_irq [ 8 ]
  110. * ipa_bam_apu_non_sec_error_irq [ 9 ]
  111. * ipa_bam_xpu2_msa_intr [ 10 ]
  112. * ipa_vmidmt_nsgcfgirpt [ 11 ]
  113. * ipa_vmidmt_nsgirpt [ 12 ]
  114. * ipa_vmidmt_gcfgirpt [ 13 ]
  115. * ipa_vmidmt_girpt [ 14 ]
  116. * bam_xpu3_qad_non_secure_intr_sp [ 15 ]
  117. */
  118. GSIDBG("Writing GE_INT_ENABLE_n(0)\n");
  119. gsi_emu_writel(
  120. 0x00FF, /* See <---HERE above */
  121. intcntrlr_base + GE_INT_ENABLE_n(0));
  122. /*
  123. * The following will enable the IC post config...
  124. */
  125. GSIDBG("Writing GE_INT_MASTER_ENABLE\n");
  126. gsi_emu_writel(
  127. 0x1,
  128. intcntrlr_base + GE_INT_MASTER_ENABLE);
  129. return 0;
  130. }
  131. /*
  132. * *****************************************************************************
  133. * The following for EMULATION hard irq...
  134. * *****************************************************************************
  135. */
  136. irqreturn_t emulator_hard_irq_isr(
  137. int irq,
  138. void *ctxt)
  139. {
  140. struct gsi_ctx *gsi_ctx_ptr = (struct gsi_ctx *) ctxt;
  141. uint32_t val;
  142. val = gsi_emu_readl(gsi_ctx_ptr->intcntrlr_base + GE_INT_MASTER_STATUS);
  143. /*
  144. * If bit zero is set, interrupt is for us, hence return IRQ_NONE
  145. * when it's not set...
  146. */
  147. if (!(val & 0x00000001))
  148. return IRQ_NONE;
  149. /*
  150. * The following will mask (ie. turn off) future interrupts from
  151. * the emulator's interrupt controller. It wil stay this way until
  152. * we turn back on...which will be done in the bottom half
  153. * (ie. emulator_soft_irq_isr)...
  154. */
  155. gsi_emu_writel(
  156. 0x0,
  157. gsi_ctx_ptr->intcntrlr_base + GE_INT_OUT_ENABLE);
  158. return IRQ_WAKE_THREAD;
  159. }
  160. /*
  161. * *****************************************************************************
  162. * The following for EMULATION soft irq...
  163. * *****************************************************************************
  164. */
  165. irqreturn_t emulator_soft_irq_isr(
  166. int irq,
  167. void *ctxt)
  168. {
  169. struct gsi_ctx *gsi_ctx_ptr = (struct gsi_ctx *) ctxt;
  170. irqreturn_t retVal = IRQ_HANDLED;
  171. uint32_t val;
  172. val = gsi_emu_readl(gsi_ctx_ptr->intcntrlr_base + GE_IRQ_STATUS_n(0));
  173. GSIDBG("Got irq(%d) with status(0x%08X)\n", irq, val);
  174. if (val & 0xF0 && gsi_ctx_ptr->intcntrlr_gsi_isr) {
  175. GSIDBG("Got gsi interrupt\n");
  176. retVal = gsi_ctx_ptr->intcntrlr_gsi_isr(irq, ctxt);
  177. }
  178. if (val & 0x0F && gsi_ctx_ptr->intcntrlr_client_isr) {
  179. GSIDBG("Got ipa interrupt\n");
  180. retVal = gsi_ctx_ptr->intcntrlr_client_isr(irq, 0);
  181. }
  182. /*
  183. * The following will clear the interrupts...
  184. */
  185. gsi_emu_writel(
  186. 0xFFFFFFFF,
  187. gsi_ctx_ptr->intcntrlr_base + GE_INT_CLEAR_n(0));
  188. /*
  189. * The following will unmask (ie. turn on) future interrupts from
  190. * the emulator's interrupt controller...
  191. */
  192. gsi_emu_writel(
  193. 0x1,
  194. gsi_ctx_ptr->intcntrlr_base + GE_INT_OUT_ENABLE);
  195. return retVal;
  196. }