import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / boot_reason / mt_boot_reason.c
1 #define pr_fmt(fmt) "["KBUILD_MODNAME"] " fmt
2 #include <linux/module.h>
3 #include <linux/device.h>
4 #include <linux/fs.h>
5 #include <linux/cdev.h>
6 #include <linux/interrupt.h>
7 #include <linux/spinlock.h>
8 #include <linux/uaccess.h>
9 #include <linux/mm.h>
10 #include <linux/kfifo.h>
11
12 #include <linux/firmware.h>
13 #include <linux/syscalls.h>
14 #include <linux/uaccess.h>
15 #include <linux/platform_device.h>
16 #include <linux/proc_fs.h>
17 #include <linux/seq_file.h>
18 #include <linux/of.h>
19 #ifdef CONFIG_OF
20 #include <linux/of_fdt.h>
21 #endif
22 #include <asm/setup.h>
23 #include <asm/atomic.h>
24 #include <mach/mt_typedefs.h>
25 #include <mach/mt_boot_reason.h>
26
27
28 typedef enum {
29 BOOT_REASON_UNINIT = 0,
30 BOOT_REASON_INITIALIZING = 1,
31 BOOT_REASON_INITIALIZED = 2,
32 } BOOT_REASON_STATE;
33
34 boot_reason_t g_boot_reason __nosavedata = BR_UNKNOWN;
35
36 static atomic_t g_br_state = ATOMIC_INIT(BOOT_REASON_UNINIT);
37 static atomic_t g_br_errcnt = ATOMIC_INIT(0);
38 static atomic_t g_br_status = ATOMIC_INIT(0);
39
40 #ifdef CONFIG_OF
41 static int __init dt_get_boot_reason(unsigned long node, const char *uname, int depth, void *data)
42 {
43 char *ptr = NULL, *br_ptr = NULL;
44
45 if (depth != 1 || (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
46 return 0;
47
48 ptr = (char *)of_get_flat_dt_prop(node, "bootargs", NULL);
49 if (ptr) {
50 if ((br_ptr = strstr(ptr, "boot_reason=")) != 0) {
51 g_boot_reason = br_ptr[12] - '0'; /* get boot reason */
52 atomic_set(&g_br_status, 1);
53 }
54 else
55 pr_warn("'boot_reason=' is not found\n");
56 pr_debug("%s\n", ptr);
57 } else
58 pr_warn("'bootargs' is not found\n");
59
60 /* break now */
61 return 1;
62 }
63 #endif
64
65
66 void init_boot_reason(unsigned int line)
67 {
68 #ifdef CONFIG_OF
69 int rc;
70
71 if (BOOT_REASON_INITIALIZING == atomic_read(&g_br_state)) {
72 pr_warn("%s (%d) state(%d)\n", __func__, line, atomic_read(&g_br_state));
73 atomic_inc(&g_br_errcnt);
74 return;
75 }
76
77 if (BOOT_REASON_UNINIT == atomic_read(&g_br_state))
78 atomic_set(&g_br_state, BOOT_REASON_INITIALIZING);
79 else
80 return;
81
82 if ((BR_UNKNOWN != g_boot_reason)) {
83 atomic_set(&g_br_state, BOOT_REASON_INITIALIZED);
84 pr_alert("boot_reason = %d\n", g_boot_reason);
85 return;
86 }
87
88 pr_info("%s %d %d %d\n", __func__, line, g_boot_reason,
89 atomic_read(&g_br_state));
90 rc = of_scan_flat_dt(dt_get_boot_reason, NULL);
91 if (0 != rc)
92 atomic_set(&g_br_state, BOOT_REASON_INITIALIZED);
93 else
94 atomic_set(&g_br_state, BOOT_REASON_UNINIT);
95 pr_info("%s %d %d %d\n", __func__, line, g_boot_reason,
96 atomic_read(&g_br_state));
97 #endif
98 }
99
100 /* return boot reason */
101 boot_reason_t get_boot_reason(void)
102 {
103 init_boot_reason(__LINE__);
104 return g_boot_reason;
105 }
106
107 static int __init boot_reason_core(void)
108 {
109 init_boot_reason(__LINE__);
110 return 0;
111 }
112
113 static int __init boot_reason_init(void)
114 {
115 pr_alert("boot_reason = %d, state(%d,%d,%d)", g_boot_reason,
116 atomic_read(&g_br_state), atomic_read(&g_br_errcnt),
117 atomic_read(&g_br_status));
118 return 0;
119 }
120
121 early_initcall(boot_reason_core);
122 module_init(boot_reason_init);
123 MODULE_DESCRIPTION("Mediatek Boot Reason Driver");
124 MODULE_LICENSE("GPL");