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:
Родитель
0ee30ace67
Коммит
7734c4b507
|
@ -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,6 +243,30 @@ 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,
|
||||||
|
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
|
* qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
|
||||||
* @entry: Entry point function for the 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 qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
|
||||||
{
|
{
|
||||||
int ret;
|
return qcom_scm_set_boot_addr(entry, cpus, qcom_scm_cpu_warm_bits);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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);
|
||||||
* 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,
|
||||||
#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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче