Re: [PATCH] power: reset: msm: Add support for download-mode control

From: Bjorn Andersson
Date: Thu Jul 19 2018 - 01:42:55 EST


On Wed 18 Jul 22:18 PDT 2018, Rajendra Nayak wrote:

> commit '8c1b7dc9b: firmware: qcom: scm: Expose download-mode control'
> added support for download-mode control using the scm firmware
> driver for platforms which require a secure call to write the magic
> cookie into the tcsr location.
>
> For platforms which *do not* need an scm call and where the kernel can
> write the cookie by a direct read/write, add similar support in the
> msm-poweroff driver.
> Similar to the scm driver, the msm-poweroff driver clears the cookie
> during a clean reboot.
>
> Download mode using msm-poweroff driver can be enabled by including
> msm-poweroff.download_mode=1 on the command line.
>

Should have thought about this when I wrote the scm code...

I would prefer if we could find a way to consolidate the two
implementations behind the same Kconfig and command line parameters.

> Signed-off-by: Rajendra Nayak <rnayak@xxxxxxxxxxxxxx>
> ---
> .../bindings/power/reset/msm-poweroff.txt | 3 ++
> drivers/power/reset/Kconfig | 11 +++++++
> drivers/power/reset/msm-poweroff.c | 38 ++++++++++++++++++++++
> 3 files changed, 52 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/power/reset/msm-poweroff.txt b/Documentation/devicetree/bindings/power/reset/msm-poweroff.txt
> index ce44ad3..9dd489f 100644
> --- a/Documentation/devicetree/bindings/power/reset/msm-poweroff.txt
> +++ b/Documentation/devicetree/bindings/power/reset/msm-poweroff.txt
> @@ -8,6 +8,9 @@ settings.
> Required Properties:
> -compatible: "qcom,pshold"
> -reg: Specifies the physical address of the ps-hold register
> +Optional Properties:
> +-qcom,dload-mode: phandle to the TCSR hardware block and offset of the
> + download mode control register
>
> Example:
>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index df58fc8..0c97e34 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -104,6 +104,17 @@ config POWER_RESET_MSM
> help
> Power off and restart support for Qualcomm boards.
>
> +config POWER_RESET_MSM_DOWNLOAD_MODE

How about moving QCOM_SCM_DOWNLOAD_MODE_DEFAULT to
drivers/soc/qcom/Kconfig (and removing "SCM") and referencing this in
both drivers?

> + bool "Qualcomm download mode enabled by default"
> + depends on POWER_RESET_MSM
> + 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 POWER_RESET_OCELOT_RESET
> bool "Microsemi Ocelot reset driver"
> depends on MSCC_OCELOT || COMPILE_TEST
> diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
> index 01b8c71..c33eac5 100644
> --- a/drivers/power/reset/msm-poweroff.c
> +++ b/drivers/power/reset/msm-poweroff.c
> @@ -18,11 +18,20 @@
> #include <linux/io.h>
> #include <linux/of.h>
> #include <linux/platform_device.h>
> +#include <linux/mfd/syscon.h>
> #include <linux/module.h>
> #include <linux/reboot.h>
> +#include <linux/regmap.h>
> #include <linux/pm.h>
>
> +static bool download_mode = IS_ENABLED(CONFIG_POWER_RESET_MSM_DOWNLOAD_MODE);
> +module_param(download_mode, bool, 0);

Iirc it's possible to have multiple implementations of __setup() for the
same string. I'm uncertain if this would be considered okay though.

> +
> +#define QCOM_SET_DLOAD_MODE 0x10
> static void __iomem *msm_ps_hold;
> +static struct regmap *tcsr_regmap;
> +static unsigned int dload_mode_offset;
> +
> static int deassert_pshold(struct notifier_block *nb, unsigned long action,
> void *data)
> {
> @@ -44,9 +53,30 @@ static void do_msm_poweroff(void)
>
> static int msm_restart_probe(struct platform_device *pdev)
> {
> + int ret;
> + struct of_phandle_args args;
> struct device *dev = &pdev->dev;
> struct resource *mem;
>
> + if (download_mode) {
> + ret = of_parse_phandle_with_fixed_args(dev->of_node,
> + "qcom,dload-mode", 1, 0,
> + &args);
> + if (ret < 0)
> + return ret;
> +
> + tcsr_regmap = syscon_node_to_regmap(args.np);
> + of_node_put(args.np);
> + if (IS_ERR(tcsr_regmap))
> + return PTR_ERR(tcsr_regmap);
> +
> + dload_mode_offset = args.args[0];
> +
> + /* Enable download mode by writing the cookie */
> + regmap_write(tcsr_regmap, dload_mode_offset,
> + QCOM_SET_DLOAD_MODE);
> + }
> +
> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> msm_ps_hold = devm_ioremap_resource(dev, mem);
> if (IS_ERR(msm_ps_hold))
> @@ -59,6 +89,13 @@ static int msm_restart_probe(struct platform_device *pdev)
> return 0;
> }
>
> +static void msm_restart_shutdown(struct platform_device *pdev)
> +{
> + /* Clean shutdown, disable download mode to allow normal restart */
> + if (download_mode)
> + regmap_write(tcsr_regmap, dload_mode_offset, 0x0);
> +}
> +
> static const struct of_device_id of_msm_restart_match[] = {
> { .compatible = "qcom,pshold", },
> {},
> @@ -71,6 +108,7 @@ static int msm_restart_probe(struct platform_device *pdev)
> .name = "msm-restart",
> .of_match_table = of_match_ptr(of_msm_restart_match),
> },
> + .shutdown = msm_restart_shutdown,
> };

Implementation looks good.

Regards,
Bjorn