drv_sys.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-11-11 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rthw.h>
  13. #include <rtthread.h>
  14. #include "NuMicro.h"
  15. #include "drv_sys.h"
  16. #define SYS_MIN_INT_SOURCE 1
  17. #define SYS_MAX_INT_SOURCE 63
  18. #define SYS_NUM_OF_AICREG 16
  19. #define INT_IRQ 0x00
  20. #define INT_FIQ 0x01
  21. extern rt_uint32_t rt_interrupt_nest;
  22. rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
  23. rt_uint32_t rt_thread_switch_interrupt_flag;
  24. struct rt_irq_desc irq_desc[SYS_MAX_INT_SOURCE + 1];
  25. void rt_hw_interrupt_dummy_handler(int vector, void *param)
  26. {
  27. rt_kprintf("Unhandled interrupt %d occurred!!!\n", vector);
  28. RT_ASSERT(0);
  29. }
  30. rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq)
  31. {
  32. rt_uint32_t active = 0;
  33. #if 0
  34. rt_uint32_t volatile _mIPER, _mISNR;
  35. _mIPER = (inpw(REG_AIC_IPER) >> 2) & 0x3f;
  36. _mISNR = inpw(REG_AIC_ISNR);
  37. if ((_mISNR != 0) && (_mIPER == _mISNR))
  38. active = _mISNR;
  39. #else
  40. if (fiq_irq != INT_FIQ)
  41. {
  42. active = inpw(REG_AIC_IRQNUM);
  43. }
  44. else
  45. active = inpw(REG_AIC_FIQNUM);
  46. #endif
  47. return active;
  48. }
  49. void rt_hw_interrupt_set_priority(int vector, int IntTypeLevel)
  50. {
  51. rt_uint32_t _mRegAddr;
  52. rt_uint32_t shift;
  53. if ((vector > SYS_MAX_INT_SOURCE) || (vector < SYS_MIN_INT_SOURCE))
  54. return;
  55. _mRegAddr = REG_AIC_SRCCTL0 + ((vector / 4) * 4);
  56. shift = (vector % 4) * 8;
  57. IntTypeLevel &= 0x7;
  58. outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0x07 << shift)) | (IntTypeLevel << shift));
  59. }
  60. void rt_hw_interrupt_ack(rt_uint32_t fiq_irq, rt_uint32_t id)
  61. {
  62. if (fiq_irq != INT_FIQ)
  63. outpw(REG_AIC_EOIS, 1);
  64. else
  65. outpw(REG_AIC_EOFS, 1);
  66. }
  67. void rt_interrupt_dispatch(rt_uint32_t fiq_irq)
  68. {
  69. rt_isr_handler_t isr_func;
  70. rt_uint32_t irq;
  71. void *param;
  72. /* get irq number */
  73. irq = rt_hw_interrupt_get_active(fiq_irq);
  74. /* get interrupt service routine */
  75. isr_func = irq_desc[irq].handler;
  76. param = irq_desc[irq].param;
  77. /* turn to interrupt service routine */
  78. isr_func(irq, param);
  79. rt_hw_interrupt_ack(fiq_irq, irq);
  80. #ifdef RT_USING_INTERRUPT_INFO
  81. irq_desc[irq].counter ++;
  82. #endif
  83. }
  84. void rt_hw_interrupt_init(void)
  85. {
  86. int i;
  87. outpw(REG_AIC_INTDIS0, 0xFFFFFFFF); // disable all interrupt channel
  88. outpw(REG_AIC_INTDIS1, 0xFFFFFFFF); // disable all interrupt channel
  89. outpw(REG_AIC_EOIS, 1); // resetand restart AIC's IRQ processing
  90. outpw(REG_AIC_EOFS, 1); // resetand restart AIC's IRQ processing
  91. /* init interrupt nest, and context in thread sp */
  92. rt_interrupt_nest = 0;
  93. rt_interrupt_from_thread = 0;
  94. rt_interrupt_to_thread = 0;
  95. rt_thread_switch_interrupt_flag = 0;
  96. for (i = 1; i <= SYS_MAX_INT_SOURCE; i++)
  97. {
  98. rt_hw_interrupt_install(i, rt_hw_interrupt_dummy_handler, RT_NULL, (char *)"dummy");
  99. rt_hw_interrupt_mask(i);
  100. }
  101. }
  102. rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name)
  103. {
  104. rt_isr_handler_t old_handler = RT_NULL;
  105. if (vector > SYS_MAX_INT_SOURCE)
  106. return RT_NULL;
  107. /* Set default priority IRQ_LEVEL_7 */
  108. rt_hw_interrupt_set_priority(vector, IRQ_LEVEL_7);
  109. old_handler = irq_desc[vector].handler;
  110. if (handler != RT_NULL)
  111. {
  112. irq_desc[vector].handler = (rt_isr_handler_t)handler;
  113. irq_desc[vector].param = param;
  114. #ifdef RT_USING_INTERRUPT_INFO
  115. rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
  116. irq_desc[vector].counter = 0;
  117. #endif
  118. }
  119. return old_handler;
  120. }
  121. /* Disable interrupt */
  122. void rt_hw_interrupt_mask(int vector)
  123. {
  124. sysDisableInterrupt((IRQn_Type)vector);
  125. }
  126. void rt_hw_interrupt_umask(int vector)
  127. {
  128. sysEnableInterrupt((IRQn_Type)vector);
  129. }
  130. /* TYPE
  131. * #define LOW_LEVEL_SENSITIVE 0x00
  132. * #define HIGH_LEVEL_SENSITIVE 0x40
  133. * #define NEGATIVE_EDGE_TRIGGER 0x80
  134. * #define POSITIVE_EDGE_TRIGGER 0xC0
  135. */
  136. void rt_hw_interrupt_set_type(int vector, int type)
  137. {
  138. rt_uint32_t _mRegAddr;
  139. rt_uint32_t shift;
  140. if ((vector > SYS_MAX_INT_SOURCE) || (vector < SYS_MIN_INT_SOURCE))
  141. return ;
  142. _mRegAddr = REG_AIC_SRCCTL0 + ((vector / 4) * 4);
  143. shift = (vector % 4) * 8;
  144. type &= 0xC0;
  145. outpw(_mRegAddr, (inpw(_mRegAddr) & ~(0xC0 << shift)) | (type << shift));
  146. }
  147. void rt_low_level_init(void)
  148. {
  149. }
  150. void nu_clock_base_init(void)
  151. {
  152. nu_sys_ipclk_enable(CPUCKEN);
  153. nu_sys_ipclk_enable(HCLKCKEN);
  154. nu_sys_ipclk_enable(HCLK1CKEN);
  155. nu_sys_ipclk_enable(HCLK3CKEN);
  156. nu_sys_ipclk_enable(HCLK4CKEN);
  157. nu_sys_ipclk_enable(PCLK0CKEN);
  158. nu_sys_ipclk_enable(PCLK1CKEN);
  159. nu_sys_ipclk_enable(SRAMCKEN);
  160. nu_sys_ipclk_enable(SDICCKEN);
  161. nu_sys_ipclk_enable(PCLK2CKEN);
  162. nu_sys_ipclk_enable(PCLKEN0_Reserved_3);
  163. }
  164. void machine_reset(void)
  165. {
  166. rt_kprintf("machine_reset...\n");
  167. rt_hw_interrupt_disable();
  168. /* Unlock */
  169. SYS_UnlockReg();
  170. nu_sys_ip_reset(CHIPRST);
  171. while (1);
  172. }
  173. void machine_shutdown(void)
  174. {
  175. rt_kprintf("machine_shutdown...\n");
  176. rt_hw_interrupt_disable();
  177. /* Unlock */
  178. SYS_UnlockReg();
  179. while (1);
  180. }
  181. void nu_sys_ip_reset(E_SYS_IPRST eIPRstIdx)
  182. {
  183. uint32_t volatile u32IPRSTRegAddr;
  184. uint32_t u32IPRSTRegBit;
  185. rt_uint32_t level;
  186. if (eIPRstIdx >= SYS_IPRST_CNT)
  187. return;
  188. u32IPRSTRegAddr = REG_SYS_AHBIPRST + (4ul * (eIPRstIdx / 32));
  189. u32IPRSTRegBit = eIPRstIdx % 32;
  190. /* Enter critical section */
  191. level = rt_hw_interrupt_disable();
  192. /* Unlock write-protect */
  193. SYS_UnlockReg();
  194. /* Enable IP reset */
  195. outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) | (1 << u32IPRSTRegBit));
  196. /* Disable IP reset */
  197. outpw(u32IPRSTRegAddr, inpw(u32IPRSTRegAddr) & ~(1 << u32IPRSTRegBit));
  198. /* Wait it done. */
  199. while (inpw(u32IPRSTRegAddr) & (1 << u32IPRSTRegBit)) {}
  200. /* Lock write protect */
  201. SYS_LockReg();
  202. /* Leave critical section */
  203. rt_hw_interrupt_enable(level);
  204. }
  205. static void _nu_sys_ipclk(E_SYS_IPCLK eIPClkIdx, uint32_t bEnable)
  206. {
  207. uint32_t volatile u32IPCLKRegAddr;
  208. uint32_t u32IPCLKRegBit;
  209. rt_uint32_t level;
  210. if (eIPClkIdx >= SYS_IPCLK_CNT)
  211. return;
  212. u32IPCLKRegAddr = REG_CLK_HCLKEN + (4ul * (eIPClkIdx / 32));
  213. u32IPCLKRegBit = eIPClkIdx % 32;
  214. /* Enter critical section */
  215. level = rt_hw_interrupt_disable();
  216. SYS_UnlockReg();
  217. if (bEnable)
  218. {
  219. /* Enable IP CLK */
  220. outpw(u32IPCLKRegAddr, inpw(u32IPCLKRegAddr) | (1 << u32IPCLKRegBit));
  221. }
  222. else
  223. {
  224. /* Disable IP CLK */
  225. outpw(u32IPCLKRegAddr, inpw(u32IPCLKRegAddr) & ~(1 << u32IPCLKRegBit));
  226. }
  227. SYS_LockReg();
  228. /* Leave critical section */
  229. rt_hw_interrupt_enable(level);
  230. }
  231. void nu_sys_ipclk_enable(E_SYS_IPCLK eIPClkIdx)
  232. {
  233. _nu_sys_ipclk(eIPClkIdx, 1);
  234. }
  235. void nu_sys_ipclk_disable(E_SYS_IPCLK eIPClkIdx)
  236. {
  237. _nu_sys_ipclk(eIPClkIdx, 0);
  238. }
  239. E_SYS_USB0_ID nu_sys_usb0_role(void)
  240. {
  241. /* Check Role on USB0 dual-role port. */
  242. /*
  243. [17] USB0_IDS
  244. USB0_ID Status
  245. 0 = USB port 0 used as a USB device port.
  246. 1 = USB port 0 used as a USB host port.
  247. */
  248. return ((inpw(REG_SYS_MISCISR) & (1 << 17)) > 0) ? USB0_ID_HOST : USB0_ID_DEVICE;
  249. }
  250. #ifdef RT_USING_FINSH
  251. #include <finsh.h>
  252. #ifdef FINSH_USING_MSH
  253. int cmd_reset(int argc, char **argv)
  254. {
  255. rt_hw_cpu_reset();
  256. return 0;
  257. }
  258. MSH_CMD_EXPORT_ALIAS(cmd_reset, reset, restart the system);
  259. int cmd_shutdown(int argc, char **argv)
  260. {
  261. rt_hw_cpu_shutdown();
  262. return 0;
  263. }
  264. MSH_CMD_EXPORT_ALIAS(cmd_shutdown, shutdown, shutdown the system);
  265. int nu_clocks(int argc, char **argv)
  266. {
  267. rt_kprintf("SYS_UPLL = %d MHz\n", sysGetClock(SYS_UPLL));
  268. rt_kprintf("SYS_APLL = %d MHz\n", sysGetClock(SYS_APLL));
  269. rt_kprintf("SYS_SYSTEM = %d MHz\n", sysGetClock(SYS_SYSTEM));
  270. rt_kprintf("SYS_HCLK = %d MHz\n", sysGetClock(SYS_HCLK));
  271. rt_kprintf("SYS_PCLK01 = %d MHz\n", sysGetClock(SYS_PCLK01));
  272. rt_kprintf("SYS_PCLK2 = %d MHz\n", sysGetClock(SYS_PCLK2));
  273. rt_kprintf("SYS_CPU = %d MHz\n", sysGetClock(SYS_CPU));
  274. rt_kprintf("CLK_HCLKEN = %08X\n", inpw(REG_CLK_HCLKEN));
  275. rt_kprintf("CLK_PCLKEN0 = %08X\n", inpw(REG_CLK_PCLKEN0));
  276. rt_kprintf("CLK_PCLKEN1 = %08X\n", inpw(REG_CLK_PCLKEN1));
  277. rt_kprintf("AIC_INTMSK0 = %08X\n", inpw(REG_AIC_INTMSK0));
  278. rt_kprintf("AIC_INTMSK1 = %08X\n", inpw(REG_AIC_INTMSK1));
  279. rt_kprintf("AIC_INTEN0 = %08X\n", inpw(REG_AIC_INTEN0));
  280. rt_kprintf("AIC_INTEN1 = %08X\n", inpw(REG_AIC_INTEN1));
  281. rt_kprintf("AIC_INTDIS0 = %08X\n", inpw(REG_AIC_INTDIS0));
  282. rt_kprintf("AIC_INTDIS1 = %08X\n", inpw(REG_AIC_INTDIS1));
  283. return 0;
  284. }
  285. MSH_CMD_EXPORT(nu_clocks, get all system clocks);
  286. #endif
  287. #ifdef RT_USING_INTERRUPT_INFO
  288. int list_interrupt(int argc, char **argv)
  289. {
  290. int i;
  291. for (i = 1; i <= SYS_MAX_INT_SOURCE; i++)
  292. {
  293. if (irq_desc[i].handler != rt_hw_interrupt_dummy_handler)
  294. {
  295. rt_kprintf("[%d] %s: %d\n", i, irq_desc[i].name, irq_desc[i].counter);
  296. }
  297. }
  298. return 0;
  299. }
  300. MSH_CMD_EXPORT(list_interrupt, list registered interrupts);
  301. #endif
  302. #endif