wd_api.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. #include <linux/kernel.h>
  2. #include <ext_wd_drv.h>
  3. #include <mach/wd_api.h>
  4. #include <linux/smp.h>
  5. /*add by debug for register restart notify*/
  6. #include <linux/notifier.h>
  7. #include <linux/reboot.h>
  8. #include <mt-plat/mt_reboot.h>
  9. #include <mt-plat/mtk_rtc.h>
  10. static int wd_cpu_hot_plug_on_notify(int cpu);
  11. static int wd_cpu_hot_plug_off_notify(int cpu);
  12. static int spmwdt_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode);
  13. static int thermal_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode);
  14. static int confirm_hwreboot(void);
  15. static void resume_notify(void);
  16. static void suspend_notify(void);
  17. static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val);
  18. static unsigned int wd_get_check_bit(void);
  19. static unsigned int wd_get_kick_bit(void);
  20. static int disable_all_wd(void);
  21. static int disable_ext(void);
  22. static int disable_local(void);
  23. static int wd_sw_reset(int type);
  24. static int wd_restart(enum wd_restart_type type);
  25. static int set_mode(enum ext_wdt_mode mode);
  26. static int wd_dram_reserved_mode(bool enabled);
  27. static int thermal_direct_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode);
  28. static int debug_key_eint_config(WD_REQ_CTL en, WD_REQ_MODE mode);
  29. static int debug_key_sysrst_config(WD_REQ_CTL en, WD_REQ_MODE mode);
  30. static struct wd_api g_wd_api_obj = {
  31. .ready = 1,
  32. .wd_cpu_hot_plug_on_notify = wd_cpu_hot_plug_on_notify, /* for cpu hot plug */
  33. .wd_cpu_hot_plug_off_notify = wd_cpu_hot_plug_off_notify, /* for cpu hot plug */
  34. .wd_spmwdt_mode_config = spmwdt_mode_config,
  35. .wd_thermal_mode_config = thermal_mode_config,
  36. .wd_sw_reset = wd_sw_reset,
  37. .wd_restart = wd_restart,
  38. .wd_config = mtk_wk_wdt_config,
  39. .wd_set_mode = set_mode,
  40. .wd_aee_confirm_hwreboot = confirm_hwreboot,
  41. .wd_disable_ext = disable_ext,
  42. .wd_disable_local = disable_local,
  43. .wd_suspend_notify = suspend_notify,
  44. .wd_resume_notify = resume_notify,
  45. .wd_disable_all = disable_all_wd,
  46. .wd_get_check_bit = wd_get_check_bit,
  47. .wd_get_kick_bit = wd_get_kick_bit,
  48. .wd_dram_reserved_mode = wd_dram_reserved_mode,
  49. .wd_thermal_direct_mode_config = thermal_direct_mode_config,
  50. .wd_debug_key_eint_config = debug_key_eint_config,
  51. .wd_debug_key_sysrst_config = debug_key_sysrst_config,
  52. };
  53. /* struct wd_private_api *g_wd_private_api_obj; */
  54. /* apiimplimentation */
  55. #ifdef CONFIG_MTK_WD_KICKER
  56. static unsigned int wd_get_check_bit(void)
  57. {
  58. return get_check_bit();
  59. }
  60. static unsigned int wd_get_kick_bit(void)
  61. {
  62. return get_kick_bit();
  63. }
  64. static int wd_restart(enum wd_restart_type type)
  65. {
  66. #ifdef CONFIG_LOCAL_WDT
  67. #ifdef CONFIG_SMP
  68. on_each_cpu((smp_call_func_t) mpcore_wdt_restart, WD_TYPE_NORMAL, 0);
  69. #else
  70. mpcore_wdt_restart(type);
  71. #endif
  72. #endif
  73. mtk_wdt_restart(type);
  74. return 0;
  75. }
  76. static int wd_cpu_hot_plug_on_notify(int cpu)
  77. {
  78. int res = 0;
  79. wk_cpu_update_bit_flag(cpu, 1);
  80. mtk_wdt_restart(WD_TYPE_NOLOCK); /* for KICK external wdt */
  81. pr_alert("WD wd_cpu_hot_plug_on_notify kick ext wd\n");
  82. return res;
  83. }
  84. static int wd_cpu_hot_plug_off_notify(int cpu)
  85. {
  86. int res = 0;
  87. wk_cpu_update_bit_flag(cpu, 0);
  88. return res;
  89. }
  90. static int wd_sw_reset(int type)
  91. {
  92. wdt_arch_reset(type);
  93. return 0;
  94. }
  95. static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val)
  96. {
  97. mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE);
  98. mtk_wdt_set_time_out_value(timeout_val);
  99. #ifdef CONFIG_LOCAL_WDT
  100. mpcore_wk_wdt_config(0, 0, timeout_val - 5); /* local 25s time out */
  101. /* mpcore_wdt_set_heartbeat(timeout_val - 5);//local 25s time out */
  102. #endif
  103. return 0;
  104. }
  105. static int disable_ext(void)
  106. {
  107. mtk_wdt_enable(WK_WDT_DIS);
  108. return 0;
  109. }
  110. static int disable_local(void)
  111. {
  112. #ifdef CONFIG_LOCAL_WDT
  113. #ifdef CONFIG_SMP
  114. on_each_cpu((smp_call_func_t) local_wdt_enable, WK_WDT_DIS, 0);
  115. #else
  116. local_wdt_enable(WK_WDT_DIS);
  117. #endif
  118. #endif
  119. pr_debug(" wd_api disable_local not support now\n");
  120. return 0;
  121. }
  122. static int set_mode(enum ext_wdt_mode mode)
  123. {
  124. pr_debug(" support only irq mode-20140522");
  125. switch (mode) {
  126. case WDT_DUAL_MODE:
  127. break;
  128. case WDT_HW_REBOOT_ONLY_MODE:
  129. break;
  130. case WDT_IRQ_ONLY_MODE:
  131. pr_debug("wd set only irq mode for debug\n");
  132. mtk_wdt_mode_config(FALSE, TRUE, TRUE, FALSE, TRUE);
  133. break;
  134. }
  135. return 0;
  136. }
  137. static int confirm_hwreboot(void)
  138. {
  139. mtk_wdt_confirm_hwreboot();
  140. return 0;
  141. }
  142. static void suspend_notify(void)
  143. {
  144. mtk_wd_suspend();
  145. }
  146. static void resume_notify(void)
  147. {
  148. mtk_wd_resume();
  149. }
  150. static int disable_all_wd(void)
  151. {
  152. disable_ext();
  153. #ifdef CONFIG_LOCAL_WDT
  154. disable_local();
  155. #endif
  156. return 0;
  157. }
  158. static int spmwdt_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  159. {
  160. int res = 0;
  161. if (WD_REQ_EN == en) {
  162. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_EN); */
  163. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_EN);
  164. } else if (WD_REQ_DIS == en) {
  165. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_DIS); */
  166. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_DIS);
  167. } else {
  168. res = -2;
  169. }
  170. if (WD_REQ_IRQ_MODE == mode) {
  171. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_IRQ_MODE);
  172. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_IRQ_MODE); */
  173. } else if (WD_REQ_RST_MODE == mode) {
  174. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_RST_MODE);
  175. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_RST_MODE); */
  176. } else {
  177. res = -3;
  178. }
  179. return res;
  180. }
  181. static int thermal_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  182. {
  183. int res = 0;
  184. if (WD_REQ_EN == en) {
  185. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_EN); */
  186. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK, WD_REQ_EN);
  187. } else if (WD_REQ_DIS == en) {
  188. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_DIS); */
  189. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK, WD_REQ_DIS);
  190. } else {
  191. res = -2;
  192. }
  193. if (WD_REQ_IRQ_MODE == mode) {
  194. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_IRQ_MODE); */
  195. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK, WD_REQ_IRQ_MODE);
  196. } else if (WD_REQ_RST_MODE == mode) {
  197. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_RST_MODE); */
  198. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK, WD_REQ_RST_MODE);
  199. } else {
  200. res = -3;
  201. }
  202. return res;
  203. }
  204. static int thermal_direct_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  205. {
  206. int res = 0;
  207. pr_debug("thermal_direct_mode_config(en:0x%x,mode:0x%x)\n", en, mode);
  208. if (WD_REQ_EN == en) {
  209. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_EN); */
  210. res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_EN);
  211. } else if (WD_REQ_DIS == en) {
  212. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_DIS); */
  213. res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_DIS);
  214. } else {
  215. res = -2;
  216. }
  217. if (WD_REQ_IRQ_MODE == mode) {
  218. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_IRQ_MODE); */
  219. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_IRQ_MODE);
  220. } else if (WD_REQ_RST_MODE == mode) {
  221. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_RST_MODE); */
  222. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_RST_MODE);
  223. } else {
  224. res = -3;
  225. }
  226. return res;
  227. }
  228. static int wd_dram_reserved_mode(bool enabled)
  229. {
  230. int ret = 0;
  231. if (true == enabled) {
  232. mtk_wdt_swsysret_config(0x10000000, 1);
  233. mtk_rgu_dram_reserved(1);
  234. } else {
  235. mtk_wdt_swsysret_config(0x10000000, 0);
  236. mtk_rgu_dram_reserved(0);
  237. }
  238. return ret;
  239. }
  240. static int debug_key_eint_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  241. {
  242. int res = 0;
  243. pr_debug("debug_key_eint_config(en:0x%x,mode:0x%x)\n", en, mode);
  244. if (WD_REQ_EN == en)
  245. res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_EN);
  246. else if (WD_REQ_DIS == en)
  247. res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_DIS);
  248. else
  249. res = -2;
  250. if (WD_REQ_IRQ_MODE == mode)
  251. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_IRQ_MODE);
  252. else if (WD_REQ_RST_MODE == mode)
  253. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_RST_MODE);
  254. else
  255. res = -3;
  256. return res;
  257. }
  258. static int debug_key_sysrst_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  259. {
  260. int res = 0;
  261. pr_debug("debug_key_sysrst_config(en:0x%x,mode:0x%x)\n", en, mode);
  262. if (WD_REQ_EN == en)
  263. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_EN);
  264. else if (WD_REQ_DIS == en)
  265. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_DIS);
  266. else
  267. res = -2;
  268. if (WD_REQ_IRQ_MODE == mode)
  269. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_IRQ_MODE);
  270. else if (WD_REQ_RST_MODE == mode)
  271. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_RST_MODE);
  272. else
  273. res = -3;
  274. return res;
  275. }
  276. #else
  277. /* dummy api */
  278. static unsigned int wd_get_check_bit(void)
  279. {
  280. pr_debug("dummy wd_get_check_bit");
  281. return 0;
  282. }
  283. static unsigned int wd_get_kick_bit(void)
  284. {
  285. pr_debug("dummy wd_get_kick_bit");
  286. return 0;
  287. }
  288. static int wd_restart(enum wd_restart_type type)
  289. {
  290. pr_debug("dummy wd_restart");
  291. return 0;
  292. }
  293. static int wd_cpu_hot_plug_on_notify(int cpu)
  294. {
  295. int res = 0;
  296. pr_debug("dummy wd_cpu_hot_plug_on_notify");
  297. return res;
  298. }
  299. static int wd_cpu_hot_plug_off_notify(int cpu)
  300. {
  301. int res = 0;
  302. pr_debug("dummy wd_cpu_hot_plug_off_notify");
  303. return res;
  304. }
  305. static int wd_sw_reset(int type)
  306. {
  307. pr_debug("dummy wd_sw_reset");
  308. wdt_arch_reset(type);
  309. return 0;
  310. }
  311. static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val)
  312. {
  313. pr_debug("dummy mtk_wk_wdt_config");
  314. return 0;
  315. }
  316. static int disable_ext(void)
  317. {
  318. pr_debug("dummy disable_ext");
  319. return 0;
  320. }
  321. static int disable_local(void)
  322. {
  323. pr_debug("dummy disable_local");
  324. return 0;
  325. }
  326. static int set_mode(enum ext_wdt_mode mode)
  327. {
  328. pr_debug("dummy set_mode");
  329. return 0;
  330. }
  331. static int confirm_hwreboot(void)
  332. {
  333. pr_debug("dummy confirm_hwreboot");
  334. return 0;
  335. }
  336. static void suspend_notify(void)
  337. {
  338. pr_debug("dummy suspend_notify\n");
  339. }
  340. static void resume_notify(void)
  341. {
  342. pr_debug("dummy resume_notify\n");
  343. }
  344. static int disable_all_wd(void)
  345. {
  346. pr_debug("dummy disable_all_wd\n");
  347. return 0;
  348. }
  349. static int spmwdt_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  350. {
  351. int res = 0;
  352. pr_debug("dummy spmwdt_mode_config\n");
  353. return res;
  354. }
  355. static int thermal_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  356. {
  357. int res = 0;
  358. pr_debug("dummy thermal_mode_config\n");
  359. return res;
  360. }
  361. static int wd_dram_reserved_mode(bool enabled)
  362. {
  363. int res = 0;
  364. pr_debug("dummy wd_dram_reserved_mode\n");
  365. return res;
  366. }
  367. static int thermal_direct_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  368. {
  369. int res = 0;
  370. pr_debug("thermal_direct_mode_config in dummy driver (en:0x%x,mode:0x%x)\n", en, mode);
  371. if (WD_REQ_EN == en) {
  372. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_EN); */
  373. res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_EN);
  374. } else if (WD_REQ_DIS == en) {
  375. /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_DIS); */
  376. res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_DIS);
  377. } else {
  378. res = -2;
  379. }
  380. if (WD_REQ_IRQ_MODE == mode) {
  381. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_IRQ_MODE); */
  382. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_IRQ_MODE);
  383. } else if (WD_REQ_RST_MODE == mode) {
  384. /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK,WD_REQ_RST_MODE); */
  385. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, WD_REQ_RST_MODE);
  386. } else {
  387. res = -3;
  388. }
  389. return res;
  390. }
  391. static int debug_key_eint_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  392. {
  393. int res = 0;
  394. pr_debug("debug_key_eint_config(en:0x%x,mode:0x%x)\n", en, mode);
  395. if (WD_REQ_EN == en)
  396. res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_EN);
  397. else if (WD_REQ_DIS == en)
  398. res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_DIS);
  399. else
  400. res = -2;
  401. if (WD_REQ_IRQ_MODE == mode)
  402. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_IRQ_MODE);
  403. else if (WD_REQ_RST_MODE == mode)
  404. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_RST_MODE);
  405. else
  406. res = -3;
  407. return res;
  408. }
  409. static int debug_key_sysrst_config(WD_REQ_CTL en, WD_REQ_MODE mode)
  410. {
  411. int res = 0;
  412. pr_debug("debug_key_sysrst_config(en:0x%x,mode:0x%x)\n", en, mode);
  413. if (WD_REQ_EN == en)
  414. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_EN);
  415. else if (WD_REQ_DIS == en)
  416. res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_DIS);
  417. else
  418. res = -2;
  419. if (WD_REQ_IRQ_MODE == mode)
  420. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_IRQ_MODE);
  421. else if (WD_REQ_RST_MODE == mode)
  422. res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_RST_MODE);
  423. else
  424. res = -3;
  425. return res;
  426. }
  427. #endif
  428. /* public interface implimentation end */
  429. int wd_api_init(void)
  430. {
  431. int i = 0;
  432. long *check_p = NULL;
  433. int api_size = 0;
  434. api_size = (sizeof(g_wd_api_obj) / sizeof(long));
  435. pr_debug("wd api_size=%d\n", api_size);
  436. /* check wd api */
  437. check_p = (long *)&g_wd_api_obj;
  438. for (i = 1; i < api_size; i++) {
  439. pr_debug("p[%d]=%lx\n", i, *(check_p + i));
  440. if (0 == check_p[i]) {
  441. pr_debug("wd_api init fail the %d api not init\n", i);
  442. g_wd_api_obj.ready = 0;
  443. return -1;
  444. }
  445. }
  446. pr_debug("wd_api init ok\n");
  447. return 0;
  448. }
  449. int get_wd_api(struct wd_api **obj)
  450. {
  451. int res = 0;
  452. *obj = &g_wd_api_obj;
  453. if (NULL == *obj) {
  454. res = -1;
  455. }
  456. if ((*obj)->ready == 0) {
  457. res = -2;
  458. }
  459. return res;
  460. }
  461. /*register restart notify and own by debug start-------
  462. *
  463. */
  464. void arch_reset(char mode, const char *cmd)
  465. {
  466. char reboot = 1;
  467. int res = 0;
  468. struct wd_api *wd_api = NULL;
  469. #ifdef CONFIG_FPGA_EARLY_PORTING
  470. return;
  471. #else
  472. res = get_wd_api(&wd_api);
  473. pr_alert("arch_reset: cmd = %s\n", cmd ? : "NULL");
  474. dump_stack();
  475. if (cmd && !strcmp(cmd, "charger")) {
  476. /* do nothing */
  477. } else if (cmd && !strcmp(cmd, "recovery")) {
  478. rtc_mark_recovery();
  479. } else if (cmd && !strcmp(cmd, "bootloader")) {
  480. rtc_mark_fast();
  481. } else if (cmd && !strcmp(cmd, "kpoc")) {
  482. #ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING
  483. rtc_mark_kpoc();
  484. #endif
  485. } else {
  486. reboot = 1;
  487. }
  488. if (res)
  489. pr_err("arch_reset, get wd api error %d\n", res);
  490. else
  491. wd_api->wd_sw_reset(reboot);
  492. #endif
  493. }
  494. static struct notifier_block mtk_restart_handler;
  495. static int mtk_arch_reset_handle(struct notifier_block *this, unsigned long mode, void *cmd)
  496. {
  497. pr_alert("ARCH_RESET happen!!!\n");
  498. arch_reset(mode, cmd);
  499. pr_alert("ARCH_RESET end!!!!\n");
  500. return NOTIFY_DONE;
  501. }
  502. static int __init mtk_arch_reset_init(void)
  503. {
  504. int ret;
  505. mtk_restart_handler.notifier_call = mtk_arch_reset_handle;
  506. mtk_restart_handler.priority = 128;
  507. pr_alert("\n register_restart_handler- 0x%p, Notify call: - 0x%p\n",
  508. &mtk_restart_handler, mtk_restart_handler.notifier_call);
  509. ret = register_restart_handler(&mtk_restart_handler);
  510. if (ret)
  511. pr_err("ARCH_RESET cannot register mtk_restart_handler!!!!\n");
  512. pr_alert("ARCH_RESET register mtk_restart_handler ok!!!!\n");
  513. return ret;
  514. }
  515. pure_initcall(mtk_arch_reset_init);
  516. /*register restart notify and own by debug end+++++
  517. *
  518. */