systracker_platform.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include <linux/module.h>
  2. #include <linux/platform_device.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/sched.h>
  5. #include <asm/system_misc.h>
  6. #include <asm/traps.h>
  7. #include <asm/signal.h>
  8. #include <mt-plat/sync_write.h>
  9. #include <mt-plat/mt_io.h>
  10. #include <mtk_ram_console.h>
  11. #include "../systracker.h"
  12. #ifdef SYSTRACKER_TEST_SUIT
  13. void __iomem *p1;
  14. void __iomem *mm_area1;
  15. #endif
  16. #ifdef CONFIG_ARM64
  17. static int read_timeout_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  18. {
  19. int i = 0;
  20. #ifdef SYSTRACKER_TEST_SUIT
  21. systracker_test_cleanup();
  22. #endif
  23. pr_debug("%s:%d: read timeout\n", __func__, __LINE__);
  24. aee_dump_backtrace(regs, NULL);
  25. if (readl(IOMEM(BUS_DBG_CON)) & BUS_DBG_CON_IRQ_AR_STA) {
  26. for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) {
  27. pr_err("AR_TRACKER Timeout Entry[%d]: ReadAddr:0x%x, Length:0x%x, TransactionID:0x%x!\n",
  28. i, readl(IOMEM(BUS_DBG_AR_TRACK_L(i))),
  29. readl(IOMEM(BUS_DBG_AR_TRACK_H(i))),
  30. readl(IOMEM(BUS_DBG_AR_TRANS_TID(i))));
  31. }
  32. }
  33. /* return -1 to indicate kernel go on its flow */
  34. return -1;
  35. }
  36. static void write_timeout_handler(struct pt_regs *regs, void *priv)
  37. {
  38. int i = 0;
  39. #ifdef SYSTRACKER_TEST_SUIT
  40. systracker_test_cleanup();
  41. #endif
  42. pr_debug("%s:%d: write timeout\n", __func__, __LINE__);
  43. aee_dump_backtrace(regs, NULL);
  44. if (readl(IOMEM(BUS_DBG_CON)) & BUS_DBG_CON_IRQ_AW_STA) {
  45. for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) {
  46. pr_err("AW_TRACKER Timeout Entry[%d]: WriteAddr:0x%x, Length:0x%x, TransactionID:0x%x!\n",
  47. i, readl(IOMEM(BUS_DBG_AW_TRACK_L(i))),
  48. readl(IOMEM(BUS_DBG_AW_TRACK_H(i))),
  49. readl(IOMEM(BUS_DBG_AW_TRANS_TID(i))));
  50. }
  51. }
  52. }
  53. static int systracker_platform_hook_fault(void)
  54. {
  55. int ret = 0;
  56. /* We use ARM64's synchroneous external abort for read timeout */
  57. hook_fault_code(0x10, read_timeout_handler, SIGTRAP, 0, "Systracker debug exception");
  58. /* for 64bit, we should register async abort handler */
  59. ret = register_async_abort_handler(write_timeout_handler, NULL);
  60. if (ret) {
  61. pr_warn("%s:%d: register_async_abort_handler failed\n", __func__, __LINE__);
  62. return -1;
  63. }
  64. return 0;
  65. }
  66. #else
  67. int systracker_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
  68. {
  69. int i;
  70. #ifdef SYSTRACKER_TEST_SUIT
  71. writel(readl(p1) & ~(0x1 << 6), p1);
  72. #endif
  73. aee_dump_backtrace(regs, NULL);
  74. if (readl(IOMEM(BUS_DBG_CON)) & BUS_DBG_CON_IRQ_AR_STA) {
  75. for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) {
  76. pr_alert("AR_TRACKER Timeout Entry[%d]: ReadAddr:0x%x, Length:0x%x, TransactionID:0x%x!\n",
  77. i, readl(IOMEM(BUS_DBG_AR_TRACK_L(i))),
  78. readl(IOMEM(BUS_DBG_AR_TRACK_H(i))),
  79. readl(IOMEM(BUS_DBG_AR_TRANS_TID(i))));
  80. }
  81. }
  82. if (readl(IOMEM(BUS_DBG_CON)) & BUS_DBG_CON_IRQ_AW_STA) {
  83. for (i = 0; i < BUS_DBG_NUM_TRACKER; i++) {
  84. pr_alert("AW_TRACKER Timeout Entry[%d]: WriteAddr:0x%x, Length:0x%x, TransactionID:0x%x!\n",
  85. i, readl(IOMEM(BUS_DBG_AW_TRACK_L(i))),
  86. readl(IOMEM(BUS_DBG_AW_TRACK_H(i))),
  87. readl(IOMEM(BUS_DBG_AW_TRANS_TID(i))));
  88. }
  89. }
  90. return -1;
  91. }
  92. /* ARM32 version */
  93. static int systracker_platform_hook_fault(void)
  94. {
  95. #ifdef CONFIG_ARM_LPAE
  96. hook_fault_code(0x10, systracker_handler, SIGTRAP, 0, "Systracker debug exception");
  97. hook_fault_code(0x11, systracker_handler, SIGTRAP, 0, "Systracker debug exception");
  98. #else
  99. hook_fault_code(0x8, systracker_handler, SIGTRAP, 0, "Systracker debug exception");
  100. hook_fault_code(0x16, systracker_handler, SIGTRAP, 0, "Systracker debug exception");
  101. #endif
  102. return 0;
  103. }
  104. #endif
  105. #ifdef SYSTRACKER_TEST_SUIT
  106. void __iomem *p1;
  107. void __iomem *mm_area1;
  108. static int systracker_platform_test_init(void)
  109. {
  110. p1 = ioremap(0x10000220, 0x4);
  111. /* use mmsys reg base for our test */
  112. mm_area1 = ioremap(0x14000000, 0x4);
  113. return 0;
  114. }
  115. static void systracker_platform_test_cleanup(void)
  116. {
  117. writel(readl(p1) & ~(0x1 << 6), p1);
  118. }
  119. static void systracker_platform_wp_test(void)
  120. {
  121. void __iomem *ptr;
  122. /* use eint reg base as our watchpoint */
  123. ptr = ioremap(0x1000b000, 0x4);
  124. pr_debug("%s:%d: we got p = 0x%p\n", __func__, __LINE__, ptr);
  125. systracker_set_watchpoint_addr(0x1000b000);
  126. systracker_watchpoint_enable();
  127. /* touch it */
  128. writel(0, ptr);
  129. pr_debug("after we touched watchpoint\n");
  130. iounmap(ptr);
  131. }
  132. static void systracker_platform_read_timeout_test(void)
  133. {
  134. /* FIXME: testing
  135. track_config.enable_slave_err = 0;
  136. systracker_enable();
  137. */
  138. writel(readl(p1) | (0x1 << 6), p1);
  139. readl(mm_area1);
  140. writel(readl(p1) & ~(0x1 << 6), p1);
  141. }
  142. static void systracker_platform_write_timeout_test(void)
  143. {
  144. writel(readl(p1) | (0x1 << 6), p1);
  145. writel(0x0, mm_area1);
  146. writel(readl(p1) & ~(0x1 << 6), p1);
  147. }
  148. static void systracker_platform_withrecord_test(void)
  149. {
  150. writel(readl(IOMEM(BUS_DBG_CON)) | BUS_DBG_CON_HALT_ON_EN, IOMEM(BUS_DBG_CON));
  151. writel(readl(p1) | (0x1 << 6), p1);
  152. readl(mm_area1);
  153. #if 0
  154. /* FIXME: related function not ready on FPGA */
  155. wdt_arch_reset(1);
  156. #endif
  157. }
  158. static void systracker_platform_notimeout_test(void)
  159. {
  160. writel(readl(p1) | (0x1 << 6), p1);
  161. /* disable timeout */
  162. writel(readl(IOMEM(BUS_DBG_CON)) & ~(BUS_DBG_CON_TIMEOUT_EN), IOMEM(BUS_DBG_CON));
  163. /* read it, should cause bus hang */
  164. readl(mm_area1);
  165. /* never come back */
  166. pr_alert("failed??\n");
  167. }
  168. #endif
  169. /* end of SYSTRACKER_TEST_SUIT */
  170. /*
  171. * mt_systracker_init: initialize driver.
  172. * Always return 0.
  173. */
  174. static int __init mt_systracker_init(void)
  175. {
  176. struct mt_systracker_driver *systracker_drv;
  177. systracker_drv = get_mt_systracker_drv();
  178. systracker_drv->systracker_hook_fault = systracker_platform_hook_fault;
  179. #ifdef SYSTRACKER_TEST_SUIT
  180. systracker_drv->systracker_test_init = systracker_platform_test_init;
  181. systracker_drv->systracker_test_cleanup = systracker_platform_test_cleanup;
  182. systracker_drv->systracker_wp_test = systracker_platform_wp_test;
  183. systracker_drv->systracker_read_timeout_test = systracker_platform_read_timeout_test;
  184. systracker_drv->systracker_write_timeout_test = systracker_platform_write_timeout_test;
  185. systracker_drv->systracker_withrecord_test = systracker_platform_withrecord_test;
  186. systracker_drv->systracker_notimeout_test = systracker_platform_notimeout_test;
  187. #endif
  188. return 0;
  189. }
  190. arch_initcall(mt_systracker_init);
  191. MODULE_DESCRIPTION("system tracker driver v2.0");