Currently on Qualcomm SoC, download_mode is enabled if CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is selected. Refactor the code such that it supports multiple download modes and drop CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT config instead, give interface to set the download mode from module parameter. Signed-off-by: Mukesh Ojha <quic_mojha@xxxxxxxxxxx> --- drivers/firmware/Kconfig | 11 --------- drivers/firmware/qcom_scm.c | 56 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index b59e3041fd62..ff7e9f330559 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -215,17 +215,6 @@ config MTK_ADSP_IPC config QCOM_SCM tristate -config QCOM_SCM_DOWNLOAD_MODE_DEFAULT - bool "Qualcomm download mode enabled by default" - depends on QCOM_SCM - help - A device with "download mode" enabled will upon an unexpected - warm-restart enter a special debug mode that allows the user to - "download" memory content over USB for offline postmortem analysis. - The feature can be enabled/disabled on the kernel command line. - - Say Y here to enable "download mode" by default. - config SYSFB bool select BOOT_VESA_SUPPORT diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index eda92f713019..689bf882cb69 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -20,13 +20,13 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/clk.h> +#include <linux/kstrtox.h> #include <linux/reset-controller.h> #include <linux/arm-smccc.h> #include "qcom_scm.h" -static bool download_mode = IS_ENABLED(CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT); -module_param(download_mode, bool, 0); +static u32 download_mode; #define SCM_HAS_CORE_CLK BIT(0) #define SCM_HAS_IFACE_CLK BIT(1) @@ -83,6 +83,11 @@ static const char * const qcom_scm_convention_names[] = { [SMC_CONVENTION_LEGACY] = "smc legacy", }; +static const char * const download_mode_name[] = { + [QCOM_DLOAD_NODUMP] = "off", + [QCOM_DLOAD_FULLDUMP] = "full", +}; + static struct qcom_scm *__scm; static DEFINE_SPINLOCK(lock); @@ -448,9 +453,10 @@ static int __qcom_scm_set_dload_mode(struct device *dev, bool enable) return qcom_scm_call_atomic(__scm->dev, &desc, NULL); } -static void qcom_scm_set_download_mode(bool enable) +static void qcom_scm_set_download_mode(u32 download_mode) { - u32 val = enable ? QCOM_DLOAD_FULLDUMP : QCOM_DLOAD_NODUMP; + bool enable = !!download_mode; + u32 val = download_mode; bool avail; int ret = 0; @@ -1430,6 +1436,42 @@ static irqreturn_t qcom_scm_irq_handler(int irq, void *data) return IRQ_HANDLED; } +static int get_download_mode(char *buffer, const struct kernel_param *kp) +{ + if (download_mode >= ARRAY_SIZE(download_mode_name)) + return sysfs_emit(buffer, "unknown mode\n"); + + return sysfs_emit(buffer, "%s\n", download_mode_name[download_mode]); +} + +static int set_download_mode(const char *val, const struct kernel_param *kp) +{ + u32 old = download_mode; + int ret; + + ret = sysfs_match_string(download_mode_name, val); + if (ret < 0) { + download_mode = old; + pr_err("qcom_scm: unknown download mode: %s\n", val); + return -EINVAL; + } + + download_mode = ret; + if (__scm) + qcom_scm_set_download_mode(download_mode); + + return 0; +} + +static const struct kernel_param_ops download_mode_param_ops = { + .get = get_download_mode, + .set = set_download_mode, +}; + +module_param_cb(download_mode, &download_mode_param_ops, NULL, 0644); +MODULE_PARM_DESC(download_mode, + "download mode: off/full are acceptable values"); + static int qcom_scm_probe(struct platform_device *pdev) { struct qcom_scm *scm; @@ -1523,12 +1565,12 @@ static int qcom_scm_probe(struct platform_device *pdev) __get_convention(); /* - * If requested enable "download mode", from this point on warmboot + * If "download mode" is requested, from this point on warmboot * will cause the boot stages to enter download mode, unless * disabled below by a clean shutdown/reboot. */ if (download_mode) - qcom_scm_set_download_mode(true); + qcom_scm_set_download_mode(download_mode); return 0; } @@ -1536,7 +1578,7 @@ static int qcom_scm_probe(struct platform_device *pdev) static void qcom_scm_shutdown(struct platform_device *pdev) { /* Clean shutdown, disable download mode to allow normal restart */ - qcom_scm_set_download_mode(false); + qcom_scm_set_download_mode(QCOM_DLOAD_NODUMP); } static const struct of_device_id qcom_scm_dt_match[] = { -- 2.7.4