power: reset: Import xiaomi changes

[ItsVixano: Skip `qcom_dload_restart` func changes, due to commit
52c3eb6f12]

Change-Id: I7b70bf2dcace33a063fb060b6108287765afc147
This commit is contained in:
Arian 2022-01-06 23:33:25 +00:00 committed by Giovanni Ricca
parent 9ef32b7651
commit 8fa6995f56
No known key found for this signature in database
4 changed files with 118 additions and 12 deletions

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
* Copyright (C) 2021 XiaoMi, Inc.
*/
#include <linux/delay.h>
@ -60,8 +61,8 @@ static struct nvmem_cell *nvmem_cell;
static int download_mode = 1;
static struct kobject dload_kobj;
static int in_panic;
static int dload_type = SCM_DLOAD_FULLDUMP;
static int in_panic = 0;
static int dload_type = SCM_DLOAD_BOTHDUMPS;
static void *dload_mode_addr;
static bool dload_mode_enabled;
static void *emergency_dload_mode_addr;
@ -431,7 +432,10 @@ static void msm_restart_prepare(const char *cmd)
else
qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET);
if (cmd != NULL) {
if (in_panic) {
reason = PON_RESTART_REASON_PANIC;
}
else if (cmd != NULL) {
if (!strncmp(cmd, "bootloader", 10)) {
reason = PON_RESTART_REASON_BOOTLOADER;
__raw_writel(0x77665500, restart_reason);
@ -461,15 +465,19 @@ static void msm_restart_prepare(const char *cmd)
} else if (!strncmp(cmd, "edl", 3)) {
enable_emergency_dload_mode();
} else {
reason = PON_RESTART_REASON_NORMAL;
__raw_writel(0x77665501, restart_reason);
}
if (reason && nvmem_cell)
nvmem_cell_write(nvmem_cell, &reason, sizeof(reason));
else
qpnp_pon_set_restart_reason(
(enum pon_restart_reason)reason);
} else {
reason = PON_RESTART_REASON_NORMAL;
__raw_writel(0x77665501, restart_reason);
}
if (reason && nvmem_cell)
nvmem_cell_write(nvmem_cell, &reason, sizeof(reason));
else
qpnp_pon_set_restart_reason(
(enum pon_restart_reason)reason);
/*outer_flush_all is not supported by 64bit kernel*/
#ifndef CONFIG_ARM64

View File

@ -38,7 +38,7 @@ struct qcom_dload {
static bool enable_dump =
IS_ENABLED(CONFIG_POWER_RESET_QCOM_DOWNLOAD_MODE_DEFAULT);
static enum qcom_download_mode current_download_mode = QCOM_DOWNLOAD_NODUMP;
static enum qcom_download_mode dump_mode = QCOM_DOWNLOAD_FULLDUMP;
static enum qcom_download_mode dump_mode = QCOM_DOWNLOAD_BOTHDUMP;
static bool early_pcie_init_enable;
static int set_download_mode(enum qcom_download_mode mode)
@ -328,6 +328,26 @@ static void check_pci_edl(struct device_node *np)
iounmap(mem);
}
#define DISPLAY_CONFIG_OFFSET_PROP "qcom,msm-imem-display_config_offset"
/*
** set display config imem first 4 bytes to 0xdead4ead, because imem context
** will not lost when warm reset. if panic, xbl ramdump will display orange
** screen, and framebuffer addr is determined by these four bytes in
** MDP_GetDisplayBootConfig function. so set these four bytes to a invalid
** value and let the framebuffer of orange screen use
** RAMDUMP_FRAME_BUFFER_ADDRESS(0xE1000000)
**/
static void clear_display_config(void)
{
void *display_config_imem_addr = map_prop_mem(DISPLAY_CONFIG_OFFSET_PROP);
if (display_config_imem_addr) {
__raw_writel(0xdead4ead, display_config_imem_addr);
iounmap(display_config_imem_addr);
pr_err("%s clear display config\n", __func__);
}
}
static int qcom_dload_probe(struct platform_device *pdev)
{
struct qcom_dload *poweroff;
@ -358,6 +378,7 @@ static int qcom_dload_probe(struct platform_device *pdev)
poweroff->dload_dest_addr = map_prop_mem("qcom,msm-imem-dload-type");
store_kaslr_offset();
check_pci_edl(pdev->dev.of_node);
clear_display_config();
msm_enable_dump_mode(enable_dump);
if (!enable_dump)

View File

@ -17,6 +17,8 @@
struct qcom_reboot_reason {
struct device *dev;
struct notifier_block reboot_nb;
struct notifier_block panic_nb;
struct notifier_block restart_nb;
struct nvmem_cell *nvmem_cell;
};
@ -32,9 +34,19 @@ static struct poweroff_reason reasons[] = {
{ "dm-verity device corrupted", 0x04 },
{ "dm-verity enforcing", 0x05 },
{ "keys clear", 0x06 },
{ "panic", 0x21 },
{ NULL, 0x20 },
{}
};
static struct poweroff_reason restart_reasons[] = {
{ "lp_kthread", 0x28 },
{ NULL, 0x00 }, //end loop flag, not reset reason
};
#define RESTART_REASON_PANIC 6
#define RESTART_REASON_NORMAL 7
static int qcom_reboot_reason_reboot(struct notifier_block *this,
unsigned long event, void *ptr)
{
@ -43,20 +55,67 @@ static int qcom_reboot_reason_reboot(struct notifier_block *this,
struct qcom_reboot_reason, reboot_nb);
struct poweroff_reason *reason;
if (!cmd)
if (!cmd) {
nvmem_cell_write(reboot->nvmem_cell,
&reasons[RESTART_REASON_NORMAL].pon_reason,
sizeof(reasons[RESTART_REASON_NORMAL].pon_reason));
return NOTIFY_OK;
}
for (reason = reasons; reason->cmd; reason++) {
if (!strcmp(cmd, reason->cmd)) {
nvmem_cell_write(reboot->nvmem_cell,
&reason->pon_reason,
sizeof(reason->pon_reason));
break;
return NOTIFY_OK;
}
}
nvmem_cell_write(reboot->nvmem_cell,
&reason->pon_reason,
sizeof(reason->pon_reason));
return NOTIFY_OK;
}
/*
* this function only used in restart chain for limited reset reasons
* eg: long press power key kthread, because it cannot trigger
* reboot chain to set reset reason
*/
static int qcom_restart_reason_reboot(struct notifier_block *this,
unsigned long event, void *ptr)
{
char *cmd = ptr;
struct qcom_reboot_reason *reboot = container_of(this,
struct qcom_reboot_reason, restart_nb);
struct poweroff_reason *reason;
if (!cmd) {
return NOTIFY_OK;
}
for (reason = restart_reasons; reason->cmd; reason++) {
if (!strcmp(cmd, reason->cmd)) {
nvmem_cell_write(reboot->nvmem_cell,
&reason->pon_reason,
sizeof(reason->pon_reason));
pr_info("restart reason: %s\n", cmd);
return NOTIFY_OK;
}
}
return NOTIFY_OK;
}
static int panic_prep_restart(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct qcom_reboot_reason *reboot = container_of(this,
struct qcom_reboot_reason, panic_nb);
nvmem_cell_write(reboot->nvmem_cell,
&reasons[RESTART_REASON_PANIC].pon_reason,
sizeof(reasons[RESTART_REASON_PANIC].pon_reason));
return NOTIFY_DONE;
}
static int qcom_reboot_reason_probe(struct platform_device *pdev)
{
struct qcom_reboot_reason *reboot;
@ -78,6 +137,15 @@ static int qcom_reboot_reason_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, reboot);
reboot->panic_nb.notifier_call = panic_prep_restart;
reboot->panic_nb.priority = INT_MAX;
atomic_notifier_chain_register(&panic_notifier_list, &reboot->panic_nb);
/*register restart chain for set restart reason*/
reboot->restart_nb.notifier_call = qcom_restart_reason_reboot;
reboot->restart_nb.priority = 200;
register_restart_handler(&reboot->restart_nb);
return 0;
}
@ -85,8 +153,9 @@ static int qcom_reboot_reason_remove(struct platform_device *pdev)
{
struct qcom_reboot_reason *reboot = platform_get_drvdata(pdev);
atomic_notifier_chain_unregister(&panic_notifier_list, &reboot->panic_nb);
unregister_reboot_notifier(&reboot->reboot_nb);
unregister_restart_handler(&reboot->restart_nb);
return 0;
}

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2012-2015, 2017-2019, The Linux Foundation.
* Copyright (C) 2021 XiaoMi, Inc.
* All rights reserved.
*/
@ -55,6 +56,8 @@ enum pon_restart_reason {
PON_RESTART_REASON_DMVERITY_CORRUPTED = 0x04,
PON_RESTART_REASON_DMVERITY_ENFORCE = 0x05,
PON_RESTART_REASON_KEYS_CLEAR = 0x06,
PON_RESTART_REASON_NORMAL = 0x20,
PON_RESTART_REASON_PANIC = 0x21,
};
#if IS_ENABLED(CONFIG_INPUT_QPNP_POWER_ON)
@ -106,4 +109,9 @@ static inline int qpnp_pon_modem_pwr_off(enum pon_power_off_type type)
#endif
#ifdef CONFIG_MTD_BLOCK2MTD
extern struct Scsi_Host *g_shost;
extern void machine_restart(char *cmd);
#endif
#endif