power: reset: msm: Deassert PS_HOLD via SCM if possible
Support a new SCM call which disables the PMIC arbiter and deasserts PS_HOLD in a single operation. Fall back on the legacy behavior of disabling the PMIC abriter and directly deasserting PS_HOLD if this call is not available. This is necessary comply with atomicity requirements of the secure environment. Change-Id: Ia3b13d469932edf94d3249fa3e7234a1c12eee1b Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
This commit is contained in:
parent
4a5aa46b78
commit
6c3bc79a39
1 changed files with 32 additions and 4 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
#define EMERGENCY_DLOAD_MAGIC3 0x77777777
|
#define EMERGENCY_DLOAD_MAGIC3 0x77777777
|
||||||
|
|
||||||
#define SCM_IO_DISABLE_PMIC_ARBITER 1
|
#define SCM_IO_DISABLE_PMIC_ARBITER 1
|
||||||
|
#define SCM_IO_DEASSERT_PS_HOLD 2
|
||||||
#define SCM_WDOG_DEBUG_BOOT_PART 0x9
|
#define SCM_WDOG_DEBUG_BOOT_PART 0x9
|
||||||
#define SCM_DLOAD_MODE 0X10
|
#define SCM_DLOAD_MODE 0X10
|
||||||
#define SCM_EDLOAD_MODE 0X01
|
#define SCM_EDLOAD_MODE 0X01
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
static int restart_mode;
|
static int restart_mode;
|
||||||
void *restart_reason;
|
void *restart_reason;
|
||||||
static bool scm_pmic_arbiter_disable_supported;
|
static bool scm_pmic_arbiter_disable_supported;
|
||||||
|
static bool scm_deassert_ps_hold_supported;
|
||||||
/* Download mode master kill-switch */
|
/* Download mode master kill-switch */
|
||||||
static void __iomem *msm_ps_hold;
|
static void __iomem *msm_ps_hold;
|
||||||
|
|
||||||
|
@ -255,6 +257,30 @@ static void msm_restart_prepare(const char *cmd)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deassert PS_HOLD to signal the PMIC that we are ready to power down or reset.
|
||||||
|
* Do this by calling into the secure environment, if available, or by directly
|
||||||
|
* writing to a hardware register.
|
||||||
|
*
|
||||||
|
* This function should never return.
|
||||||
|
*/
|
||||||
|
static void deassert_ps_hold(void)
|
||||||
|
{
|
||||||
|
struct scm_desc desc = {
|
||||||
|
.args[0] = 0,
|
||||||
|
.arginfo = SCM_ARGS(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (scm_deassert_ps_hold_supported) {
|
||||||
|
/* This call will be available on ARMv8 only */
|
||||||
|
scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_PWR,
|
||||||
|
SCM_IO_DEASSERT_PS_HOLD), &desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fall-through to the direct write in case the scm_call "returns" */
|
||||||
|
__raw_writel(0, msm_ps_hold);
|
||||||
|
}
|
||||||
|
|
||||||
static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
|
static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -289,7 +315,7 @@ static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||||
pr_err("Failed to disable secure wdog debug: %d\n", ret);
|
pr_err("Failed to disable secure wdog debug: %d\n", ret);
|
||||||
|
|
||||||
halt_spmi_pmic_arbiter();
|
halt_spmi_pmic_arbiter();
|
||||||
__raw_writel(0, msm_ps_hold);
|
deassert_ps_hold();
|
||||||
|
|
||||||
mdelay(10000);
|
mdelay(10000);
|
||||||
}
|
}
|
||||||
|
@ -319,8 +345,7 @@ static void do_msm_poweroff(void)
|
||||||
pr_err("Failed to disable wdog debug: %d\n", ret);
|
pr_err("Failed to disable wdog debug: %d\n", ret);
|
||||||
|
|
||||||
halt_spmi_pmic_arbiter();
|
halt_spmi_pmic_arbiter();
|
||||||
/* MSM initiated power off, lower ps_hold */
|
deassert_ps_hold();
|
||||||
__raw_writel(0, msm_ps_hold);
|
|
||||||
|
|
||||||
mdelay(10000);
|
mdelay(10000);
|
||||||
pr_err("Powering off has failed\n");
|
pr_err("Powering off has failed\n");
|
||||||
|
@ -383,6 +408,9 @@ static int msm_restart_probe(struct platform_device *pdev)
|
||||||
if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER) > 0)
|
if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER) > 0)
|
||||||
scm_pmic_arbiter_disable_supported = true;
|
scm_pmic_arbiter_disable_supported = true;
|
||||||
|
|
||||||
|
if (scm_is_call_available(SCM_SVC_PWR, SCM_IO_DEASSERT_PS_HOLD) > 0)
|
||||||
|
scm_deassert_ps_hold_supported = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_restart_reason:
|
err_restart_reason:
|
||||||
|
|
Loading…
Add table
Reference in a new issue