forked from Minki/linux
firmware: qcom: scm: Simplify set_cold/warm_boot_addr()
The qcom_scm_set_cold/warm_boot_addr() implementations have a lot of functionality that is actually not used. For example, set_warm_boot_addr() caches the last used entry address and skips making the SCM call when the entry address is unchanged. But there is actually just a single call of qcom_scm_set_warm_boot_addr() in the whole kernel tree, which always configures the entry address to cpu_resume_arm(). Simplify this by having a single qcom_scm_set_boot_addr() function for both cold and warm boot address. This is totally sufficient for the functionality supported in the mainline tree. Signed-off-by: Stephan Gerhold <stephan@gerhold.net> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Link: https://lore.kernel.org/r/20211201130505.257379-3-stephan@gerhold.net
This commit is contained in:
parent
0ee30ace67
commit
7734c4b507
@ -49,26 +49,12 @@ struct qcom_scm_mem_map_info {
|
||||
__le64 mem_size;
|
||||
};
|
||||
|
||||
#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
|
||||
#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
|
||||
#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
|
||||
#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
|
||||
|
||||
#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
|
||||
#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
|
||||
#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
|
||||
#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
|
||||
|
||||
struct qcom_scm_wb_entry {
|
||||
int flag;
|
||||
void *entry;
|
||||
/* Each bit configures cold/warm boot address for one of the 4 CPUs */
|
||||
static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
|
||||
0, BIT(0), BIT(3), BIT(5)
|
||||
};
|
||||
|
||||
static struct qcom_scm_wb_entry qcom_scm_wb[] = {
|
||||
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
|
||||
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
|
||||
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
|
||||
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
|
||||
static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
|
||||
BIT(2), BIT(1), BIT(4), BIT(6)
|
||||
};
|
||||
|
||||
static const char * const qcom_scm_convention_names[] = {
|
||||
@ -257,6 +243,30 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
|
||||
return ret ? false : !!res.result[0];
|
||||
}
|
||||
|
||||
static int qcom_scm_set_boot_addr(void *entry, const cpumask_t *cpus,
|
||||
const u8 *cpu_bits)
|
||||
{
|
||||
int cpu;
|
||||
unsigned int flags = 0;
|
||||
struct qcom_scm_desc desc = {
|
||||
.svc = QCOM_SCM_SVC_BOOT,
|
||||
.cmd = QCOM_SCM_BOOT_SET_ADDR,
|
||||
.arginfo = QCOM_SCM_ARGS(2),
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
if (cpu >= QCOM_SCM_BOOT_MAX_CPUS)
|
||||
return -EINVAL;
|
||||
flags |= cpu_bits[cpu];
|
||||
}
|
||||
|
||||
desc.args[0] = flags;
|
||||
desc.args[1] = virt_to_phys(entry);
|
||||
|
||||
return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
|
||||
* @entry: Entry point function for the cpus
|
||||
@ -267,39 +277,7 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
|
||||
*/
|
||||
int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
|
||||
{
|
||||
int ret;
|
||||
int flags = 0;
|
||||
int cpu;
|
||||
struct qcom_scm_desc desc = {
|
||||
.svc = QCOM_SCM_SVC_BOOT,
|
||||
.cmd = QCOM_SCM_BOOT_SET_ADDR,
|
||||
.arginfo = QCOM_SCM_ARGS(2),
|
||||
};
|
||||
|
||||
/*
|
||||
* Reassign only if we are switching from hotplug entry point
|
||||
* to cpuidle entry point or vice versa.
|
||||
*/
|
||||
for_each_cpu(cpu, cpus) {
|
||||
if (entry == qcom_scm_wb[cpu].entry)
|
||||
continue;
|
||||
flags |= qcom_scm_wb[cpu].flag;
|
||||
}
|
||||
|
||||
/* No change in entry function */
|
||||
if (!flags)
|
||||
return 0;
|
||||
|
||||
desc.args[0] = flags;
|
||||
desc.args[1] = virt_to_phys(entry);
|
||||
|
||||
ret = qcom_scm_call(__scm->dev, &desc, NULL);
|
||||
if (!ret) {
|
||||
for_each_cpu(cpu, cpus)
|
||||
qcom_scm_wb[cpu].entry = entry;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return qcom_scm_set_boot_addr(entry, cpus, qcom_scm_cpu_warm_bits);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
|
||||
|
||||
@ -307,41 +285,10 @@ EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
|
||||
* qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
|
||||
* @entry: Entry point function for the cpus
|
||||
* @cpus: The cpumask of cpus that will use the entry point
|
||||
*
|
||||
* Set the cold boot address of the cpus. Any cpu outside the supported
|
||||
* range would be removed from the cpu present mask.
|
||||
*/
|
||||
int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
|
||||
{
|
||||
int flags = 0;
|
||||
int cpu;
|
||||
int scm_cb_flags[] = {
|
||||
QCOM_SCM_FLAG_COLDBOOT_CPU0,
|
||||
QCOM_SCM_FLAG_COLDBOOT_CPU1,
|
||||
QCOM_SCM_FLAG_COLDBOOT_CPU2,
|
||||
QCOM_SCM_FLAG_COLDBOOT_CPU3,
|
||||
};
|
||||
struct qcom_scm_desc desc = {
|
||||
.svc = QCOM_SCM_SVC_BOOT,
|
||||
.cmd = QCOM_SCM_BOOT_SET_ADDR,
|
||||
.arginfo = QCOM_SCM_ARGS(2),
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
|
||||
if (!cpus || cpumask_empty(cpus))
|
||||
return -EINVAL;
|
||||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
if (cpu < ARRAY_SIZE(scm_cb_flags))
|
||||
flags |= scm_cb_flags[cpu];
|
||||
else
|
||||
set_cpu_present(cpu, false);
|
||||
}
|
||||
|
||||
desc.args[0] = flags;
|
||||
desc.args[1] = virt_to_phys(entry);
|
||||
|
||||
return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
|
||||
return qcom_scm_set_boot_addr(entry, cpus, qcom_scm_cpu_cold_bits);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
|
||||
|
||||
|
@ -80,6 +80,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
|
||||
#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10
|
||||
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
|
||||
#define QCOM_SCM_FLUSH_FLAG_MASK 0x3
|
||||
#define QCOM_SCM_BOOT_MAX_CPUS 4
|
||||
|
||||
#define QCOM_SCM_SVC_PIL 0x02
|
||||
#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01
|
||||
|
Loading…
Reference in New Issue
Block a user