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