smi_debug.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #include <linux/uaccess.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/platform_device.h>
  5. #include <linux/cdev.h>
  6. #include <linux/interrupt.h>
  7. #include <asm/io.h>
  8. #include <linux/sched.h>
  9. #include <linux/wait.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/delay.h>
  12. #include <linux/mm.h>
  13. #include <linux/vmalloc.h>
  14. #include <linux/dma-mapping.h>
  15. #include <linux/slab.h>
  16. #include <aee.h>
  17. #include <linux/timer.h>
  18. /* #include <asm/system.h> */
  19. #include <asm-generic/irq_regs.h>
  20. /* #include <asm/mach/map.h> */
  21. #include <sync_write.h>
  22. /*#include <mach/irqs.h>*/
  23. #include <asm/cacheflush.h>
  24. #include <linux/string.h>
  25. #include <linux/time.h>
  26. #include <linux/fb.h>
  27. #include <linux/debugfs.h>
  28. #include <m4u.h>
  29. #include <mt_smi.h>
  30. #include "smi_common.h"
  31. #include "smi_reg.h"
  32. #include "smi_debug.h"
  33. #include "smi_configuration.h"
  34. #define SMI_LOG_TAG "smi"
  35. #if !defined(CONFIG_MTK_CLKMGR)
  36. #define SMI_INTERNAL_CCF_SUPPORT
  37. #endif
  38. #if !defined(SMI_INTERNAL_CCF_SUPPORT)
  39. #include <mach/mt_clkmgr.h>
  40. #endif
  41. /* Debug Function */
  42. static void smi_dump_format(unsigned long base, unsigned int from, unsigned int to);
  43. static void smi_dumpper(int output_gce_buffer, unsigned long *offset, unsigned long base, int reg_number)
  44. {
  45. int num_of_set = 3;
  46. int remain_runtimes = 0;
  47. int runtimes = 0;
  48. int i = 0;
  49. remain_runtimes = reg_number % num_of_set;
  50. runtimes = reg_number / num_of_set;
  51. runtimes = runtimes * 3;
  52. do {
  53. SMIMSG3(output_gce_buffer, "[0x%lx,0x%lx,0x%lx]=[0x%x,0x%x,0x%x]\n",
  54. offset[i], offset[i + 1], offset[i + 2],
  55. M4U_ReadReg32(base, offset[i]), M4U_ReadReg32(base, offset[i + 1]),
  56. M4U_ReadReg32(base, offset[i + 2]));
  57. i += 3;
  58. } while (i < runtimes);
  59. switch (remain_runtimes) {
  60. case 2:
  61. SMIMSG3(output_gce_buffer, "[0x%lx,0x%lx]=[0x%x,0x%x]\n",
  62. offset[i], offset[i + 1],
  63. M4U_ReadReg32(base, offset[i]), M4U_ReadReg32(base, offset[i + 1]));
  64. break;
  65. case 1:
  66. SMIMSG3(output_gce_buffer, "[0x%lx]=[0x%x]\n",
  67. offset[i], M4U_ReadReg32(base, offset[i]));
  68. break;
  69. default:
  70. break;
  71. }
  72. }
  73. void smi_dumpCommonDebugMsg(int output_gce_buffer)
  74. {
  75. unsigned long u4Base;
  76. /* No verify API in CCF, assume clk is always on */
  77. int smiCommonClkEnabled = 1;
  78. #if !defined(SMI_INTERNAL_CCF_SUPPORT)
  79. smiCommonClkEnabled = clock_is_on(MT_CG_DISP0_SMI_COMMON);
  80. #endif /* !defined (SMI_INTERNAL_CCF_SUPPORT) */
  81. /* SMI COMMON dump */
  82. if ((!smiCommonClkEnabled)) {
  83. SMIMSG3(output_gce_buffer, "===SMI common clock is disabled===\n");
  84. return;
  85. }
  86. SMIMSG3(output_gce_buffer, "===SMI common reg dump, CLK: %d===\n", smiCommonClkEnabled);
  87. u4Base = SMI_COMMON_EXT_BASE;
  88. smi_dumpper(output_gce_buffer, smi_common_debug_offset, u4Base,
  89. SMI_COMMON_DEBUG_OFFSET_NUM);
  90. }
  91. void smi_dumpLarbDebugMsg(unsigned int u4Index, int output_gce_buffer)
  92. {
  93. unsigned long u4Base = 0;
  94. /* No verify API in CCF, assume clk is always on */
  95. int larbClkEnabled = 1;
  96. u4Base = get_larb_base_addr(u4Index);
  97. #if !defined(SMI_INTERNAL_CCF_SUPPORT)
  98. larbClkEnabled = smi_larb_clock_is_on(u4Index);
  99. #endif
  100. if (u4Base == SMI_ERROR_ADDR) {
  101. SMIMSG3(output_gce_buffer, "Doesn't support reg dump for Larb%d\n", u4Index);
  102. return;
  103. } else if ((larbClkEnabled != 0)) {
  104. SMIMSG3(output_gce_buffer, "===SMI LARB%d reg dump, CLK: %d===\n", u4Index,
  105. larbClkEnabled);
  106. smi_dumpper(output_gce_buffer, smi_larb_debug_offset[u4Index], u4Base,
  107. smi_larb_debug_offset_num[u4Index]);
  108. } else {
  109. SMIMSG3(output_gce_buffer, "===SMI LARB%d clock is disabled===\n", u4Index);
  110. }
  111. }
  112. void smi_dumpLarb(unsigned int index)
  113. {
  114. unsigned long u4Base;
  115. u4Base = get_larb_base_addr(index);
  116. if (u4Base == SMI_ERROR_ADDR) {
  117. SMIMSG2("Doesn't support reg dump for Larb%d\n", index);
  118. } else {
  119. SMIMSG2("===SMI LARB%d reg dump base 0x%lx===\n", index, u4Base);
  120. smi_dump_format(u4Base, 0, 0x434);
  121. smi_dump_format(u4Base, 0xF00, 0xF0C);
  122. }
  123. }
  124. void smi_dumpCommon(void)
  125. {
  126. SMIMSG2("===SMI COMMON reg dump base 0x%lx===\n", SMI_COMMON_EXT_BASE);
  127. smi_dump_format(SMI_COMMON_EXT_BASE, 0x1A0, 0x444);
  128. }
  129. static void smi_dump_format(unsigned long base, unsigned int from, unsigned int to)
  130. {
  131. int i, j, left;
  132. unsigned int value[8];
  133. for (i = from; i <= to; i += 32) {
  134. for (j = 0; j < 8; j++)
  135. value[j] = M4U_ReadReg32(base, i + j * 4);
  136. SMIMSG2("%8x %x %x %x %x %x %x %x %x\n", i, value[0], value[1],
  137. value[2], value[3], value[4], value[5], value[6], value[7]);
  138. }
  139. left = ((from - to) / 4 + 1) % 8;
  140. if (left) {
  141. memset(value, 0, 8 * sizeof(unsigned int));
  142. for (j = 0; j < left; j++)
  143. value[j] = M4U_ReadReg32(base, i - 32 + j * 4);
  144. SMIMSG2("%8x %x %x %x %x %x %x %x %x\n", i - 32 + j * 4, value[0],
  145. value[1], value[2], value[3], value[4], value[5], value[6], value[7]);
  146. }
  147. }
  148. void smi_dumpDebugMsg(void)
  149. {
  150. unsigned int u4Index;
  151. /* SMI COMMON dump, 0 stands for not pass log to CMDQ error dumping messages */
  152. smi_dumpCommonDebugMsg(0);
  153. /* dump all SMI LARB */
  154. /* SMI Larb dump, 0 stands for not pass log to CMDQ error dumping messages */
  155. for (u4Index = 0; u4Index < SMI_LARB_NR; u4Index++)
  156. smi_dumpLarbDebugMsg(u4Index, 0);
  157. }
  158. int smi_debug_bus_hanging_detect(unsigned int larbs, int show_dump)
  159. {
  160. return smi_debug_bus_hanging_detect_ext(larbs, show_dump, 0);
  161. }
  162. static int get_status_code(int smi_larb_clk_status, int smi_larb_busy_count,
  163. int smi_common_busy_count)
  164. {
  165. int status_code = 0;
  166. if (smi_larb_clk_status != 0) {
  167. if (smi_larb_busy_count == 5) { /* The larb is always busy */
  168. if (smi_common_busy_count == 5) /* smi common is always busy */
  169. status_code = 1;
  170. else if (smi_common_busy_count == 0) /* smi common is always idle */
  171. status_code = 2;
  172. else
  173. status_code = 5; /* smi common is sometimes busy and idle */
  174. } else if (smi_larb_busy_count == 0) { /* The larb is always idle */
  175. if (smi_common_busy_count == 5) /* smi common is always busy */
  176. status_code = 3;
  177. else if (smi_common_busy_count == 0) /* smi common is always idle */
  178. status_code = 4;
  179. else
  180. status_code = 6; /* smi common is sometimes busy and idle */
  181. } else { /* sometime the larb is busy */
  182. if (smi_common_busy_count == 5) /* smi common is always busy */
  183. status_code = 7;
  184. else if (smi_common_busy_count == 0) /* smi common is always idle */
  185. status_code = 8;
  186. else
  187. status_code = 9; /* smi common is sometimes busy and idle */
  188. }
  189. } else {
  190. status_code = 10;
  191. }
  192. return status_code;
  193. }
  194. int smi_debug_bus_hanging_detect_ext(unsigned int larbs, int show_dump, int output_gce_buffer)
  195. {
  196. /* output_gce_buffer = 1, write log into kernel log and CMDQ buffer. */
  197. /* dual_buffer = 0, write log into kernel log only */
  198. int i = 0;
  199. int dump_time = 0;
  200. int is_smi_issue = 0;
  201. int status_code = 0;
  202. /* Keep the dump result */
  203. unsigned char smi_common_busy_count = 0;
  204. unsigned int u4Index = 0;
  205. unsigned long u4Base = 0;
  206. volatile unsigned int reg_temp = 0;
  207. unsigned char smi_larb_busy_count[SMI_LARB_NR] = { 0 };
  208. unsigned char smi_larb_mmu_status[SMI_LARB_NR] = { 0 };
  209. int smi_larb_clk_status[SMI_LARB_NR] = { 0 };
  210. /* dump resister and save resgister status */
  211. for (dump_time = 0; dump_time < 5; dump_time++) {
  212. reg_temp = M4U_ReadReg32(SMI_COMMON_EXT_BASE, 0x440);
  213. if ((reg_temp & (1 << 0)) == 0) {
  214. /* smi common is busy */
  215. smi_common_busy_count++;
  216. }
  217. /* Dump smi common regs */
  218. if (show_dump != 0)
  219. smi_dumpCommonDebugMsg(output_gce_buffer);
  220. for (u4Index = 0; u4Index < SMI_LARB_NR; u4Index++) {
  221. u4Base = get_larb_base_addr(u4Index);
  222. smi_larb_clk_status[u4Index] = smi_larb_clock_is_on(u4Index);
  223. /* check larb clk is enable */
  224. if (smi_larb_clk_status[u4Index] != 0) {
  225. if (u4Base != SMI_ERROR_ADDR) {
  226. reg_temp = M4U_ReadReg32(u4Base, 0x0);
  227. if (reg_temp != 0) {
  228. /* Larb is busy */
  229. smi_larb_busy_count[u4Index]++;
  230. }
  231. smi_larb_mmu_status[u4Index] = M4U_ReadReg32(u4Base, 0xa0);
  232. if (show_dump != 0)
  233. smi_dumpLarbDebugMsg(u4Index, output_gce_buffer);
  234. }
  235. }
  236. }
  237. /* Show the checked result */
  238. for (i = 0; i < SMI_LARB_NR; i++) { /* Check each larb */
  239. if (SMI_DGB_LARB_SELECT(larbs, i)) {
  240. /* larb i has been selected */
  241. /* Get status code */
  242. status_code = get_status_code(smi_larb_clk_status[i], smi_larb_busy_count[i],
  243. smi_common_busy_count);
  244. /* Send the debug message according to the final result */
  245. switch (status_code) {
  246. case 1:
  247. case 3:
  248. case 5:
  249. case 7:
  250. case 8:
  251. SMIMSG3(output_gce_buffer,
  252. "Larb%d Busy=%d/5, SMI Common Busy=%d/5, status=%d ==> Check engine's state first\n",
  253. i, smi_larb_busy_count[i], smi_common_busy_count,
  254. status_code);
  255. SMIMSG3(output_gce_buffer,
  256. "If the engine is waiting for Larb%ds' response, it needs SMI HW's check\n",
  257. i);
  258. break;
  259. case 2:
  260. if (smi_larb_mmu_status[i] == 0) {
  261. SMIMSG3(output_gce_buffer,
  262. "Larb%d Busy=%d/5, SMI Common Busy=%d/5, status=%d ==> Check engine state first\n",
  263. i, smi_larb_busy_count[i],
  264. smi_common_busy_count, status_code);
  265. SMIMSG3(output_gce_buffer,
  266. "If the engine is waiting for Larb%ds' response, it needs SMI HW's check\n",
  267. i);
  268. } else {
  269. SMIMSG3(output_gce_buffer,
  270. "Larb%d Busy=%d/5, SMI Common Busy=%d/5, status=%d ==> MMU port config error\n",
  271. i, smi_larb_busy_count[i],
  272. smi_common_busy_count, status_code);
  273. is_smi_issue = 1;
  274. }
  275. break;
  276. case 4:
  277. case 6:
  278. case 9:
  279. SMIMSG3(output_gce_buffer,
  280. "Larb%d Busy=%d/5, SMI Common Busy=%d/5, status=%d ==> not SMI issue\n",
  281. i, smi_larb_busy_count[i], smi_common_busy_count,
  282. status_code);
  283. break;
  284. case 10:
  285. SMIMSG3(output_gce_buffer,
  286. "Larb%d clk is disbable, status=%d ==> no need to check\n",
  287. i, status_code);
  288. break;
  289. default:
  290. SMIMSG3(output_gce_buffer,
  291. "Larb%d Busy=%d/5, SMI Common Busy=%d/5, status=%d ==> status unknown\n",
  292. i, smi_larb_busy_count[i], smi_common_busy_count,
  293. status_code);
  294. break;
  295. }
  296. }
  297. }
  298. }
  299. return is_smi_issue;
  300. }