tz_irq.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include <linux/module.h>
  2. #include <linux/types.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/slab.h>
  5. #include <linux/irqdomain.h>
  6. #include <linux/of_irq.h>
  7. #include <dt-bindings/interrupt-controller/arm-gic.h>
  8. #include "tz_cross/trustzone.h"
  9. #include "tz_cross/ta_system.h"
  10. #include "tz_cross/ta_irq.h"
  11. #include "trustzone/kree/system.h"
  12. #include "kree_int.h"
  13. static struct irq_domain *sysirq;
  14. static struct device_node *sysirq_node;
  15. /*************************************************************
  16. * REE Service
  17. *************************************************************/
  18. static irqreturn_t KREE_IrqHandler(int virq, void *dev)
  19. {
  20. struct irq_data *data = irq_get_irq_data(virq);
  21. uint32_t paramTypes;
  22. MTEEC_PARAM param[4];
  23. TZ_RESULT ret;
  24. if (!data)
  25. return IRQ_NONE;
  26. /* +32, support SPI only */
  27. param[0].value.a = (uint32_t) irqd_to_hwirq(data) + 32;
  28. paramTypes = TZ_ParamTypes1(TZPT_VALUE_INPUT);
  29. ret = KREE_TeeServiceCall(
  30. (KREE_SESSION_HANDLE) MTEE_SESSION_HANDLE_SYSTEM,
  31. TZCMD_SYS_IRQ, paramTypes, param);
  32. return (ret == TZ_RESULT_SUCCESS) ? IRQ_HANDLED : IRQ_NONE;
  33. }
  34. static unsigned int tz_hwirq_to_virq(unsigned int hwirq, unsigned long flags)
  35. {
  36. struct of_phandle_args oirq;
  37. if (sysirq_node) {
  38. oirq.np = sysirq_node;
  39. oirq.args_count = 3;
  40. oirq.args[0] = GIC_SPI;
  41. oirq.args[1] = hwirq - 32;
  42. oirq.args[2] = flags;
  43. return irq_create_of_mapping(&oirq);
  44. }
  45. return hwirq;
  46. }
  47. TZ_RESULT KREE_ServRequestIrq(u32 op, u8 uparam[REE_SERVICE_BUFFER_SIZE])
  48. {
  49. struct ree_service_irq *param = (struct ree_service_irq *)uparam;
  50. int rret;
  51. unsigned long flags;
  52. TZ_RESULT ret = TZ_RESULT_SUCCESS;
  53. unsigned int *token;
  54. unsigned int virq;
  55. if (param->enable) {
  56. flags = 0;
  57. if (param->flags & MTIRQF_SHARED)
  58. flags |= IRQF_SHARED;
  59. if (param->flags & MTIRQF_TRIGGER_LOW)
  60. flags |= IRQF_TRIGGER_LOW;
  61. else if (param->flags & MTIRQF_TRIGGER_HIGH)
  62. flags |= IRQF_TRIGGER_HIGH;
  63. else if (param->flags & MTIRQF_TRIGGER_RISING)
  64. flags |= IRQF_TRIGGER_RISING;
  65. else if (param->flags & MTIRQF_TRIGGER_FALLING)
  66. flags |= IRQF_TRIGGER_FALLING;
  67. /* Generate a token if not already exists.
  68. * Token is used as device for Share IRQ */
  69. token = 0;
  70. if (!param->token64) {
  71. token = kmalloc(sizeof(unsigned int), GFP_KERNEL);
  72. if (!token)
  73. return TZ_RESULT_ERROR_OUT_OF_MEMORY;
  74. *token = param->irq;
  75. param->token64 = (uint64_t)(unsigned long)token;
  76. }
  77. virq = tz_hwirq_to_virq(param->irq, flags);
  78. pr_debug("%s: [irq] of_map got virq:%u, hwirq:%u(gic#)\n"
  79. , __func__, virq, param->irq);
  80. if (virq > 0)
  81. rret = request_irq(virq, KREE_IrqHandler, flags,
  82. "TEE IRQ", (void *)(unsigned long)param->token64);
  83. else
  84. rret = -EINVAL;
  85. if (rret) {
  86. kfree(token);
  87. pr_warn("request_irq return error: %d\n", rret);
  88. if (rret == -ENOMEM)
  89. ret = TZ_RESULT_ERROR_OUT_OF_MEMORY;
  90. else
  91. ret = TZ_RESULT_ERROR_BAD_PARAMETERS;
  92. }
  93. } else {
  94. if (sysirq)
  95. virq = irq_find_mapping(sysirq, param->irq - 32);
  96. else
  97. virq = param->irq;
  98. if (virq) {
  99. free_irq(virq, (void *)(unsigned long)param->token64);
  100. if (param->token64 &&
  101. *(unsigned int *)(unsigned long)param->token64 == param->irq)
  102. kfree((void *)(unsigned long)param->token64);
  103. }
  104. }
  105. return ret;
  106. }
  107. TZ_RESULT KREE_ServEnableIrq(u32 op, u8 uparam[REE_SERVICE_BUFFER_SIZE])
  108. {
  109. struct ree_service_irq *param = (struct ree_service_irq *)uparam;
  110. unsigned int virq;
  111. virq = tz_hwirq_to_virq(param->irq, 0);
  112. if (virq > 0) {
  113. if (param->enable)
  114. enable_irq(virq);
  115. else
  116. disable_irq(virq);
  117. return TZ_RESULT_SUCCESS;
  118. }
  119. return TZ_RESULT_ERROR_BAD_PARAMETERS;
  120. }
  121. /*************************************************************
  122. * TEE Service
  123. *************************************************************/
  124. static KREE_SESSION_HANDLE irq_session;
  125. void kree_irq_init(void)
  126. {
  127. TZ_RESULT ret;
  128. ret = KREE_CreateSession(TZ_TA_IRQ_UUID, &irq_session);
  129. if (ret != TZ_RESULT_SUCCESS) {
  130. pr_warn("%s: CreateSession error %d\n", __func__, ret);
  131. return;
  132. }
  133. }
  134. int kree_set_fiq(int irq, unsigned long irq_flags)
  135. {
  136. MTEEC_PARAM param[4];
  137. TZ_RESULT ret;
  138. unsigned long tz_irq_flags = 0;
  139. if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
  140. tz_irq_flags |= TZ_IRQF_EDGE_SENSITIVE;
  141. tz_irq_flags |=
  142. (irq_flags & IRQF_TRIGGER_FALLING) ? TZ_IRQF_LOW : TZ_IRQF_HIGH;
  143. } else if (irq_flags & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
  144. tz_irq_flags |= TZ_IRQF_LEVEL_SENSITIVE;
  145. tz_irq_flags |=
  146. (irq_flags & IRQF_TRIGGER_LOW) ? TZ_IRQF_LOW : TZ_IRQF_HIGH;
  147. }
  148. param[0].value.a = irq;
  149. param[1].value.a = tz_irq_flags;
  150. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_SET_FIQ,
  151. TZ_ParamTypes2(TZPT_VALUE_INPUT,
  152. TZPT_VALUE_INPUT),
  153. param);
  154. if (ret != TZ_RESULT_SUCCESS)
  155. pr_warn("%s error: %s\n", __func__, TZ_GetErrorString(ret));
  156. return ret;
  157. }
  158. static void __kree_enable_fiq(int irq, int enable)
  159. {
  160. MTEEC_PARAM param[4];
  161. TZ_RESULT ret;
  162. param[0].value.a = irq;
  163. param[1].value.a = enable;
  164. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_ENABLE_FIQ,
  165. TZ_ParamTypes2(TZPT_VALUE_INPUT,
  166. TZPT_VALUE_INPUT),
  167. param);
  168. if (ret != TZ_RESULT_SUCCESS)
  169. pr_warn("%s error: %s\n", __func__, TZ_GetErrorString(ret));
  170. }
  171. void kree_enable_fiq(int irq)
  172. {
  173. __kree_enable_fiq(irq, 1);
  174. }
  175. void kree_disable_fiq(int irq)
  176. {
  177. __kree_enable_fiq(irq, 0);
  178. }
  179. void kree_query_fiq(int irq, int *enable, int *pending)
  180. {
  181. MTEEC_PARAM param[4];
  182. TZ_RESULT ret;
  183. param[0].value.a = irq;
  184. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_QUERY_FIQ,
  185. TZ_ParamTypes2(TZPT_VALUE_INPUT,
  186. TZPT_VALUE_OUTPUT),
  187. param);
  188. if (ret != TZ_RESULT_SUCCESS) {
  189. pr_warn("%s error: %s\n", __func__, TZ_GetErrorString(ret));
  190. param[1].value.a = 0;
  191. }
  192. *enable = param[1].value.a & 1;
  193. *pending = (param[1].value.a & 2) != 0;
  194. }
  195. unsigned int kree_fiq_get_intack(void)
  196. {
  197. MTEEC_PARAM param[4];
  198. TZ_RESULT ret;
  199. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_GET_INTACK,
  200. TZ_ParamTypes1(TZPT_VALUE_OUTPUT), param);
  201. if (ret == TZ_RESULT_SUCCESS)
  202. return param[0].value.a;
  203. return 0xffff;
  204. }
  205. void kree_fiq_eoi(unsigned int iar)
  206. {
  207. MTEEC_PARAM param[4];
  208. param[0].value.a = iar;
  209. KREE_TeeServiceCall(irq_session, TZCMD_IRQ_EOI,
  210. TZ_ParamTypes1(TZPT_VALUE_INPUT), param);
  211. }
  212. int kree_raise_softfiq(unsigned int mask, unsigned int irq)
  213. {
  214. MTEEC_PARAM param[4];
  215. TZ_RESULT ret;
  216. param[0].value.a = mask;
  217. param[1].value.a = irq;
  218. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_TRIGGER_SGI,
  219. TZ_ParamTypes2(TZPT_VALUE_INPUT,
  220. TZPT_VALUE_INPUT),
  221. param);
  222. return ret == TZ_RESULT_SUCCESS;
  223. }
  224. void kree_irq_mask_all(unsigned int *pmask, unsigned int size)
  225. {
  226. MTEEC_PARAM param[4];
  227. TZ_RESULT ret;
  228. param[0].mem.buffer = pmask;
  229. param[0].mem.size = size;
  230. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_MASK_ALL,
  231. TZ_ParamTypes1(TZPT_MEM_OUTPUT), param);
  232. if (ret != TZ_RESULT_SUCCESS)
  233. pr_warn("%s error: %s\n", __func__, TZ_GetErrorString(ret));
  234. }
  235. void kree_irq_mask_restore(unsigned int *pmask, unsigned int size)
  236. {
  237. MTEEC_PARAM param[4];
  238. TZ_RESULT ret;
  239. param[0].mem.buffer = pmask;
  240. param[0].mem.size = size;
  241. ret = KREE_TeeServiceCall(irq_session, TZCMD_IRQ_MASK_RESTORE,
  242. TZ_ParamTypes1(TZPT_MEM_INPUT), param);
  243. if (ret != TZ_RESULT_SUCCESS)
  244. pr_warn("%s error: %s\n", __func__, TZ_GetErrorString(ret));
  245. }
  246. void kree_set_sysirq_node(struct device_node *pnode)
  247. {
  248. if (pnode) {
  249. sysirq_node = pnode;
  250. sysirq = irq_find_host(sysirq_node);
  251. }
  252. }