kernel_samsung_a34x-permissive/drivers/samsung/sec_reboot.c
2024-04-28 15:49:01 +02:00

185 lines
5.6 KiB
C
Executable file

/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#define DEBUG 1
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/input.h>
#include <asm/cacheflush.h>
#include <asm/system_misc.h>
#include <linux/power_supply.h>
#include <linux/sec_debug.h>
#if defined(CONFIG_SEC_ABC)
#include <linux/sti/abc_common.h>
#endif
/* function ptr for original arm_pm_restart */
void (*mach_power_off)(void);
EXPORT_SYMBOL(mach_power_off);
void (*mach_restart)(enum reboot_mode mode, const char *cmd);
EXPORT_SYMBOL(mach_restart);
#define psy_get_property(psy, property, value) \
{ \
int ret; \
if (!psy) { \
pr_err("%s: Fail to get "#psy" psy\n", __func__); \
value.intval = 0; \
} else { \
if (psy->desc->get_property != NULL) { \
ret = psy->desc->get_property(psy, (property), &(value)); \
if (ret < 0) { \
pr_err("%s: Fail to get property of "#psy" (%d=>%d)\n", \
__func__, (property), ret); \
value.intval = 0; \
} \
} \
} \
}
#if defined(CONFIG_SEC_DUMP_SINK)
void sec_set_reboot_magic(int magic)
{
int tmp;
tmp = LAST_RR_VAL(reboot_magic);
pr_info("%s: prev: %x\n", __func__, tmp);
tmp = magic;
pr_info("%s: set as: %x\n", __func__, tmp);
LAST_RR_SET(reboot_magic, tmp);
}
#endif
extern int mtk_pmic_pwrkey_status(void);
static void sec_power_off(void)
{
int pressed;
union power_supply_propval ac_val = {0, }, usb_val = {0, }, wc_val = {0, };
struct power_supply *ac_psy = power_supply_get_by_name("ac");
struct power_supply *usb_psy = power_supply_get_by_name("usb");
struct power_supply *wc_psy = power_supply_get_by_name("wireless");
psy_get_property(ac_psy, POWER_SUPPLY_PROP_ONLINE, ac_val);
psy_get_property(usb_psy, POWER_SUPPLY_PROP_ONLINE, usb_val);
psy_get_property(wc_psy, POWER_SUPPLY_PROP_ONLINE, wc_val);
pr_info("[%s] AC[%d] : USB[%d] : WC[%d]\n", __func__,
ac_val.intval, usb_val.intval, wc_val.intval);
/* This is NOT upload case */
LAST_RR_SET(is_upload, UPLOAD_MAGIC_NORMAL);
pr_emerg("%s: waiting for reboot\n", __func__);
__inner_flush_dcache_all();
while (1) {
/* wait for power button release */
pressed = mtk_pmic_pwrkey_status();
if (!pressed) {
pr_info("%s: PowerButton was released(%d)\n", __func__, pressed);
mach_power_off();
} else {
/* if power button is not released, wait and check TA again */
pr_info("%s: PowerButton wasn't released(%d)\n", __func__, pressed);
}
mdelay(1000);
}
}
static void sec_reboot(enum reboot_mode reboot_mode, const char *cmd)
{
local_irq_disable();
pr_emerg("%s (%d, %s)\n", __func__, reboot_mode, cmd ? cmd : "(null)");
/* LPM mode prevention */
LAST_RR_SET(is_power_reset, SEC_POWER_RESET);
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_UNKNOWN);
if (cmd) {
unsigned long value;
if (!strcmp(cmd, "recovery-update"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_FOTA);
else if (!strcmp(cmd, "fota_bl"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_FOTA_BL);
else if (!strcmp(cmd, "recovery"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_RECOVERY);
else if (!strcmp(cmd, "download"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_DOWNLOAD);
else if (!strcmp(cmd, "bootloader"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_BOOTLOADER);
else if (!strcmp(cmd, "upload"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_UPLOAD);
else if (!strcmp(cmd, "secure"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_SECURE);
else if (!strcmp(cmd, "fwup"))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_FWUP);
#if defined(CONFIG_SEC_ABC)
else if (!strncmp(cmd, "user_dram_test", 14) && sec_abc_get_enabled())
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_USER_DRAM_TEST);
#endif
else if (!strncmp(cmd, "emergency", 9))
LAST_RR_SET(power_reset_reason, SEC_RESET_REASON_EMERGENCY);
else if (!strncmp(cmd, "debug", 5)
&& !kstrtoul(cmd + 5, 0, &value))
LAST_RR_SET(power_reset_reason, SEC_RESET_SET_DEBUG | value);
#if defined(CONFIG_SEC_DUMP_SINK)
else if (!strncmp(cmd, "dump_sink", 9) && !kstrtoul(cmd + 9, 0, &value))
LAST_RR_SET(power_reset_reason, SEC_RESET_SET_DUMPSINK | (SEC_DUMPSINK_MASK & value));
#endif
else if (!strncmp(cmd, "swsel", 5)
&& !kstrtoul(cmd + 5, 0, &value))
LAST_RR_SET(power_reset_reason, SEC_RESET_SET_SWSEL | value);
else if (!strncmp(cmd, "sud", 3)
&& !kstrtoul(cmd + 3, 0, &value))
LAST_RR_SET(power_reset_reason, SEC_RESET_SET_SUD | value);
else if (!strncmp(cmd, "cpmem_on", 8))
LAST_RR_SET(power_reset_reason, SEC_RESET_CP_DBGMEM | 0x1);
else if (!strncmp(cmd, "cpmem_off", 9))
LAST_RR_SET(power_reset_reason, SEC_RESET_CP_DBGMEM | 0x2);
#ifdef CONFIG_SEC_DEBUG_MDM_SEPERATE_CRASH
else if (!strncmp(cmd, "cpdebug", 7)
&& !kstrtoul(cmd + 7, 0, &value))
LAST_RR_SET(power_reset_reason, SEC_RESET_SET_CP_DEBUG | value);
#endif
#ifdef CONFIG_DIAG_MODE
else if (!strncmp(cmd, "diag", 4)
&& !kstrtoul(cmd + 4, 0, &value))
LAST_RR_SET(power_reset_reason, SEC_RESET_SET_DIAG | (value & 0x1));
#endif
}
/* This is NOT upload case */
LAST_RR_SET(is_upload, UPLOAD_MAGIC_NORMAL);
pr_emerg("%s: waiting for reboot\n", __func__);
__inner_flush_dcache_all();
mach_restart(REBOOT_COLD, "hw reset");
while (1);
}
static int __init sec_reboot_init(void)
{
mach_restart = arm_pm_restart;
mach_power_off = pm_power_off;
pm_power_off = sec_power_off;
arm_pm_restart = sec_reboot;
return 0;
}
subsys_initcall(sec_reboot_init);