Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ce76a6a authored by Lina Iyer's avatar Lina Iyer Committed by Kumar Gala
Browse files

firmware: qcom: scm: Add qcom_scm_set_warm_boot_addr function



A core can be powered down for cpuidle or when it is hotplugged off. In
either case, the warmboot return address would be different. Allow
setting the warmboot address for a specific cpu, optimize and write to
the firmware, if the address is different than the previously set
address.

Export qcom_scm_set_warm_boot_addr function move the warm boot flags to
implementation.

Signed-off-by: default avatarLina Iyer <lina.iyer@linaro.org>
Signed-off-by: default avatarKumar Gala <galak@codeaurora.org>
parent a353e4a0
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
 * Copyright (C) 2015 Linaro Ltd.
 *
 * 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
@@ -39,6 +40,23 @@
#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_entry {
	int flag;
	void *entry;
};

static struct qcom_scm_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 DEFINE_MUTEX(qcom_scm_lock);

/**
@@ -379,3 +397,41 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
	return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
}
EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);

/**
 * 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)
{
	int ret;
	int flags = 0;
	int cpu;

	/*
	 * 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;

	ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
	if (!ret) {
		for_each_cpu(cpu, cpus)
			qcom_scm_wb[cpu].entry = entry;
	}

	return ret;
}
EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
+2 −5
Original line number Diff line number Diff line
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
 * Copyright (C) 2015 Linaro Ltd.
 *
 * 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
@@ -12,12 +13,8 @@
#ifndef __QCOM_SCM_H
#define __QCOM_SCM_H

#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

extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);

#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))