f7cb952bd06dcca671c109ede9df5a6c2a21994b
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / platform / sprd / sec-reboot.c
1 #include <linux/delay.h>
2 #include <linux/pm.h>
3 #include <asm/io.h>
4 #include <mach/io.h>
5 #include <asm/cacheflush.h>
6 #include <soc/sprd/system.h>
7 #include <linux/notifier.h>
8 #include <linux/reboot.h>
9 #include <mach/gpio.h>
10 #include <soc/sprd/sec_debug.h>
11
12 #if 0 /* should be fixed later */
13 /* charger cable state */
14 extern bool is_cable_attached;
15
16 static void sec_power_off(void)
17 {
18         int poweroff_try = 0;
19
20         local_irq_disable();
21
22         pr_emerg("%s : cable state=%d\n", __func__, is_cable_attached);
23         flush_cache_all();
24         outer_flush_all();
25
26         while (1) {
27                 /* Check reboot charging */
28                 if (is_cable_attached || (poweroff_try >= 5)) {
29                         pr_emerg
30                             ("%s: charger connected(%d) or power"
31                              "off failed(%d), reboot!\n",
32                              __func__, is_cable_attached, poweroff_try);
33                         writel(0x0, (void __iomem *)S5P_INFORM2);       /* To enter LP charging */
34
35                         flush_cache_all();
36                         outer_flush_all();
37                         arch_reset(0, 0);
38
39                         pr_emerg("%s: waiting for reboot\n", __func__);
40                         while (1);
41                 }
42
43                 /* wait for power button release */
44                 if (gpio_get_value(GPIO_nPOWER)) {
45                         pr_emerg("%s: set PS_HOLD low\n", __func__);
46
47                         /* power off code
48                          * PS_HOLD Out/High -->
49                          * Low PS_HOLD_CONTROL, R/W, 0x1002_330C
50                          */
51                         writel(readl(S5P_PS_HOLD_CONTROL) & 0xFFFFFEFF,
52                                (void __iomem *)S5P_PS_HOLD_CONTROL);
53
54                         ++poweroff_try;
55                         pr_emerg
56                             ("%s: Should not reach here! (poweroff_try:%d)\n",
57                              __func__, poweroff_try);
58                 } else {
59                         /* if power button is not released, wait and check TA again */
60                         pr_info("%s: PowerButton is not released.\n", __func__);
61                 }
62                 mdelay(1000);
63         }
64 }
65
66 #endif  /* should be fixed later */
67
68 #define REBOOT_MODE_PREFIX      0x12345670
69 #define REBOOT_MODE_NONE                0
70 #define REBOOT_MODE_DOWNLOAD    1
71 #define REBOOT_MODE_UPLOAD              2
72 #define REBOOT_MODE_CHARGING    3
73 #define REBOOT_MODE_RECOVERY    4
74 #define REBOOT_MODE_FOTA                5
75 #define REBOOT_MODE_FOTA_BL             6
76 #define REBOOT_MODE_NORMAL              8
77 #define REBOOT_MODE_FUS_RW              9
78 #define REBOOT_MODE_SILENT              0xA
79
80 #define REBOOT_SET_PREFIX       0xabc00000
81 #define REBOOT_SET_DEBUG        0x000d0000
82 #define REBOOT_SET_SWSEL        0x000e0000
83 #define REBOOT_SET_SUD          0x000f0000
84
85 //extern int sec_debug_level(void);
86
87 static int sec_reboot_notifier(struct notifier_block *nb,
88                                                         unsigned long l, void *buf)
89 {
90         unsigned long value;
91         char *cmd = buf;
92
93
94         pr_emerg("%s (%lu, %s)\n", __func__, l, cmd ? cmd : "(null)");
95
96         writel(0x12345678,(void __iomem *)SPRD_INFORM2);        /* Don't enter lpm mode */
97
98         if (!cmd) {
99                 writel(REBOOT_MODE_PREFIX | REBOOT_MODE_NONE, (void __iomem *)SPRD_INFORM3);
100         } else {
101                 if (!strcmp(cmd, "fota"))
102                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_FOTA,
103                                (void __iomem *)SPRD_INFORM3);
104                 else if (!strcmp(cmd, "fota_bl"))
105                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_FOTA_BL,
106                                (void __iomem *)SPRD_INFORM3);
107                 else if (!strcmp(cmd, "recovery"))
108                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_RECOVERY,
109                                (void __iomem *)SPRD_INFORM3);
110                 else if (!strcmp(cmd, "download"))
111                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_DOWNLOAD,
112                                (void __iomem *)SPRD_INFORM3);
113                 else if (!strcmp(cmd, "upload"))
114                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_UPLOAD,
115                                (void __iomem *)SPRD_INFORM3);
116                 else if (!strcmp(cmd, "silent"))
117                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_SILENT,
118                                (void __iomem *)SPRD_INFORM3);
119                 else if (!strncmp(cmd, "debug", 5)
120                          && !kstrtoul(cmd + 5, 0, &value))
121                         writel(REBOOT_SET_PREFIX | REBOOT_SET_DEBUG | value,
122                                (void __iomem *)SPRD_INFORM3);
123                 else if (!strncmp(cmd, "swsel", 5)
124                          && !kstrtoul(cmd + 5, 0, &value))
125                         writel(REBOOT_SET_PREFIX | REBOOT_SET_SWSEL | value,
126                                (void __iomem *)SPRD_INFORM3);
127                 else if (!strncmp(cmd, "sud", 3)
128                          && !kstrtoul(cmd + 3, 0, &value))
129                         writel(REBOOT_SET_PREFIX | REBOOT_SET_SUD | value,
130                                (void __iomem *)SPRD_INFORM3);
131                 else
132                         writel(REBOOT_MODE_PREFIX | REBOOT_MODE_NONE,
133                                (void __iomem *)SPRD_INFORM3);
134         }
135         flush_cache_all();
136         return NOTIFY_DONE;
137
138 }
139
140 static struct notifier_block nb_sec_reboot_block = {
141         .notifier_call = sec_reboot_notifier
142 };
143 static int __init sec_reboot_init(void)
144 {
145         /* to support system shut down */
146         register_reboot_notifier(&nb_sec_reboot_block);
147         return 0;
148 }
149
150 subsys_initcall(sec_reboot_init);
151