wd_common_drv.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. #include <linux/version.h>
  2. #include <linux/kernel.h>
  3. #include <linux/sched.h>
  4. #include <linux/kthread.h>
  5. #include <linux/delay.h>
  6. #include <linux/module.h>
  7. #include <linux/init.h>
  8. #include <linux/proc_fs.h>
  9. #include <linux/string.h>
  10. #include <linux/uaccess.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/rtc.h>
  13. #include <linux/cpu.h>
  14. #include <mt-plat/aee.h>
  15. #include <ext_wd_drv.h>
  16. #include <mach/wd_api.h>
  17. #include <linux/seq_file.h>
  18. /*#include <mach/mtk_rtc.h>*/
  19. /*************************************************************************
  20. * Feature configure region
  21. *************************************************************************/
  22. #define __ENABLE_WDT_SYSFS__
  23. #define __ENABLE_WDT_AT_INIT__
  24. /* ------------------------------------------------------------------------ */
  25. #define PFX "wdk: "
  26. #define DEBUG_WDK 0
  27. #if DEBUG_WDK
  28. #define dbgmsg(msg...) pr_debug(PFX msg)
  29. #else
  30. #define dbgmsg(...)
  31. #endif
  32. #define msg(msg...) pr_info(PFX msg)
  33. #define warnmsg(msg...) pr_warn(PFX msg)
  34. #define errmsg(msg...) pr_err(PFX msg)
  35. #define MIN_KICK_INTERVAL 1
  36. #define MAX_KICK_INTERVAL 30
  37. #define MRDUMP_SYSRESETB 0
  38. #define MRDUMP_EINTRST 1
  39. #define PROC_WK "wdk"
  40. #define PROC_MRDUMP_RST "mrdump_rst"
  41. static int kwdt_thread(void *arg);
  42. static int start_kicker(void);
  43. static int g_kicker_init;
  44. static int debug_sleep;
  45. static DEFINE_SPINLOCK(lock);
  46. #define CPU_NR (nr_cpu_ids)
  47. struct task_struct *wk_tsk[16] = { 0 }; /* max cpu 16 */
  48. static unsigned long kick_bit;
  49. enum ext_wdt_mode g_wk_wdt_mode = WDT_DUAL_MODE;
  50. static struct wd_api *g_wd_api;
  51. static int g_kinterval = -1;
  52. static int g_timeout = -1;
  53. static int g_need_config;
  54. static int wdt_start;
  55. static int g_enable = 1;
  56. static unsigned int lasthpg_act;
  57. static unsigned int lasthpg_cpu;
  58. static unsigned long long lasthpg_t;
  59. static char cmd_buf[256];
  60. static int wk_proc_cmd_read(struct seq_file *s, void *v)
  61. {
  62. seq_printf(s, "mode interval timeout enable\n%-4d %-9d %-8d %-7d\n", g_wk_wdt_mode,
  63. g_kinterval, g_timeout, g_enable);
  64. return 0;
  65. }
  66. static int wk_proc_cmd_open(struct inode *inode, struct file *file)
  67. {
  68. return single_open(file, wk_proc_cmd_read, NULL);
  69. }
  70. static ssize_t wk_proc_cmd_write(struct file *file, const char *buf, size_t count, loff_t *data)
  71. {
  72. int ret;
  73. int timeout;
  74. int mode;
  75. int kinterval;
  76. int en; /* enable or disable ext wdt 1<-->enable 0<-->disable */
  77. struct wd_api *my_wd_api = NULL;
  78. ret = get_wd_api(&my_wd_api);
  79. if (ret)
  80. pr_debug("get public api error in wd common driver %d", ret);
  81. if (count == 0)
  82. return -1;
  83. if (count > 255)
  84. count = 255;
  85. ret = copy_from_user(cmd_buf, buf, count);
  86. if (ret < 0)
  87. return -1;
  88. cmd_buf[count] = '\0';
  89. pr_debug("Write %s\n", cmd_buf);
  90. ret = sscanf(cmd_buf, "%d %d %d %d %d", &mode, &kinterval, &timeout, &debug_sleep, &en);
  91. pr_debug("[WDK] mode=%d interval=%d timeout=%d enable =%d\n", mode, kinterval, timeout, en);
  92. if (timeout < kinterval) {
  93. pr_err("The interval(%d) value should be smaller than timeout value(%d)\n",
  94. kinterval, timeout);
  95. return -1;
  96. }
  97. if ((timeout < MIN_KICK_INTERVAL) || (timeout > MAX_KICK_INTERVAL)) {
  98. pr_err("The timeout(%d) is invalid (%d - %d)\n", kinterval, MIN_KICK_INTERVAL,
  99. MAX_KICK_INTERVAL);
  100. return -1;
  101. }
  102. if ((kinterval < MIN_KICK_INTERVAL) || (kinterval > MAX_KICK_INTERVAL)) {
  103. pr_err("The interval(%d) is invalid (%d - %d)\n", kinterval, MIN_KICK_INTERVAL,
  104. MAX_KICK_INTERVAL);
  105. return -1;
  106. }
  107. if (!((mode == WDT_IRQ_ONLY_MODE) ||
  108. (mode == WDT_HW_REBOOT_ONLY_MODE) || (mode == WDT_DUAL_MODE))) {
  109. pr_err("Tha watchdog kicker wdt mode is not correct %d\n", mode);
  110. return -1;
  111. }
  112. if (1 == en) {
  113. mtk_wdt_enable(WK_WDT_EN);
  114. #ifdef CONFIG_LOCAL_WDT
  115. local_wdt_enable(WK_WDT_EN);
  116. pr_debug("[WDK] enable local wdt\n");
  117. #endif
  118. pr_debug("[WDK] enable wdt\n");
  119. }
  120. if (0 == en) {
  121. mtk_wdt_enable(WK_WDT_DIS);
  122. #ifdef CONFIG_LOCAL_WDT
  123. local_wdt_enable(WK_WDT_DIS);
  124. pr_debug("[WDK] disable local wdt\n");
  125. #endif
  126. pr_debug("[WDK] disable wdt\n");
  127. }
  128. spin_lock(&lock);
  129. g_enable = en;
  130. g_kinterval = kinterval;
  131. g_wk_wdt_mode = mode;
  132. if (1 == mode) {
  133. /* irq mode only useful to 75 */
  134. mtk_wdt_swsysret_config(0x20000000, 1);
  135. pr_debug("[WDK] use irq mod\n");
  136. } else if (0 == mode) {
  137. /* reboot mode only useful to 75 */
  138. mtk_wdt_swsysret_config(0x20000000, 0);
  139. pr_debug("[WDK] use reboot mod\n");
  140. } else if (2 == mode)
  141. my_wd_api->wd_set_mode(WDT_IRQ_ONLY_MODE);
  142. else
  143. pr_debug("[WDK] mode err\n");
  144. g_timeout = timeout;
  145. if (mode != 2)
  146. g_need_config = 1;
  147. spin_unlock(&lock);
  148. return count;
  149. }
  150. static int mrdump_proc_cmd_read(struct seq_file *s, void *v)
  151. {
  152. return 0;
  153. }
  154. static int mrdump_proc_cmd_open(struct inode *inode, struct file *file)
  155. {
  156. return single_open(file, mrdump_proc_cmd_read, NULL);
  157. }
  158. static ssize_t mrdump_proc_cmd_write(struct file *file, const char *buf, size_t count,
  159. loff_t *data)
  160. {
  161. int ret = 0;
  162. int mrdump_rst_source;
  163. int en, mode; /* enable or disable ext wdt 1<-->enable 0<-->disable */
  164. char mrdump_cmd_buf[256];
  165. struct wd_api *my_wd_api = NULL;
  166. ret = get_wd_api(&my_wd_api);
  167. if (ret)
  168. pr_debug("get public api error in wd common driver %d", ret);
  169. if (count == 0)
  170. return -1;
  171. if (count > 255)
  172. count = 255;
  173. ret = copy_from_user(mrdump_cmd_buf, buf, count);
  174. if (ret < 0)
  175. return -1;
  176. mrdump_cmd_buf[count] = '\0';
  177. dbgmsg("Write %s\n", mrdump_cmd_buf);
  178. ret = sscanf(mrdump_cmd_buf, "%d %d %d", &mrdump_rst_source, &mode, &en);
  179. if (ret != 3)
  180. pr_debug("%s: expect 3 numbers\n", __func__);
  181. pr_debug("[MRDUMP] rst_source=%d mode=%d enable=%d\n", mrdump_rst_source, mode, en);
  182. if (1 < mrdump_rst_source) {
  183. errmsg("The mrdump_rst_source(%d) value should be smaller than 2\n",
  184. mrdump_rst_source);
  185. return -1;
  186. }
  187. if (1 < mode) {
  188. errmsg("The mrdump_rst_mode(%d) value should be smaller than 2\n", mode);
  189. return -1;
  190. }
  191. spin_lock(&lock);
  192. if (mrdump_rst_source == MRDUMP_SYSRESETB) {
  193. ret = my_wd_api->wd_debug_key_sysrst_config(en, mode);
  194. } else if (mrdump_rst_source == MRDUMP_EINTRST) {
  195. ret = my_wd_api->wd_debug_key_eint_config(en, mode);
  196. } else {
  197. pr_debug("[MRDUMP] invalid mrdump_rst_source\n");
  198. ret = -1;
  199. }
  200. spin_unlock(&lock);
  201. if (ret == 0)
  202. pr_debug("[MRDUMP] MRDUMP External success\n");
  203. else
  204. pr_debug("[MRDUMP] MRDUMP External key not support!\n");
  205. return count;
  206. }
  207. static int start_kicker_thread_with_default_setting(void)
  208. {
  209. int ret = 0;
  210. spin_lock(&lock);
  211. g_kinterval = 20; /* default interval: 20s */
  212. g_need_config = 0; /* Note, we DO NOT want to call configure function */
  213. wdt_start = 1; /* Start once only */
  214. spin_unlock(&lock);
  215. start_kicker();
  216. pr_debug("[WDK] fwq start_kicker_thread_with_default_setting done\n");
  217. return ret;
  218. }
  219. static unsigned int cpus_kick_bit;
  220. void wk_start_kick_cpu(int cpu)
  221. {
  222. if (IS_ERR(wk_tsk[cpu])) {
  223. pr_debug("[wdk]wk_task[%d] is NULL\n", cpu);
  224. } else {
  225. kthread_bind(wk_tsk[cpu], cpu);
  226. pr_debug("[wdk]bind thread[%d] to cpu[%d]\n", wk_tsk[cpu]->pid, cpu);
  227. wake_up_process(wk_tsk[cpu]);
  228. }
  229. }
  230. void kicker_cpu_bind(int cpu)
  231. {
  232. if (IS_ERR(wk_tsk[cpu]))
  233. pr_debug("[wdk]wk_task[%d] is NULL\n", cpu);
  234. else {
  235. /* kthread_bind(wk_tsk[cpu], cpu); */
  236. WARN_ON_ONCE(set_cpus_allowed_ptr(wk_tsk[cpu], cpumask_of(cpu)) < 0);
  237. wake_up_process(wk_tsk[cpu]);
  238. pr_debug("[wdk]bind kicker thread[%d] to cpu[%d]\n", wk_tsk[cpu]->pid, cpu);
  239. }
  240. }
  241. void wk_cpu_update_bit_flag(int cpu, int plug_status)
  242. {
  243. if (1 == plug_status) { /* plug on */
  244. spin_lock(&lock);
  245. cpus_kick_bit |= (1 << cpu);
  246. kick_bit = 0;
  247. lasthpg_cpu = cpu;
  248. lasthpg_act = plug_status;
  249. lasthpg_t = sched_clock();
  250. spin_unlock(&lock);
  251. }
  252. if (0 == plug_status) { /* plug off */
  253. spin_lock(&lock);
  254. cpus_kick_bit &= (~(1 << cpu));
  255. kick_bit = 0;
  256. lasthpg_cpu = cpu;
  257. lasthpg_act = plug_status;
  258. lasthpg_t = sched_clock();
  259. spin_unlock(&lock);
  260. }
  261. }
  262. unsigned int wk_check_kick_bit(void)
  263. {
  264. return cpus_kick_bit;
  265. }
  266. static const struct file_operations wk_proc_cmd_fops = {
  267. .owner = THIS_MODULE,
  268. .open = wk_proc_cmd_open,
  269. .read = seq_read,
  270. .write = wk_proc_cmd_write,
  271. .llseek = seq_lseek,
  272. .release = single_release,
  273. };
  274. static const struct file_operations mrdump_rst_proc_cmd_fops = {
  275. .owner = THIS_MODULE,
  276. .open = mrdump_proc_cmd_open,
  277. .read = seq_read,
  278. .write = mrdump_proc_cmd_write,
  279. .llseek = seq_lseek,
  280. .release = single_release,
  281. };
  282. int wk_proc_init(void)
  283. {
  284. struct proc_dir_entry *de = proc_create(PROC_WK, 0660, NULL, &wk_proc_cmd_fops);
  285. if (!de)
  286. pr_debug("[wk_proc_init]: create /proc/wdk failed\n");
  287. de = proc_create(PROC_MRDUMP_RST, 0660, NULL, &mrdump_rst_proc_cmd_fops);
  288. if (!de)
  289. pr_debug("[wk_proc_init]: create /proc/mrdump_rst failed\n");
  290. pr_debug("[WDK] Initialize proc\n");
  291. /* de->read_proc = wk_proc_cmd_read; */
  292. /* de->write_proc = wk_proc_cmd_write; */
  293. return 0;
  294. }
  295. void wk_proc_exit(void)
  296. {
  297. remove_proc_entry(PROC_WK, NULL);
  298. }
  299. static int kwdt_thread(void *arg)
  300. {
  301. struct sched_param param = {.sched_priority = 99 };
  302. struct rtc_time tm;
  303. struct timeval tv = { 0 };
  304. /* android time */
  305. struct rtc_time tm_android;
  306. struct timeval tv_android = { 0 };
  307. int cpu = 0;
  308. int local_bit = 0, loc_need_config = 0, loc_timeout = 0;
  309. struct wd_api *loc_wk_wdt = NULL;
  310. sched_setscheduler(current, SCHED_FIFO, &param);
  311. set_current_state(TASK_INTERRUPTIBLE);
  312. for (;;) {
  313. if (kthread_should_stop()) {
  314. pr_err("[WDK] kthread_should_stop do !!\n");
  315. break;
  316. }
  317. spin_lock(&lock);
  318. cpu = smp_processor_id();
  319. loc_wk_wdt = g_wd_api;
  320. loc_need_config = g_need_config;
  321. loc_timeout = g_timeout;
  322. spin_unlock(&lock);
  323. /* printk("fwq loc_wk_wdt(%x),loc_wk_wdt->ready(%d)\n",loc_wk_wdt ,loc_wk_wdt->ready); */
  324. if (loc_wk_wdt && loc_wk_wdt->ready && g_enable) {
  325. if (loc_need_config) {
  326. /* daul mode */
  327. loc_wk_wdt->wd_config(WDT_DUAL_MODE, loc_timeout);
  328. spin_lock(&lock);
  329. g_need_config = 0;
  330. spin_unlock(&lock);
  331. }
  332. /* pr_debug("[WDK] cpu-task=%d, current_pid=%d\n", wk_tsk[cpu]->pid, current->pid); */
  333. /*to avoid wk_tsk[cpu] had not created out */
  334. if (wk_tsk[cpu] != 0) {
  335. if (wk_tsk[cpu]->pid == current->pid) {
  336. /* only process WDT info if thread-x is on cpu-x */
  337. spin_lock(&lock);
  338. local_bit = kick_bit;
  339. printk_deferred("[WDK], local_bit:0x%x, cpu:%d,RT[%lld]\n",
  340. local_bit, cpu, sched_clock());
  341. if ((local_bit & (1 << cpu)) == 0) {
  342. /* printk("[WDK]: set WDT kick_bit\n"); */
  343. local_bit |= (1 << cpu);
  344. /* aee_rr_rec_wdk_kick_jiffies(jiffies); */
  345. }
  346. printk_deferred
  347. ("[WDK], local_bit:0x%x, cpu:%d, check bit0x:%x, lasthpg_cpu:%d, lasthpg_act:%d, lasthpg_t:%lld, RT[%lld]\n",
  348. local_bit, cpu, wk_check_kick_bit(), lasthpg_cpu, lasthpg_act, lasthpg_t, sched_clock());
  349. if (local_bit == wk_check_kick_bit()) {
  350. printk_deferred("[WDK]: kick Ex WDT,RT[%lld]\n",
  351. sched_clock());
  352. mtk_wdt_restart(WD_TYPE_NORMAL); /* for KICK external wdt */
  353. local_bit = 0;
  354. }
  355. kick_bit = local_bit;
  356. spin_unlock(&lock);
  357. #ifdef CONFIG_LOCAL_WDT
  358. printk_deferred("[WDK]: cpu:%d, kick local wdt,RT[%lld]\n",
  359. cpu, sched_clock());
  360. /* kick local wdt */
  361. mpcore_wdt_restart(WD_TYPE_NORMAL);
  362. #endif
  363. }
  364. }
  365. } else if (0 == g_enable) {
  366. pr_debug("WDK stop to kick\n");
  367. } else {
  368. pr_err("No watch dog driver is hooked\n");
  369. BUG();
  370. }
  371. /*to avoid wk_tsk[cpu] had not created out */
  372. if (wk_tsk[cpu] != 0) {
  373. if (wk_tsk[cpu]->pid == current->pid) {
  374. #if (DEBUG_WDK == 1)
  375. msleep_interruptible(debug_sleep * 1000);
  376. pr_debug("WD kicker woke up %d\n", debug_sleep);
  377. #endif
  378. do_gettimeofday(&tv);
  379. tv_android = tv;
  380. rtc_time_to_tm(tv.tv_sec, &tm);
  381. tv_android.tv_sec -= sys_tz.tz_minuteswest * 60;
  382. rtc_time_to_tm(tv_android.tv_sec, &tm_android);
  383. printk_deferred
  384. ("[thread:%d][RT:%lld] %d-%02d-%02d %02d:%02d:%02d.%u UTC;"
  385. "android time %d-%02d-%02d %02d:%02d:%02d.%03d\n",
  386. current->pid, sched_clock(), tm.tm_year + 1900, tm.tm_mon + 1,
  387. tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
  388. (unsigned int)tv.tv_usec, tm_android.tm_year + 1900,
  389. tm_android.tm_mon + 1, tm_android.tm_mday, tm_android.tm_hour,
  390. tm_android.tm_min, tm_android.tm_sec,
  391. (unsigned int)tv_android.tv_usec);
  392. }
  393. }
  394. msleep_interruptible((g_kinterval) * 1000);
  395. #ifdef CONFIG_MTK_AEE_POWERKEY_HANG_DETECT
  396. if ((cpu == 0) && (wk_tsk[cpu]->pid == current->pid)) { /* only effect at cpu0 */
  397. if (aee_kernel_wdt_kick_api(g_kinterval) == WDT_PWK_HANG_FORCE_HWT) {
  398. printk_deferred("power key trigger HWT\n");
  399. cpus_kick_bit = 0xFFFF; /* Try to force to HWT */
  400. }
  401. }
  402. #endif
  403. }
  404. pr_debug("[WDK] WDT kicker thread stop, cpu:%d, pid:%d\n", cpu, current->pid);
  405. return 0;
  406. }
  407. static int start_kicker(void)
  408. {
  409. int i;
  410. wk_cpu_update_bit_flag(0, 1);
  411. for (i = 0; i < CPU_NR; i++) {
  412. wk_tsk[i] = kthread_create(kwdt_thread, (void *)(unsigned long)i, "wdtk-%d", i);
  413. if (IS_ERR(wk_tsk[i])) {
  414. int ret = PTR_ERR(wk_tsk[i]);
  415. wk_tsk[i] = NULL;
  416. pr_alert("[WDK]kthread_create failed, wdtk-%d\n", i);
  417. return ret;
  418. }
  419. /* wk_cpu_update_bit_flag(i,1); */
  420. wk_start_kick_cpu(i);
  421. }
  422. g_kicker_init = 1;
  423. pr_alert("[WDK] WDT start kicker done CPU_NR=%d\n", CPU_NR);
  424. return 0;
  425. }
  426. unsigned int get_check_bit(void)
  427. {
  428. return wk_check_kick_bit();
  429. }
  430. unsigned int get_kick_bit(void)
  431. {
  432. return kick_bit;
  433. }
  434. /******************************************************************************
  435. * SYSFS support
  436. ******************************************************************************/
  437. #ifdef __ENABLE_WDT_SYSFS__
  438. /*---------------------------------------------------------------------------*/
  439. /*define sysfs entry for configuring debug level and sysrq*/
  440. const struct sysfs_ops mtk_rgu_sysfs_ops = {
  441. .show = mtk_rgu_attr_show,
  442. .store = mtk_rgu_attr_store,
  443. };
  444. /*---------------------------------------------------------------------------*/
  445. struct mtk_rgu_sys_entry {
  446. struct attribute attr;
  447. ssize_t (*show)(struct kobject *kobj, char *page);
  448. ssize_t (*store)(struct kobject *kobj, const char *page, size_t size);
  449. };
  450. /*---------------------------------------------------------------------------*/
  451. static struct mtk_rgu_sys_entry pause_wdt_entry = {
  452. {.name = "pause", .mode = S_IRUGO | S_IWUSR},
  453. mtk_rgu_pause_wdt_show,
  454. mtk_rgu_pause_wdt_store,
  455. };
  456. /*---------------------------------------------------------------------------*/
  457. struct attribute *mtk_rgu_attributes[] = {
  458. &pause_wdt_entry.attr,
  459. NULL,
  460. };
  461. /*---------------------------------------------------------------------------*/
  462. struct kobj_type mtk_rgu_ktype = {
  463. .sysfs_ops = &mtk_rgu_sysfs_ops,
  464. .default_attrs = mtk_rgu_attributes,
  465. };
  466. /*---------------------------------------------------------------------------*/
  467. static struct mtk_rgu_sysobj {
  468. struct kobject kobj;
  469. } rgu_sysobj;
  470. /*---------------------------------------------------------------------------*/
  471. int mtk_rgu_sysfs(void)
  472. {
  473. struct mtk_rgu_sysobj *obj = &rgu_sysobj;
  474. memset(&obj->kobj, 0x00, sizeof(obj->kobj));
  475. obj->kobj.parent = kernel_kobj;
  476. if (kobject_init_and_add(&obj->kobj, &mtk_rgu_ktype, NULL, "mtk_rgu")) {
  477. kobject_put(&obj->kobj);
  478. return -ENOMEM;
  479. }
  480. kobject_uevent(&obj->kobj, KOBJ_ADD);
  481. return 0;
  482. }
  483. /*---------------------------------------------------------------------------*/
  484. ssize_t mtk_rgu_attr_show(struct kobject *kobj, struct attribute *attr, char *buffer)
  485. {
  486. struct mtk_rgu_sys_entry *entry = container_of(attr, struct mtk_rgu_sys_entry, attr);
  487. return entry->show(kobj, buffer);
  488. }
  489. /*---------------------------------------------------------------------------*/
  490. ssize_t mtk_rgu_attr_store(struct kobject *kobj, struct attribute *attr, const char *buffer,
  491. size_t size)
  492. {
  493. struct mtk_rgu_sys_entry *entry = container_of(attr, struct mtk_rgu_sys_entry, attr);
  494. return entry->store(kobj, buffer, size);
  495. }
  496. /*---------------------------------------------------------------------------*/
  497. ssize_t mtk_rgu_pause_wdt_show(struct kobject *kobj, char *buffer)
  498. {
  499. int remain = PAGE_SIZE;
  500. int len = 0;
  501. char *ptr = buffer;
  502. ptr += len;
  503. remain -= len;
  504. return (PAGE_SIZE - remain);
  505. }
  506. /*---------------------------------------------------------------------------*/
  507. ssize_t mtk_rgu_pause_wdt_store(struct kobject *kobj, const char *buffer, size_t size)
  508. {
  509. char pause_wdt;
  510. int pause_wdt_b;
  511. int res = sscanf(buffer, "%c", &pause_wdt);
  512. pause_wdt_b = pause_wdt;
  513. if (res != 1) {
  514. pr_err("%s: expect 1 numbers\n", __func__);
  515. } else {
  516. /* For real case, pause wdt if get value is not zero. Suspend and resume may enable wdt again */
  517. if (pause_wdt_b)
  518. mtk_wdt_enable(WK_WDT_DIS);
  519. }
  520. return size;
  521. }
  522. /*---------------------------------------------------------------------------*/
  523. #endif /*__ENABLE_WDT_SYSFS__*/
  524. /*---------------------------------------------------------------------------*/
  525. static int __cpuinit wk_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
  526. {
  527. int hotcpu = (unsigned long)hcpu;
  528. switch (action) {
  529. case CPU_UP_PREPARE:
  530. case CPU_UP_PREPARE_FROZEN:
  531. /* watchdog_prepare_cpu(hotcpu); */
  532. wk_cpu_update_bit_flag(hotcpu, 1);
  533. break;
  534. case CPU_ONLINE:
  535. case CPU_ONLINE_FROZEN:
  536. /* wk_cpu_update_bit_flag(hotcpu, 1); */
  537. if (1 == g_kicker_init)
  538. kicker_cpu_bind(hotcpu);
  539. mtk_wdt_restart(WD_TYPE_NORMAL); /* for KICK external wdt */
  540. #ifdef CONFIG_LOCAL_WDT
  541. pr_debug("[WDK]cpu %d plug on kick local wdt\n", hotcpu);
  542. /* kick local wdt */
  543. mpcore_wdt_restart(WD_TYPE_NORMAL);
  544. #endif
  545. /* pr_alert("[WDK]cpu %d plug on kick wdt\n", hotcpu); */
  546. break;
  547. #ifdef CONFIG_HOTPLUG_CPU
  548. #ifdef CONFIG_LOCAL_WDT
  549. /* must kick local wdt in per cpu */
  550. case CPU_DYING:
  551. /* fall-through */
  552. #endif
  553. case CPU_UP_CANCELED:
  554. /* fall-through */
  555. case CPU_UP_CANCELED_FROZEN:
  556. /* fall-through */
  557. case CPU_DEAD:
  558. /* fall-through */
  559. case CPU_DEAD_FROZEN:
  560. mtk_wdt_restart(WD_TYPE_NORMAL); /* for KICK external wdt */
  561. #ifdef CONFIG_LOCAL_WDT
  562. pr_debug("[WDK]cpu %d plug off kick local wdt\n", hotcpu);
  563. /* kick local wdt */
  564. /* mpcore_wdt_restart(WD_TYPE_NORMAL); */
  565. /* disable local watchdog */
  566. mpcore_wk_wdt_stop();
  567. #endif
  568. wk_cpu_update_bit_flag(hotcpu, 0);
  569. /* pr_alert("[WDK]cpu %d plug off, kick wdt\n", hotcpu); */
  570. break;
  571. #endif /* CONFIG_HOTPLUG_CPU */
  572. default:
  573. return NOTIFY_DONE;
  574. }
  575. return NOTIFY_OK;
  576. }
  577. static struct notifier_block cpu_nfb __cpuinitdata = {
  578. .notifier_call = wk_cpu_callback,
  579. .priority = 6
  580. };
  581. static int __init init_wk(void)
  582. {
  583. int res = 0;
  584. int i = 0;
  585. /* init api */
  586. wd_api_init();
  587. /* */
  588. res = get_wd_api(&g_wd_api);
  589. if (res)
  590. pr_err("get public api error in wd common driver %d", res);
  591. #ifdef __ENABLE_WDT_SYSFS__
  592. mtk_rgu_sysfs();
  593. #endif
  594. cpu_hotplug_disable();
  595. #ifdef __ENABLE_WDT_AT_INIT__
  596. start_kicker_thread_with_default_setting();
  597. #endif
  598. wk_proc_init();
  599. register_cpu_notifier(&cpu_nfb);
  600. for (i = 0; i < CPU_NR; i++) {
  601. if (cpu_online(i)) {
  602. wk_cpu_update_bit_flag(i, 1);
  603. pr_debug("[WDK]init cpu online %d\n", i);
  604. } else {
  605. wk_cpu_update_bit_flag(i, 0);
  606. pr_debug("[WDK]init cpu offline %d\n", i);
  607. }
  608. }
  609. mtk_wdt_restart(WD_TYPE_NORMAL); /* for KICK external wdt */
  610. cpu_hotplug_enable();
  611. pr_alert("[WDK]init_wk done late_initcall cpus_kick_bit=0x%x -----\n", cpus_kick_bit);
  612. return 0;
  613. }
  614. static void __exit exit_wk(void)
  615. {
  616. wk_proc_exit();
  617. kthread_stop((struct task_struct *)wk_tsk);
  618. }
  619. static int __init init_wk_check_bit(void)
  620. {
  621. int i = 0;
  622. pr_debug("[WDK]arch init check_bit=0x%x+++++\n", cpus_kick_bit);
  623. for (i = 0; i < CPU_NR; i++)
  624. wk_cpu_update_bit_flag(i, 1);
  625. pr_debug("[WDK]arch init check_bit=0x%x-----\n", cpus_kick_bit);
  626. return 0;
  627. }
  628. /*********************************************************************************/
  629. late_initcall(init_wk);
  630. arch_initcall(init_wk_check_bit);
  631. MODULE_LICENSE("GPL");
  632. MODULE_AUTHOR("Mediatek inc.");
  633. MODULE_DESCRIPTION("The watchdog kicker");