mirror of https://gitee.com/openkylin/linux.git
firmware: qcom: scm: Use atomic SCM for cold boot
This patch changes the cold_set_boot_addr function to use atomic SCM calls. cold_set_boot_addr required adding qcom_scm_call_atomic2 to support the two arguments going to the smc call. Using atomic removes the need for memory allocation and instead places all arguments in registers. Signed-off-by: Andy Gross <andy.gross@linaro.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
parent
d0f6fa7ba2
commit
13e7774780
|
@ -342,6 +342,41 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
|
||||||
return r0;
|
return r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments
|
||||||
|
* @svc_id: service identifier
|
||||||
|
* @cmd_id: command identifier
|
||||||
|
* @arg1: first argument
|
||||||
|
* @arg2: second argument
|
||||||
|
*
|
||||||
|
* This shall only be used with commands that are guaranteed to be
|
||||||
|
* uninterruptable, atomic and SMP safe.
|
||||||
|
*/
|
||||||
|
static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
|
||||||
|
{
|
||||||
|
int context_id;
|
||||||
|
|
||||||
|
register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2);
|
||||||
|
register u32 r1 asm("r1") = (u32)&context_id;
|
||||||
|
register u32 r2 asm("r2") = arg1;
|
||||||
|
register u32 r3 asm("r3") = arg2;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
__asmeq("%0", "r0")
|
||||||
|
__asmeq("%1", "r0")
|
||||||
|
__asmeq("%2", "r1")
|
||||||
|
__asmeq("%3", "r2")
|
||||||
|
__asmeq("%4", "r3")
|
||||||
|
#ifdef REQUIRES_SEC
|
||||||
|
".arch_extension sec\n"
|
||||||
|
#endif
|
||||||
|
"smc #0 @ switch to secure world\n"
|
||||||
|
: "=r" (r0)
|
||||||
|
: "r" (r0), "r" (r1), "r" (r2), "r" (r3)
|
||||||
|
);
|
||||||
|
return r0;
|
||||||
|
}
|
||||||
|
|
||||||
u32 qcom_scm_get_version(void)
|
u32 qcom_scm_get_version(void)
|
||||||
{
|
{
|
||||||
int context_id;
|
int context_id;
|
||||||
|
@ -378,22 +413,6 @@ u32 qcom_scm_get_version(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(qcom_scm_get_version);
|
EXPORT_SYMBOL(qcom_scm_get_version);
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the cold/warm boot address for one of the CPU cores.
|
|
||||||
*/
|
|
||||||
static int qcom_scm_set_boot_addr(u32 addr, int flags)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
__le32 flags;
|
|
||||||
__le32 addr;
|
|
||||||
} cmd;
|
|
||||||
|
|
||||||
cmd.addr = cpu_to_le32(addr);
|
|
||||||
cmd.flags = cpu_to_le32(flags);
|
|
||||||
return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
|
|
||||||
&cmd, sizeof(cmd), NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
|
* qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
|
||||||
* @entry: Entry point function for the cpus
|
* @entry: Entry point function for the cpus
|
||||||
|
@ -423,7 +442,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
|
||||||
set_cpu_present(cpu, false);
|
set_cpu_present(cpu, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
|
return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
|
||||||
|
flags, virt_to_phys(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -439,6 +459,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
|
||||||
int ret;
|
int ret;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
struct {
|
||||||
|
__le32 flags;
|
||||||
|
__le32 addr;
|
||||||
|
} cmd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reassign only if we are switching from hotplug entry point
|
* Reassign only if we are switching from hotplug entry point
|
||||||
|
@ -454,7 +478,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
|
||||||
if (!flags)
|
if (!flags)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
|
cmd.addr = cpu_to_le32(virt_to_phys(entry));
|
||||||
|
cmd.flags = cpu_to_le32(flags);
|
||||||
|
ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
|
||||||
|
&cmd, sizeof(cmd), NULL, 0);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
for_each_cpu(cpu, cpus)
|
for_each_cpu(cpu, cpus)
|
||||||
qcom_scm_wb[cpu].entry = entry;
|
qcom_scm_wb[cpu].entry = entry;
|
||||||
|
|
Loading…
Reference in New Issue