interrupt.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2013-07-06 Bernard first version
  9. * 2018-11-22 Jesven add smp support
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #include "interrupt.h"
  14. #include "gic.h"
  15. #include "gicv3.h"
  16. #ifdef RT_USING_SMART
  17. #include "ioremap.h"
  18. #else
  19. #define rt_ioremap(x, ...) (x)
  20. #endif
  21. /* exception and interrupt handler table */
  22. struct rt_irq_desc isr_table[MAX_HANDLERS];
  23. #ifndef RT_USING_SMP
  24. /* Those variables will be accessed in ISR, so we need to share them. */
  25. rt_ubase_t rt_interrupt_from_thread = 0;
  26. rt_ubase_t rt_interrupt_to_thread = 0;
  27. rt_ubase_t rt_thread_switch_interrupt_flag = 0;
  28. #endif
  29. #ifndef RT_CPUS_NR
  30. #define RT_CPUS_NR 1
  31. #endif
  32. const unsigned int VECTOR_BASE = 0x00;
  33. extern void rt_cpu_vector_set_base(void *addr);
  34. extern void *system_vectors;
  35. #ifdef RT_USING_SMP
  36. #define rt_interrupt_nest rt_cpu_self()->irq_nest
  37. #else
  38. extern volatile rt_uint8_t rt_interrupt_nest;
  39. #endif
  40. #ifdef SOC_BCM283x
  41. static void default_isr_handler(int vector, void *param)
  42. {
  43. #ifdef RT_USING_SMP
  44. rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector);
  45. #else
  46. rt_kprintf("unhandled irq: %d\n",vector);
  47. #endif
  48. }
  49. #endif
  50. void rt_hw_vector_init(void)
  51. {
  52. rt_cpu_vector_set_base(&system_vectors);
  53. }
  54. /**
  55. * This function will initialize hardware interrupt
  56. */
  57. void rt_hw_interrupt_init(void)
  58. {
  59. #ifdef SOC_BCM283x
  60. rt_uint32_t index;
  61. /* initialize vector table */
  62. rt_hw_vector_init();
  63. /* initialize exceptions table */
  64. rt_memset(isr_table, 0x00, sizeof(isr_table));
  65. /* mask all of interrupts */
  66. IRQ_DISABLE_BASIC = 0x000000ff;
  67. IRQ_DISABLE1 = 0xffffffff;
  68. IRQ_DISABLE2 = 0xffffffff;
  69. for (index = 0; index < MAX_HANDLERS; index ++)
  70. {
  71. isr_table[index].handler = default_isr_handler;
  72. isr_table[index].param = RT_NULL;
  73. #ifdef RT_USING_INTERRUPT_INFO
  74. rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX);
  75. isr_table[index].counter = 0;
  76. #endif
  77. }
  78. /* init interrupt nest, and context in thread sp */
  79. rt_interrupt_nest = 0;
  80. rt_interrupt_from_thread = 0;
  81. rt_interrupt_to_thread = 0;
  82. rt_thread_switch_interrupt_flag = 0;
  83. #else
  84. rt_uint64_t gic_cpu_base;
  85. rt_uint64_t gic_dist_base;
  86. #ifdef BSP_USING_GICV3
  87. rt_uint64_t gic_rdist_base;
  88. #endif
  89. rt_uint64_t gic_irq_start;
  90. /* initialize vector table */
  91. rt_hw_vector_init();
  92. /* initialize exceptions table */
  93. rt_memset(isr_table, 0x00, sizeof(isr_table));
  94. /* initialize ARM GIC */
  95. #ifdef RT_USING_SMART
  96. gic_dist_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_dist_base(), 0x2000);
  97. gic_cpu_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_cpu_base(), 0x1000);
  98. #ifdef BSP_USING_GICV3
  99. gic_rdist_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_redist_base(),
  100. RT_CPUS_NR * (2 << 16));
  101. #endif
  102. #else
  103. gic_dist_base = platform_get_gic_dist_base();
  104. gic_cpu_base = platform_get_gic_cpu_base();
  105. #ifdef BSP_USING_GICV3
  106. gic_rdist_base = platform_get_gic_redist_base();
  107. #endif
  108. #endif
  109. gic_irq_start = GIC_IRQ_START;
  110. arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
  111. arm_gic_cpu_init(0, gic_cpu_base);
  112. #ifdef BSP_USING_GICV3
  113. arm_gic_redist_init(0, gic_rdist_base);
  114. #endif
  115. #endif
  116. }
  117. /**
  118. * This function will mask a interrupt.
  119. * @param vector the interrupt number
  120. */
  121. void rt_hw_interrupt_mask(int vector)
  122. {
  123. #ifdef SOC_BCM283x
  124. if (vector < 32)
  125. {
  126. IRQ_DISABLE1 = (1 << vector);
  127. }
  128. else if (vector < 64)
  129. {
  130. vector = vector % 32;
  131. IRQ_DISABLE2 = (1 << vector);
  132. }
  133. else
  134. {
  135. vector = vector - 64;
  136. IRQ_DISABLE_BASIC = (1 << vector);
  137. }
  138. #else
  139. arm_gic_mask(0, vector);
  140. #endif
  141. }
  142. /**
  143. * This function will un-mask a interrupt.
  144. * @param vector the interrupt number
  145. */
  146. void rt_hw_interrupt_umask(int vector)
  147. {
  148. #ifdef SOC_BCM283x
  149. if (vector < 32)
  150. {
  151. IRQ_ENABLE1 = (1 << vector);
  152. }
  153. else if (vector < 64)
  154. {
  155. vector = vector % 32;
  156. IRQ_ENABLE2 = (1 << vector);
  157. }
  158. else
  159. {
  160. vector = vector - 64;
  161. IRQ_ENABLE_BASIC = (1 << vector);
  162. }
  163. #else
  164. arm_gic_umask(0, vector);
  165. #endif
  166. }
  167. /**
  168. * This function returns the active interrupt number.
  169. * @param none
  170. */
  171. int rt_hw_interrupt_get_irq(void)
  172. {
  173. #ifndef SOC_BCM283x
  174. return arm_gic_get_active_irq(0);
  175. #else
  176. return 0;
  177. #endif
  178. }
  179. /**
  180. * This function acknowledges the interrupt.
  181. * @param vector the interrupt number
  182. */
  183. void rt_hw_interrupt_ack(int vector)
  184. {
  185. #ifndef SOC_BCM283x
  186. arm_gic_ack(0, vector);
  187. #endif
  188. }
  189. #ifndef SOC_BCM283x
  190. /**
  191. * This function set interrupt CPU targets.
  192. * @param vector: the interrupt number
  193. * cpu_mask: target cpus mask, one bit for one core
  194. */
  195. void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask)
  196. {
  197. arm_gic_set_cpu(0, vector, cpu_mask);
  198. }
  199. /**
  200. * This function get interrupt CPU targets.
  201. * @param vector: the interrupt number
  202. * @return target cpus mask, one bit for one core
  203. */
  204. unsigned int rt_hw_interrupt_get_target_cpus(int vector)
  205. {
  206. return arm_gic_get_target_cpu(0, vector);
  207. }
  208. /**
  209. * This function set interrupt triger mode.
  210. * @param vector: the interrupt number
  211. * mode: interrupt triger mode; 0: level triger, 1: edge triger
  212. */
  213. void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode)
  214. {
  215. arm_gic_set_configuration(0, vector, mode & IRQ_MODE_MASK);
  216. }
  217. /**
  218. * This function get interrupt triger mode.
  219. * @param vector: the interrupt number
  220. * @return interrupt triger mode; 0: level triger, 1: edge triger
  221. */
  222. unsigned int rt_hw_interrupt_get_triger_mode(int vector)
  223. {
  224. return arm_gic_get_configuration(0, vector);
  225. }
  226. /**
  227. * This function set interrupt pending flag.
  228. * @param vector: the interrupt number
  229. */
  230. void rt_hw_interrupt_set_pending(int vector)
  231. {
  232. arm_gic_set_pending_irq(0, vector);
  233. }
  234. /**
  235. * This function get interrupt pending flag.
  236. * @param vector: the interrupt number
  237. * @return interrupt pending flag, 0: not pending; 1: pending
  238. */
  239. unsigned int rt_hw_interrupt_get_pending(int vector)
  240. {
  241. return arm_gic_get_pending_irq(0, vector);
  242. }
  243. /**
  244. * This function clear interrupt pending flag.
  245. * @param vector: the interrupt number
  246. */
  247. void rt_hw_interrupt_clear_pending(int vector)
  248. {
  249. arm_gic_clear_pending_irq(0, vector);
  250. }
  251. /**
  252. * This function set interrupt priority value.
  253. * @param vector: the interrupt number
  254. * priority: the priority of interrupt to set
  255. */
  256. void rt_hw_interrupt_set_priority(int vector, unsigned int priority)
  257. {
  258. arm_gic_set_priority(0, vector, priority);
  259. }
  260. /**
  261. * This function get interrupt priority.
  262. * @param vector: the interrupt number
  263. * @return interrupt priority value
  264. */
  265. unsigned int rt_hw_interrupt_get_priority(int vector)
  266. {
  267. return arm_gic_get_priority(0, vector);
  268. }
  269. /**
  270. * This function set priority masking threshold.
  271. * @param priority: priority masking threshold
  272. */
  273. void rt_hw_interrupt_set_priority_mask(unsigned int priority)
  274. {
  275. arm_gic_set_interface_prior_mask(0, priority);
  276. }
  277. /**
  278. * This function get priority masking threshold.
  279. * @param none
  280. * @return priority masking threshold
  281. */
  282. unsigned int rt_hw_interrupt_get_priority_mask(void)
  283. {
  284. return arm_gic_get_interface_prior_mask(0);
  285. }
  286. /**
  287. * This function set priority grouping field split point.
  288. * @param bits: priority grouping field split point
  289. * @return 0: success; -1: failed
  290. */
  291. int rt_hw_interrupt_set_prior_group_bits(unsigned int bits)
  292. {
  293. int status;
  294. if (bits < 8)
  295. {
  296. arm_gic_set_binary_point(0, (7 - bits));
  297. status = 0;
  298. }
  299. else
  300. {
  301. status = -1;
  302. }
  303. return (status);
  304. }
  305. /**
  306. * This function get priority grouping field split point.
  307. * @param none
  308. * @return priority grouping field split point
  309. */
  310. unsigned int rt_hw_interrupt_get_prior_group_bits(void)
  311. {
  312. unsigned int bp;
  313. bp = arm_gic_get_binary_point(0) & 0x07;
  314. return (7 - bp);
  315. }
  316. #endif /* SOC_BCM283x */
  317. /**
  318. * This function will install a interrupt service routine to a interrupt.
  319. * @param vector the interrupt number
  320. * @param new_handler the interrupt service routine to be installed
  321. * @param old_handler the old interrupt service routine
  322. */
  323. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
  324. void *param, const char *name)
  325. {
  326. rt_isr_handler_t old_handler = RT_NULL;
  327. if (vector < MAX_HANDLERS)
  328. {
  329. old_handler = isr_table[vector].handler;
  330. if (handler != RT_NULL)
  331. {
  332. #ifdef RT_USING_INTERRUPT_INFO
  333. rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
  334. #endif /* RT_USING_INTERRUPT_INFO */
  335. isr_table[vector].handler = handler;
  336. isr_table[vector].param = param;
  337. }
  338. }
  339. return old_handler;
  340. }
  341. #ifdef RT_USING_SMP
  342. void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
  343. {
  344. #ifdef BSP_USING_GICV2
  345. arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
  346. #elif defined(BSP_USING_GICV3)
  347. arm_gic_send_affinity_sgi(0, ipi_vector, (unsigned int *)&cpu_mask, GICV3_ROUTED_TO_SPEC);
  348. #endif
  349. }
  350. void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
  351. {
  352. /* note: ipi_vector maybe different with irq_vector */
  353. rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER");
  354. }
  355. #endif