aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/sec-reboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/sec-reboot.c')
-rw-r--r--arch/arm/mach-exynos/sec-reboot.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/sec-reboot.c b/arch/arm/mach-exynos/sec-reboot.c
new file mode 100644
index 0000000..075f107
--- /dev/null
+++ b/arch/arm/mach-exynos/sec-reboot.c
@@ -0,0 +1,133 @@
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <mach/system.h>
+#include <mach/regs-pmu.h>
+#include <mach/gpio.h>
+
+/* charger cable state */
+extern bool is_cable_attached;
+static void sec_power_off(void)
+{
+ int poweroff_try = 0;
+
+ local_irq_disable();
+
+ pr_emerg("%s : cable state=%d\n", __func__, is_cable_attached);
+
+ while (1) {
+ /* Check reboot charging */
+ if (is_cable_attached || (poweroff_try >= 5)) {
+ pr_emerg
+ ("%s: charger connected(%d) or power"
+ "off failed(%d), reboot!\n",
+ __func__, is_cable_attached, poweroff_try);
+ writel(0x0, S5P_INFORM2); /* To enter LP charging */
+
+ flush_cache_all();
+ outer_flush_all();
+ arch_reset(0, 0);
+
+ pr_emerg("%s: waiting for reboot\n", __func__);
+ while (1);
+ }
+
+ /* wait for power button release */
+ if (gpio_get_value(GPIO_nPOWER)) {
+ pr_emerg("%s: set PS_HOLD low\n", __func__);
+
+ /* power off code
+ * PS_HOLD Out/High -->
+ * Low PS_HOLD_CONTROL, R/W, 0x1002_330C
+ */
+ writel(readl(S5P_PS_HOLD_CONTROL) & 0xFFFFFEFF,
+ S5P_PS_HOLD_CONTROL);
+
+ ++poweroff_try;
+ pr_emerg
+ ("%s: Should not reach here! (poweroff_try:%d)\n",
+ __func__, poweroff_try);
+ } else {
+ /* if power button is not released, wait and check TA again */
+ pr_info("%s: PowerButton is not released.\n", __func__);
+ }
+ mdelay(1000);
+ }
+}
+
+#define REBOOT_MODE_PREFIX 0x12345670
+#define REBOOT_MODE_NONE 0
+#define REBOOT_MODE_DOWNLOAD 1
+#define REBOOT_MODE_UPLOAD 2
+#define REBOOT_MODE_CHARGING 3
+#define REBOOT_MODE_RECOVERY 4
+#define REBOOT_MODE_FOTA 5
+#define REBOOT_MODE_FOTA_BL 6 /* update bootloader */
+
+#define REBOOT_SET_PREFIX 0xabc00000
+#define REBOOT_SET_DEBUG 0x000d0000
+#define REBOOT_SET_SWSEL 0x000e0000
+#define REBOOT_SET_SUD 0x000f0000
+
+static void sec_reboot(char str, const char *cmd)
+{
+ local_irq_disable();
+
+ pr_emerg("%s (%d, %s)\n", __func__, str, cmd ? cmd : "(null)");
+
+ writel(0x12345678, S5P_INFORM2); /* Don't enter lpm mode */
+
+ if (!cmd) {
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_NONE, S5P_INFORM3);
+ } else {
+ unsigned long value;
+ if (!strcmp(cmd, "fota"))
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_FOTA,
+ S5P_INFORM3);
+ else if (!strcmp(cmd, "fota_bl"))
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_FOTA_BL,
+ S5P_INFORM3);
+ else if (!strcmp(cmd, "recovery"))
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_RECOVERY,
+ S5P_INFORM3);
+ else if (!strcmp(cmd, "download"))
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_DOWNLOAD,
+ S5P_INFORM3);
+ else if (!strcmp(cmd, "upload"))
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_UPLOAD,
+ S5P_INFORM3);
+ else if (!strncmp(cmd, "debug", 5)
+ && !kstrtoul(cmd + 5, 0, &value))
+ writel(REBOOT_SET_PREFIX | REBOOT_SET_DEBUG | value,
+ S5P_INFORM3);
+ else if (!strncmp(cmd, "swsel", 5)
+ && !kstrtoul(cmd + 5, 0, &value))
+ writel(REBOOT_SET_PREFIX | REBOOT_SET_SWSEL | value,
+ S5P_INFORM3);
+ else if (!strncmp(cmd, "sud", 3)
+ && !kstrtoul(cmd + 3, 0, &value))
+ writel(REBOOT_SET_PREFIX | REBOOT_SET_SUD | value,
+ S5P_INFORM3);
+ else
+ writel(REBOOT_MODE_PREFIX | REBOOT_MODE_NONE,
+ S5P_INFORM3);
+ }
+
+ flush_cache_all();
+ outer_flush_all();
+ arch_reset(0, 0);
+
+ pr_emerg("%s: waiting for reboot\n", __func__);
+ while (1);
+}
+
+static int __init sec_reboot_init(void)
+{
+ /* to support system shut down */
+ pm_power_off = sec_power_off;
+ arm_pm_restart = sec_reboot;
+ return 0;
+}
+
+subsys_initcall(sec_reboot_init);