Commit 7734c4b5 authored by Stephan Gerhold's avatar Stephan Gerhold Committed by Bjorn Andersson

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: default avatarStephan Gerhold <stephan@gerhold.net>
Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20211201130505.257379-3-stephan@gerhold.net
parent 0ee30ace
...@@ -49,26 +49,12 @@ struct qcom_scm_mem_map_info { ...@@ -49,26 +49,12 @@ struct qcom_scm_mem_map_info {
__le64 mem_size; __le64 mem_size;
}; };
#define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 /* Each bit configures cold/warm boot address for one of the 4 CPUs */
#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 0, BIT(0), BIT(3), BIT(5)
#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;
}; };
static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = {
static struct qcom_scm_wb_entry qcom_scm_wb[] = { BIT(2), BIT(1), BIT(4), BIT(6)
{ .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 char * const qcom_scm_convention_names[] = { static const char * const qcom_scm_convention_names[] = {
...@@ -257,49 +243,41 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id, ...@@ -257,49 +243,41 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
return ret ? false : !!res.result[0]; return ret ? false : !!res.result[0];
} }
/** static int qcom_scm_set_boot_addr(void *entry, const cpumask_t *cpus,
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus const u8 *cpu_bits)
* @entry: Entry point function for the cpus
* @cpus: The cpumask of cpus that will use the entry point
*
* Set the Linux entry point for the SCM to transfer control to when coming
* out of a power down. CPU power down may be executed on cpuidle or hotplug.
*/
int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
{ {
int ret;
int flags = 0;
int cpu; int cpu;
unsigned int flags = 0;
struct qcom_scm_desc desc = { struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_BOOT, .svc = QCOM_SCM_SVC_BOOT,
.cmd = QCOM_SCM_BOOT_SET_ADDR, .cmd = QCOM_SCM_BOOT_SET_ADDR,
.arginfo = QCOM_SCM_ARGS(2), .arginfo = QCOM_SCM_ARGS(2),
.owner = ARM_SMCCC_OWNER_SIP,
}; };
/*
* Reassign only if we are switching from hotplug entry point
* to cpuidle entry point or vice versa.
*/
for_each_cpu(cpu, cpus) { for_each_cpu(cpu, cpus) {
if (entry == qcom_scm_wb[cpu].entry) if (cpu >= QCOM_SCM_BOOT_MAX_CPUS)
continue; return -EINVAL;
flags |= qcom_scm_wb[cpu].flag; flags |= cpu_bits[cpu];
} }
/* No change in entry function */
if (!flags)
return 0;
desc.args[0] = flags; desc.args[0] = flags;
desc.args[1] = virt_to_phys(entry); desc.args[1] = virt_to_phys(entry);
ret = qcom_scm_call(__scm->dev, &desc, NULL); return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
if (!ret) { }
for_each_cpu(cpu, cpus)
qcom_scm_wb[cpu].entry = entry;
}
return ret; /**
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
* @entry: Entry point function for the cpus
* @cpus: The cpumask of cpus that will use the entry point
*
* Set the Linux entry point for the SCM to transfer control to when coming
* out of a power down. CPU power down may be executed on cpuidle or hotplug.
*/
int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
{
return qcom_scm_set_boot_addr(entry, cpus, qcom_scm_cpu_warm_bits);
} }
EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
...@@ -307,41 +285,10 @@ 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 * 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
* @cpus: The cpumask of cpus that will use the entry point * @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 qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
{ {
int flags = 0; return qcom_scm_set_boot_addr(entry, cpus, qcom_scm_cpu_cold_bits);
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);
} }
EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); 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, ...@@ -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_DLOAD_MODE 0x10
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 #define QCOM_SCM_FLUSH_FLAG_MASK 0x3
#define QCOM_SCM_BOOT_MAX_CPUS 4
#define QCOM_SCM_SVC_PIL 0x02 #define QCOM_SCM_SVC_PIL 0x02
#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01 #define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment