#include #include #include #include #include #include #include /* charger cable state */ extern bool is_cable_attached; #ifdef CONFIG_MACH_U1_NA_SPR static void cdma_wimax_chk_modem_pwroff(void); #endif 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) { #ifdef CONFIG_MACH_U1_NA_SPR cdma_wimax_chk_modem_pwroff(); #endif /* 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 #ifdef CONFIG_MACH_U1_NA_SPR static void cdma_wimax_chk_modem_pwroff(void) { int phone_wait_cnt = 0; pr_emerg("%s\n", __func__); /* phone power off */ gpio_direction_output(GPIO_QSC_PHONE_ON, GPIO_LEVEL_LOW); /* confirm phone off */ while (1) { if (gpio_get_value(GPIO_QSC_PHONE_ACTIVE)) { printk(KERN_ALERT"Try to Turn Phone Off by CP_RST\n"); gpio_set_value(GPIO_QSC_PHONE_RST, 0); if (phone_wait_cnt > 10) { pr_emerg("%s: PHONE OFF Failed\n", __func__); break; } phone_wait_cnt++; mdelay(100); } else { pr_emerg("%s: PHONE OFF Success\n", __func__); break; } } } #endif 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, "bootloader")) writel(REBOOT_MODE_PREFIX | REBOOT_MODE_DOWNLOAD, 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 if (!strncmp(cmd, "emergency", 9)) writel(0, 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);