diff --git a/drivers/power/reset/qcom-dload-mode.c b/drivers/power/reset/qcom-dload-mode.c index 8af5318d526f..6ac8a8c051a1 100644 --- a/drivers/power/reset/qcom-dload-mode.c +++ b/drivers/power/reset/qcom-dload-mode.c @@ -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 int set_download_mode(enum qcom_download_mode mode) { @@ -264,10 +264,8 @@ static int qcom_dload_reboot(struct notifier_block *this, unsigned long event, set_download_mode(QCOM_DOWNLOAD_NODUMP); if (cmd) { - if (!strcmp(cmd, "edl")) - set_download_mode(QCOM_DOWNLOAD_EDL); - else if (!strcmp(cmd, "qcom_dload")) - msm_enable_dump_mode(true); + if (!strcmp(cmd, "qcom_dload")) + msm_enable_dump_mode(true); } if (current_download_mode != QCOM_DOWNLOAD_NODUMP) diff --git a/drivers/power/reset/qcom-reboot-reason.c b/drivers/power/reset/qcom-reboot-reason.c index 483e974121fc..bd83d5bbb7bf 100644 --- a/drivers/power/reset/qcom-reboot-reason.c +++ b/drivers/power/reset/qcom-reboot-reason.c @@ -17,6 +17,7 @@ struct qcom_reboot_reason { struct device *dev; struct notifier_block reboot_nb; + struct notifier_block panic_nb; struct nvmem_cell *nvmem_cell; }; @@ -32,9 +33,52 @@ static struct poweroff_reason reasons[] = { { "dm-verity device corrupted", 0x04 }, { "dm-verity enforcing", 0x05 }, { "keys clear", 0x06 }, + { "ffu", 0x41 }, + { "panic", 0x21 }, + { NULL, 0x20 }, {} }; +#define RESTART_REASON_PANIC 7 +#define RESTART_REASON_NORMAL 8 + +static struct qcom_reboot_reason *ffu_reboot = NULL; + +int ufs_ffu_reboot_reason_reboot(void *ptr) +{ + char *cmd = ptr; + struct qcom_reboot_reason *reboot; + struct poweroff_reason *reason; + + if(!ffu_reboot) + return NOTIFY_BAD; + + reboot = ffu_reboot; + + 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)); + return NOTIFY_OK; + } + } + + nvmem_cell_write(reboot->nvmem_cell, + &reason->pon_reason, + sizeof(reason->pon_reason)); + + return NOTIFY_OK; +} +EXPORT_SYMBOL(ufs_ffu_reboot_reason_reboot); + static int qcom_reboot_reason_reboot(struct notifier_block *this, unsigned long event, void *ptr) { @@ -43,20 +87,38 @@ 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; } +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 +140,12 @@ 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); + + ffu_reboot = reboot; + return 0; } @@ -85,6 +153,7 @@ 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); return 0;