summaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/psci.h
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-02-06 16:11:03 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-02-13 08:35:42 +0100
commitcc407b41135d4a427dfb09fb6e32b831e6c98a31 (patch)
tree0ba793b8a0c041819e4409f0c31b2d4f297c997a /arch/arm/include/asm/psci.h
parentcdf33e6ecf4ca724d8be64fefbc4896eb8baf046 (diff)
downloadbarebox-cc407b41135d4a427dfb09fb6e32b831e6c98a31.tar.gz
barebox-cc407b41135d4a427dfb09fb6e32b831e6c98a31.tar.xz
ARM: Add PSCI support
This patch contains the barebox implementation for the ARM "Power State Coordination Interface" (PSCI). The interface is aimed at the generalization of code in the following power management scenarios: * Core idle management. * Dynamic addition and removal of cores, and secondary core boot. * big.LITTLE migration. * System shutdown and reset. In practice, all that's currently implemented is a way to enable the secondary core one some SoCs. With PSCI the Kernel is either started in nonsecure or in Hypervisor mode and PSCI is used to apply power to the secondary cores. The start mode is passed in the global.bootm.secure_state variable. This enum can contain "secure" (Kernel is started in secure mode, means no PSCI), "nonsecure" (Kernel is started in nonsecure mode, PSCI available) or "hyp" (Kernel is started in hyp mode, meaning it can support virtualization). We currently only support putting the secure monitor code into SDRAM, which means we always steal some amount of memory from the Kernel. To keep things simple for now we simply keep the whole barebox binary in memory The PSCI support has been tested on i.MX7 only so far. The only supported operations are CPU_ON and CPU_OFF. The PSCI and secure monitor code is based on the corresponding U-Boot code. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/include/asm/psci.h')
-rw-r--r--arch/arm/include/asm/psci.h140
1 files changed, 140 insertions, 0 deletions
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
new file mode 100644
index 0000000000..e0c4525389
--- /dev/null
+++ b/arch/arm/include/asm/psci.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_PSCI_H__
+#define __ARM_PSCI_H__
+
+#define ARM_PSCI_VER_1_0 (0x00010000)
+#define ARM_PSCI_VER_0_2 (0x00000002)
+
+/* PSCI 0.1 interface */
+#define ARM_PSCI_FN_BASE 0x95c1ba5e
+#define ARM_PSCI_FN(n) (ARM_PSCI_FN_BASE + (n))
+
+#define ARM_PSCI_FN_CPU_SUSPEND ARM_PSCI_FN(0)
+#define ARM_PSCI_FN_CPU_OFF ARM_PSCI_FN(1)
+#define ARM_PSCI_FN_CPU_ON ARM_PSCI_FN(2)
+#define ARM_PSCI_FN_MIGRATE ARM_PSCI_FN(3)
+
+#define ARM_PSCI_RET_SUCCESS 0
+#define ARM_PSCI_RET_NOT_SUPPORTED (-1)
+#define ARM_PSCI_RET_INVAL (-2)
+#define ARM_PSCI_RET_DENIED (-3)
+#define ARM_PSCI_RET_ALREADY_ON (-4)
+#define ARM_PSCI_RET_ON_PENDING (-5)
+#define ARM_PSCI_RET_INTERNAL_FAILURE (-6)
+#define ARM_PSCI_RET_NOT_PRESENT (-7)
+#define ARM_PSCI_RET_DISABLED (-8)
+#define ARM_PSCI_RET_INVALID_ADDRESS (-9)
+
+/* PSCI 0.2 interface */
+#define ARM_PSCI_0_2_FN_BASE 0x84000000
+#define ARM_PSCI_0_2_FN(n) (ARM_PSCI_0_2_FN_BASE + (n))
+
+#define ARM_PSCI_0_2_FN64_BASE 0xC4000000
+#define ARM_PSCI_0_2_FN64(n) (ARM_PSCI_0_2_FN64_BASE + (n))
+
+#define ARM_PSCI_0_2_FN_PSCI_VERSION ARM_PSCI_0_2_FN(0)
+#define ARM_PSCI_0_2_FN_CPU_SUSPEND ARM_PSCI_0_2_FN(1)
+#define ARM_PSCI_0_2_FN_CPU_OFF ARM_PSCI_0_2_FN(2)
+#define ARM_PSCI_0_2_FN_CPU_ON ARM_PSCI_0_2_FN(3)
+#define ARM_PSCI_0_2_FN_AFFINITY_INFO ARM_PSCI_0_2_FN(4)
+#define ARM_PSCI_0_2_FN_MIGRATE ARM_PSCI_0_2_FN(5)
+#define ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE ARM_PSCI_0_2_FN(6)
+#define ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU ARM_PSCI_0_2_FN(7)
+#define ARM_PSCI_0_2_FN_SYSTEM_OFF ARM_PSCI_0_2_FN(8)
+#define ARM_PSCI_0_2_FN_SYSTEM_RESET ARM_PSCI_0_2_FN(9)
+
+#define ARM_PSCI_0_2_FN64_CPU_SUSPEND ARM_PSCI_0_2_FN64(1)
+#define ARM_PSCI_0_2_FN64_CPU_ON ARM_PSCI_0_2_FN64(3)
+#define ARM_PSCI_0_2_FN64_AFFINITY_INFO ARM_PSCI_0_2_FN64(4)
+#define ARM_PSCI_0_2_FN64_MIGRATE ARM_PSCI_0_2_FN64(5)
+#define ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU ARM_PSCI_0_2_FN64(7)
+
+/* PSCI 1.0 interface */
+#define ARM_PSCI_1_0_FN_PSCI_FEATURES ARM_PSCI_0_2_FN(10)
+#define ARM_PSCI_1_0_FN_CPU_FREEZE ARM_PSCI_0_2_FN(11)
+#define ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND ARM_PSCI_0_2_FN(12)
+#define ARM_PSCI_1_0_FN_NODE_HW_STATE ARM_PSCI_0_2_FN(13)
+#define ARM_PSCI_1_0_FN_SYSTEM_SUSPEND ARM_PSCI_0_2_FN(14)
+#define ARM_PSCI_1_0_FN_SET_SUSPEND_MODE ARM_PSCI_0_2_FN(15)
+#define ARM_PSCI_1_0_FN_STAT_RESIDENCY ARM_PSCI_0_2_FN(16)
+#define ARM_PSCI_1_0_FN_STAT_COUNT ARM_PSCI_0_2_FN(17)
+
+#define ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND ARM_PSCI_0_2_FN64(12)
+#define ARM_PSCI_1_0_FN64_NODE_HW_STATE ARM_PSCI_0_2_FN64(13)
+#define ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND ARM_PSCI_0_2_FN64(14)
+#define ARM_PSCI_1_0_FN64_STAT_RESIDENCY ARM_PSCI_0_2_FN64(16)
+#define ARM_PSCI_1_0_FN64_STAT_COUNT ARM_PSCI_0_2_FN64(17)
+
+/* PSCI affinity level state returned by AFFINITY_INFO */
+#define PSCI_AFFINITY_LEVEL_ON 0
+#define PSCI_AFFINITY_LEVEL_OFF 1
+#define PSCI_AFFINITY_LEVEL_ON_PENDING 2
+
+struct psci_ops {
+ int (*cpu_suspend)(u32 power_state, unsigned long entry, u32 context_id);
+ int (*cpu_off)(void);
+ int (*cpu_on)(u32 cpu_id);
+ int (*affinity_info)(u32 affinity, u32 lowest_affinity_level);
+ int (*migrate)(u32 cpu_id);
+ int (*migrate_info_type)(void);
+ int (*migrate_info_up_cpu)(void);
+ void (*system_off)(void);
+ void (*system_reset)(void);
+};
+
+#ifdef CONFIG_ARM_PSCI
+void psci_set_ops(struct psci_ops *ops);
+#else
+static inline void psci_set_ops(struct psci_ops *ops)
+{
+}
+#endif
+
+void psci_cpu_entry(void);
+
+#ifdef CONFIG_ARM_PSCI_DEBUG
+void psci_set_putc(void (*putcf)(void *ctx, int c), void *ctx);
+void psci_putc(char c);
+int psci_puts(const char *str);
+int psci_printf(const char *fmt, ...)
+ __attribute__ ((format(__printf__, 1, 2)));
+#else
+
+static inline void psci_set_putc(void (*putcf)(void *ctx, int c), void *ctx)
+{
+}
+
+static inline void psci_putc(char c)
+{
+}
+
+static inline int psci_puts(const char *str)
+{
+ return 0;
+}
+
+static inline int psci_printf(const char *fmt, ...)
+{
+ return 0;
+}
+#endif
+
+int psci_get_cpu_id(void);
+
+#endif /* __ARM_PSCI_H__ */