aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/qcom_scm.c56
-rw-r--r--include/linux/qcom_scm.h7
2 files changed, 58 insertions, 5 deletions
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index c953cc38918f..4d8ede4807ac 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -1,4 +1,5 @@
1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. 1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 * Copyright (C) 2015 Linaro Ltd.
2 * 3 *
3 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and 5 * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +40,23 @@
39#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 40#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
40#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 41#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
41 42
43#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
44#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
45#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
46#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
47
48struct qcom_scm_entry {
49 int flag;
50 void *entry;
51};
52
53static struct qcom_scm_entry qcom_scm_wb[] = {
54 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
55 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
56 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
57 { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
58};
59
42static DEFINE_MUTEX(qcom_scm_lock); 60static DEFINE_MUTEX(qcom_scm_lock);
43 61
44/** 62/**
@@ -379,3 +397,41 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
379 return qcom_scm_set_boot_addr(virt_to_phys(entry), flags); 397 return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
380} 398}
381EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); 399EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
400
401/**
402 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
403 * @entry: Entry point function for the cpus
404 * @cpus: The cpumask of cpus that will use the entry point
405 *
406 * Set the Linux entry point for the SCM to transfer control to when coming
407 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
408 */
409int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
410{
411 int ret;
412 int flags = 0;
413 int cpu;
414
415 /*
416 * Reassign only if we are switching from hotplug entry point
417 * to cpuidle entry point or vice versa.
418 */
419 for_each_cpu(cpu, cpus) {
420 if (entry == qcom_scm_wb[cpu].entry)
421 continue;
422 flags |= qcom_scm_wb[cpu].flag;
423 }
424
425 /* No change in entry function */
426 if (!flags)
427 return 0;
428
429 ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
430 if (!ret) {
431 for_each_cpu(cpu, cpus)
432 qcom_scm_wb[cpu].entry = entry;
433 }
434
435 return ret;
436}
437EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index 68a1d8801c6f..95ef72a47b0f 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -1,4 +1,5 @@
1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. 1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 * Copyright (C) 2015 Linaro Ltd.
2 * 3 *
3 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and 5 * it under the terms of the GNU General Public License version 2 and
@@ -12,12 +13,8 @@
12#ifndef __QCOM_SCM_H 13#ifndef __QCOM_SCM_H
13#define __QCOM_SCM_H 14#define __QCOM_SCM_H
14 15
15#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
16#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
17#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
18#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
19
20extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); 16extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
17extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
21 18
22#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) 19#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
23 20