* [U-Boot] [PATCH v2 0/3] ARM: support System Reset via PSCI
@ 2017-04-13 2:39 Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 1/3] ARM: import arm-smccc code from Linux 4.11-rc6 Masahiro Yamada
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Masahiro Yamada @ 2017-04-13 2:39 UTC (permalink / raw)
To: u-boot
For ARMv8, the secure firmware (ex. ARM Trusted Firmware BL31) is
often implemented, making U-Boot a non-secure world boot loader.
The secure firmware generally includes PSCI. The power management
operations, including System Reset, are supposed to be handled by
PSCI. In this case, U-Boot should not touch the system reset directly.
Instead, U-Boot should call PSCI service to reset the system.
In order to implement this, arm-smccc code is needed. The code
has been copied from Linux. (1/3)
They have been adjusted for use in U-Boot (2/3).
3/3 implements a generic sysreset driver based on the PSCI
specification.
Masahiro Yamada (3):
ARM: import arm-smccc code from Linux 4.11-rc6
ARM: adjust arm-smccc code for use in U-Boot
sysreset: psci: support system reset in a generic way with PSCI
arch/arm/Kconfig | 9 ++
arch/arm/cpu/armv7/Makefile | 1 +
arch/arm/cpu/armv7/smccc-call.S | 56 +++++++++
arch/arm/cpu/armv8/Makefile | 2 +
arch/arm/cpu/armv8/smccc-call.S | 44 +++++++
arch/arm/include/asm/opcodes-sec.h | 17 +++
arch/arm/include/asm/opcodes-virt.h | 27 +++++
arch/arm/include/asm/opcodes.h | 229 ++++++++++++++++++++++++++++++++++++
arch/arm/lib/asm-offsets.c | 8 ++
drivers/Kconfig | 2 +
drivers/Makefile | 5 +-
drivers/firmware/Kconfig | 6 +
drivers/firmware/Makefile | 2 +
drivers/firmware/firmware-uclass.c | 11 ++
drivers/firmware/psci.c | 94 +++++++++++++++
drivers/sysreset/Kconfig | 10 ++
drivers/sysreset/Makefile | 1 +
drivers/sysreset/sysreset_psci.c | 41 +++++++
include/dm/uclass-id.h | 1 +
include/linux/arm-smccc.h | 126 ++++++++++++++++++++
include/linux/psci.h | 13 ++
21 files changed, 703 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/cpu/armv7/smccc-call.S
create mode 100644 arch/arm/cpu/armv8/smccc-call.S
create mode 100644 arch/arm/include/asm/opcodes-sec.h
create mode 100644 arch/arm/include/asm/opcodes-virt.h
create mode 100644 arch/arm/include/asm/opcodes.h
create mode 100644 drivers/firmware/Kconfig
create mode 100644 drivers/firmware/Makefile
create mode 100644 drivers/firmware/firmware-uclass.c
create mode 100644 drivers/firmware/psci.c
create mode 100644 drivers/sysreset/sysreset_psci.c
create mode 100644 include/linux/arm-smccc.h
--
2.7.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* [U-Boot] [PATCH v2 1/3] ARM: import arm-smccc code from Linux 4.11-rc6
2017-04-13 2:39 [U-Boot] [PATCH v2 0/3] ARM: support System Reset via PSCI Masahiro Yamada
@ 2017-04-13 2:39 ` Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 2/3] ARM: adjust arm-smccc code for use in U-Boot Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI Masahiro Yamada
2 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2017-04-13 2:39 UTC (permalink / raw)
To: u-boot
Imports ARM SMC Calling Convention code from Linux 4.11-rc6.
The files have been copied as follows:
[Linux] [U-Boot]
arch/arm/kernel/smccc-call.S -> arch/arm/cpu/armv7/smccc-call.S
arch/arm64/kernel/smccc-call.S -> arch/arm/cpu/armv8/smccc-call.S
arch/arm/include/asm/opcodes* -> arch/arm/include/asm/opcodes*
include/linux/arm-smccc.h -> include/linux/arm-smccc.h
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
Changes in v2:
- split into separate patches "import" and "adjust"
arch/arm/cpu/armv7/smccc-call.S | 64 ++++++++++
arch/arm/cpu/armv8/smccc-call.S | 52 ++++++++
arch/arm/include/asm/opcodes-sec.h | 24 ++++
arch/arm/include/asm/opcodes-virt.h | 39 ++++++
arch/arm/include/asm/opcodes.h | 231 ++++++++++++++++++++++++++++++++++++
include/linux/arm-smccc.h | 134 +++++++++++++++++++++
6 files changed, 544 insertions(+)
create mode 100644 arch/arm/cpu/armv7/smccc-call.S
create mode 100644 arch/arm/cpu/armv8/smccc-call.S
create mode 100644 arch/arm/include/asm/opcodes-sec.h
create mode 100644 arch/arm/include/asm/opcodes-virt.h
create mode 100644 arch/arm/include/asm/opcodes.h
create mode 100644 include/linux/arm-smccc.h
diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S
new file mode 100644
index 0000000..e5d4306
--- /dev/null
+++ b/arch/arm/cpu/armv7/smccc-call.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#include <linux/linkage.h>
+
+#include <asm/opcodes-sec.h>
+#include <asm/opcodes-virt.h>
+#include <asm/unwind.h>
+
+ /*
+ * Wrap c macros in asm macros to delay expansion until after the
+ * SMCCC asm macro is expanded.
+ */
+ .macro SMCCC_SMC
+ __SMC(0)
+ .endm
+
+ .macro SMCCC_HVC
+ __HVC(0)
+ .endm
+
+ .macro SMCCC instr
+UNWIND( .fnstart)
+ mov r12, sp
+ push {r4-r7}
+UNWIND( .save {r4-r7})
+ ldm r12, {r4-r7}
+ \instr
+ pop {r4-r7}
+ ldr r12, [sp, #(4 * 4)]
+ stm r12, {r0-r3}
+ bx lr
+UNWIND( .fnend)
+ .endm
+
+/*
+ * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+ * unsigned long a3, unsigned long a4, unsigned long a5,
+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ * struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_smc)
+ SMCCC SMCCC_SMC
+ENDPROC(__arm_smccc_smc)
+
+/*
+ * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
+ * unsigned long a3, unsigned long a4, unsigned long a5,
+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ * struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_hvc)
+ SMCCC SMCCC_HVC
+ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
new file mode 100644
index 0000000..6252234
--- /dev/null
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * 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.
+ *
+ */
+#include <linux/linkage.h>
+#include <linux/arm-smccc.h>
+#include <asm/asm-offsets.h>
+
+ .macro SMCCC instr
+ .cfi_startproc
+ \instr #0
+ ldr x4, [sp]
+ stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
+ stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
+ ldr x4, [sp, #8]
+ cbz x4, 1f /* no quirk structure */
+ ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
+ cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6
+ b.ne 1f
+ str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
+1: ret
+ .cfi_endproc
+ .endm
+
+/*
+ * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
+ * unsigned long a3, unsigned long a4, unsigned long a5,
+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ * struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_smc)
+ SMCCC smc
+ENDPROC(__arm_smccc_smc)
+
+/*
+ * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
+ * unsigned long a3, unsigned long a4, unsigned long a5,
+ * unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
+ * struct arm_smccc_quirk *quirk)
+ */
+ENTRY(__arm_smccc_hvc)
+ SMCCC hvc
+ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm/include/asm/opcodes-sec.h b/arch/arm/include/asm/opcodes-sec.h
new file mode 100644
index 0000000..bc3a917
--- /dev/null
+++ b/arch/arm/include/asm/opcodes-sec.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#ifndef __ASM_ARM_OPCODES_SEC_H
+#define __ASM_ARM_OPCODES_SEC_H
+
+#include <asm/opcodes.h>
+
+#define __SMC(imm4) __inst_arm_thumb32( \
+ 0xE1600070 | (((imm4) & 0xF) << 0), \
+ 0xF7F08000 | (((imm4) & 0xF) << 16) \
+)
+
+#endif /* __ASM_ARM_OPCODES_SEC_H */
diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
new file mode 100644
index 0000000..efcfdf9
--- /dev/null
+++ b/arch/arm/include/asm/opcodes-virt.h
@@ -0,0 +1,39 @@
+/*
+ * opcodes-virt.h: Opcode definitions for the ARM virtualization extensions
+ * Copyright (C) 2012 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __ASM_ARM_OPCODES_VIRT_H
+#define __ASM_ARM_OPCODES_VIRT_H
+
+#include <asm/opcodes.h>
+
+#define __HVC(imm16) __inst_arm_thumb32( \
+ 0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F), \
+ 0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \
+)
+
+#define __ERET __inst_arm_thumb32( \
+ 0xE160006E, \
+ 0xF3DE8F00 \
+)
+
+#define __MSR_ELR_HYP(regnum) __inst_arm_thumb32( \
+ 0xE12EF300 | regnum, \
+ 0xF3808E30 | (regnum << 16) \
+)
+
+#endif /* ! __ASM_ARM_OPCODES_VIRT_H */
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
new file mode 100644
index 0000000..e796c59
--- /dev/null
+++ b/arch/arm/include/asm/opcodes.h
@@ -0,0 +1,231 @@
+/*
+ * arch/arm/include/asm/opcodes.h
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARM_OPCODES_H
+#define __ASM_ARM_OPCODES_H
+
+#ifndef __ASSEMBLY__
+#include <linux/linkage.h>
+extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
+#endif
+
+#define ARM_OPCODE_CONDTEST_FAIL 0
+#define ARM_OPCODE_CONDTEST_PASS 1
+#define ARM_OPCODE_CONDTEST_UNCOND 2
+
+
+/*
+ * Assembler opcode byteswap helpers.
+ * These are only intended for use by this header: don't use them directly,
+ * because they will be suboptimal in most cases.
+ */
+#define ___asm_opcode_swab32(x) ( \
+ (((x) << 24) & 0xFF000000) \
+ | (((x) << 8) & 0x00FF0000) \
+ | (((x) >> 8) & 0x0000FF00) \
+ | (((x) >> 24) & 0x000000FF) \
+)
+#define ___asm_opcode_swab16(x) ( \
+ (((x) << 8) & 0xFF00) \
+ | (((x) >> 8) & 0x00FF) \
+)
+#define ___asm_opcode_swahb32(x) ( \
+ (((x) << 8) & 0xFF00FF00) \
+ | (((x) >> 8) & 0x00FF00FF) \
+)
+#define ___asm_opcode_swahw32(x) ( \
+ (((x) << 16) & 0xFFFF0000) \
+ | (((x) >> 16) & 0x0000FFFF) \
+)
+#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
+#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
+
+
+/*
+ * Opcode byteswap helpers
+ *
+ * These macros help with converting instructions between a canonical integer
+ * format and in-memory representation, in an endianness-agnostic manner.
+ *
+ * __mem_to_opcode_*() convert from in-memory representation to canonical form.
+ * __opcode_to_mem_*() convert from canonical form to in-memory representation.
+ *
+ *
+ * Canonical instruction representation:
+ *
+ * ARM: 0xKKLLMMNN
+ * Thumb 16-bit: 0x0000KKLL, where KK < 0xE8
+ * Thumb 32-bit: 0xKKLLMMNN, where KK >= 0xE8
+ *
+ * There is no way to distinguish an ARM instruction in canonical representation
+ * from a Thumb instruction (just as these cannot be distinguished in memory).
+ * Where this distinction is important, it needs to be tracked separately.
+ *
+ * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
+ * represent any valid Thumb-2 instruction. For this range,
+ * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
+ *
+ * The ___asm variants are intended only for use by this header, in situations
+ * involving inline assembler. For .S files, the normal __opcode_*() macros
+ * should do the right thing.
+ */
+#ifdef __ASSEMBLY__
+
+#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
+#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
+#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
+#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
+#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
+#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
+
+#else /* ! __ASSEMBLY__ */
+
+#include <linux/types.h>
+#include <linux/swab.h>
+
+#define ___opcode_swab32(x) swab32(x)
+#define ___opcode_swab16(x) swab16(x)
+#define ___opcode_swahb32(x) swahb32(x)
+#define ___opcode_swahw32(x) swahw32(x)
+#define ___opcode_identity32(x) ((u32)(x))
+#define ___opcode_identity16(x) ((u16)(x))
+
+#endif /* ! __ASSEMBLY__ */
+
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+
+#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
+#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
+#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
+#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
+#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
+
+#else /* ! CONFIG_CPU_ENDIAN_BE8 */
+
+#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
+#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
+#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
+#ifndef CONFIG_CPU_ENDIAN_BE32
+/*
+ * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
+ * work in all cases, due to alignment constraints. For now, a correct
+ * version is not provided for BE32.
+ */
+#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
+#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
+#endif
+
+#endif /* ! CONFIG_CPU_ENDIAN_BE8 */
+
+#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
+#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
+#ifndef CONFIG_CPU_ENDIAN_BE32
+#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
+#endif
+
+/* Operations specific to Thumb opcodes */
+
+/* Instruction size checks: */
+#define __opcode_is_thumb32(x) ( \
+ ((x) & 0xF8000000) == 0xE8000000 \
+ || ((x) & 0xF0000000) == 0xF0000000 \
+)
+#define __opcode_is_thumb16(x) ( \
+ ((x) & 0xFFFF0000) == 0 \
+ && !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \
+)
+
+/* Operations to construct or split 32-bit Thumb instructions: */
+#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
+#define __opcode_thumb32_second(x) (___opcode_identity16(x))
+#define __opcode_thumb32_compose(first, second) ( \
+ (___opcode_identity32(___opcode_identity16(first)) << 16) \
+ | ___opcode_identity32(___opcode_identity16(second)) \
+)
+#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
+#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
+#define ___asm_opcode_thumb32_compose(first, second) ( \
+ (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
+ | ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
+)
+
+/*
+ * Opcode injection helpers
+ *
+ * In rare cases it is necessary to assemble an opcode which the
+ * assembler does not support directly, or which would normally be
+ * rejected because of the CFLAGS or AFLAGS used to build the affected
+ * file.
+ *
+ * Before using these macros, consider carefully whether it is feasible
+ * instead to change the build flags for your file, or whether it really
+ * makes sense to support old assembler versions when building that
+ * particular kernel feature.
+ *
+ * The macros defined here should only be used where there is no viable
+ * alternative.
+ *
+ *
+ * __inst_arm(x): emit the specified ARM opcode
+ * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
+ * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
+ *
+ * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
+ * 16-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ * kernel is being built
+ *
+ * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
+ * 32-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ * kernel is being built
+ *
+ *
+ * Note that using these macros directly is poor practice. Instead, you
+ * should use them to define human-readable wrapper macros to encode the
+ * instructions that you care about. In code which might run on ARMv7 or
+ * above, you can usually use the __inst_arm_thumb{16,32} macros to
+ * specify the ARM and Thumb alternatives at the same time. This ensures
+ * that the correct opcode gets emitted depending on the instruction set
+ * used for the kernel build.
+ *
+ * Look@opcodes-virt.h for an example of how to use these macros.
+ */
+#include <linux/stringify.h>
+
+#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
+#define __inst_thumb32(x) ___inst_thumb32( \
+ ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \
+ ___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \
+)
+#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
+ __inst_thumb16(thumb_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
+ __inst_thumb32(thumb_opcode)
+#else
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#endif
+
+/* Helpers for the helpers. Don't use these directly. */
+#ifdef __ASSEMBLY__
+#define ___inst_arm(x) .long x
+#define ___inst_thumb16(x) .short x
+#define ___inst_thumb32(first, second) .short first, second
+#else
+#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
+#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
+#define ___inst_thumb32(first, second) \
+ ".short " __stringify(first) ", " __stringify(second) "\n\t"
+#endif
+
+#endif /* __ASM_ARM_OPCODES_H */
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
new file mode 100644
index 0000000..4c5bca3
--- /dev/null
+++ b/include/linux/arm-smccc.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#ifndef __LINUX_ARM_SMCCC_H
+#define __LINUX_ARM_SMCCC_H
+
+/*
+ * This file provides common defines for ARM SMC Calling Convention as
+ * specified in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+ */
+
+#define ARM_SMCCC_STD_CALL 0
+#define ARM_SMCCC_FAST_CALL 1
+#define ARM_SMCCC_TYPE_SHIFT 31
+
+#define ARM_SMCCC_SMC_32 0
+#define ARM_SMCCC_SMC_64 1
+#define ARM_SMCCC_CALL_CONV_SHIFT 30
+
+#define ARM_SMCCC_OWNER_MASK 0x3F
+#define ARM_SMCCC_OWNER_SHIFT 24
+
+#define ARM_SMCCC_FUNC_MASK 0xFFFF
+
+#define ARM_SMCCC_IS_FAST_CALL(smc_val) \
+ ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
+#define ARM_SMCCC_IS_64(smc_val) \
+ ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
+#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)
+#define ARM_SMCCC_OWNER_NUM(smc_val) \
+ (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
+
+#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
+ (((type) << ARM_SMCCC_TYPE_SHIFT) | \
+ ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
+ (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
+ ((func_num) & ARM_SMCCC_FUNC_MASK))
+
+#define ARM_SMCCC_OWNER_ARCH 0
+#define ARM_SMCCC_OWNER_CPU 1
+#define ARM_SMCCC_OWNER_SIP 2
+#define ARM_SMCCC_OWNER_OEM 3
+#define ARM_SMCCC_OWNER_STANDARD 4
+#define ARM_SMCCC_OWNER_TRUSTED_APP 48
+#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
+#define ARM_SMCCC_OWNER_TRUSTED_OS 50
+#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
+
+#define ARM_SMCCC_QUIRK_NONE 0
+#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <linux/types.h>
+/**
+ * struct arm_smccc_res - Result from SMC/HVC call
+ * @a0-a3 result values from registers 0 to 3
+ */
+struct arm_smccc_res {
+ unsigned long a0;
+ unsigned long a1;
+ unsigned long a2;
+ unsigned long a3;
+};
+
+/**
+ * struct arm_smccc_quirk - Contains quirk information
+ * @id: quirk identification
+ * @state: quirk specific information
+ * @a6: Qualcomm quirk entry for returning post-smc call contents of a6
+ */
+struct arm_smccc_quirk {
+ int id;
+ union {
+ unsigned long a6;
+ } state;
+};
+
+/**
+ * __arm_smccc_smc() - make SMC calls
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
+ *
+ * This function is used to make SMC calls following SMC Calling Convention.
+ * The content of the supplied param are copied to registers 0 to 7 prior
+ * to the SMC instruction. The return values are updated with the content
+ * from register 0 to 3 on return from the SMC instruction. An optional
+ * quirk structure provides vendor specific behavior.
+ */
+asmlinkage void __arm_smccc_smc(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
+
+/**
+ * __arm_smccc_hvc() - make HVC calls
+ * @a0-a7: arguments passed in registers 0 to 7
+ * @res: result values from registers 0 to 3
+ * @quirk: points to an arm_smccc_quirk, or NULL when no quirks are required.
+ *
+ * This function is used to make HVC calls following SMC Calling
+ * Convention. The content of the supplied param are copied to registers 0
+ * to 7 prior to the HVC instruction. The return values are updated with
+ * the content from register 0 to 3 on return from the HVC instruction. An
+ * optional quirk structure provides vendor specific behavior.
+ */
+asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *res, struct arm_smccc_quirk *quirk);
+
+#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
+
+#define arm_smccc_smc_quirk(...) __arm_smccc_smc(__VA_ARGS__)
+
+#define arm_smccc_hvc(...) __arm_smccc_hvc(__VA_ARGS__, NULL)
+
+#define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__)
+
+#endif /*__ASSEMBLY__*/
+#endif /*__LINUX_ARM_SMCCC_H*/
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [U-Boot] [PATCH v2 2/3] ARM: adjust arm-smccc code for use in U-Boot
2017-04-13 2:39 [U-Boot] [PATCH v2 0/3] ARM: support System Reset via PSCI Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 1/3] ARM: import arm-smccc code from Linux 4.11-rc6 Masahiro Yamada
@ 2017-04-13 2:39 ` Masahiro Yamada
2017-04-13 13:57 ` Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI Masahiro Yamada
2 siblings, 1 reply; 7+ messages in thread
From: Masahiro Yamada @ 2017-04-13 2:39 UTC (permalink / raw)
To: u-boot
Adjust ARM SMC Calling Convention code for U-Boot:
- Replace the license block with SPDX
- Change path to asm-offsets.h
- Define UNWIND() as no-op
- Add Kconfig entry
- Add asm-offsets
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
Changes in v2:
- split into separate patches "import" and "adjust"
arch/arm/Kconfig | 8 ++++++++
arch/arm/cpu/armv7/Makefile | 1 +
arch/arm/cpu/armv7/smccc-call.S | 12 ++----------
arch/arm/cpu/armv8/Makefile | 2 ++
arch/arm/cpu/armv8/smccc-call.S | 12 ++----------
arch/arm/include/asm/opcodes-sec.h | 11 ++---------
arch/arm/include/asm/opcodes-virt.h | 14 +-------------
arch/arm/include/asm/opcodes.h | 4 +---
arch/arm/lib/asm-offsets.c | 8 ++++++++
include/linux/arm-smccc.h | 10 +---------
10 files changed, 28 insertions(+), 54 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7b20750..84744ef 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -174,6 +174,14 @@ config SYS_CACHELINE_SIZE
default 64 if SYS_CACHE_SHIFT_6
default 32 if SYS_CACHE_SHIFT_5
+config ARM_SMCCC
+ bool "Support for ARM SMC Calling Convention (SMCCC)"
+ depends on CPU_V7 || ARM64
+ help
+ Say Y here if you want to enable ARM SMC Calling Convention.
+ This should be enabled if U-Boot needs to communicate with system
+ firmware (for example, PSCI) according to SMCCC.
+
config SEMIHOSTING
bool "support boot from semihosting"
help
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index 02e8778..3a9913a 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -18,6 +18,7 @@ obj-y += lowlevel_init.o
endif
endif
+obj-$(CONFIG_ARM_SMCCC) += smccc-call.o
obj-$(CONFIG_ARMV7_NONSEC) += nonsec_virt.o virt-v7.o virt-dt.o
obj-$(CONFIG_ARMV7_PSCI) += psci.o psci-common.o
diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S
index e5d4306..c2fdbad 100644
--- a/arch/arm/cpu/armv7/smccc-call.S
+++ b/arch/arm/cpu/armv7/smccc-call.S
@@ -1,22 +1,14 @@
/*
* Copyright (c) 2015, Linaro Limited
*
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
+ * SPDX-License-Identifier: GPL-2.0
*/
#include <linux/linkage.h>
#include <asm/opcodes-sec.h>
#include <asm/opcodes-virt.h>
-#include <asm/unwind.h>
+#define UNWIND(x...)
/*
* Wrap c macros in asm macros to delay expansion until after the
* SMCCC asm macro is expanded.
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index 65915ee..c447085 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -16,6 +16,8 @@ obj-y += tlb.o
obj-y += transition.o
obj-y += fwcall.o
obj-y += cpu-dt.o
+obj-$(CONFIG_ARM_SMCCC) += smccc-call.o
+
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
endif
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index 6252234..bbb6cba 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -1,19 +1,11 @@
/*
* Copyright (c) 2015, Linaro Limited
*
- * 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.
- *
+ * SPDX-License-Identifier: GPL-2.0
*/
#include <linux/linkage.h>
#include <linux/arm-smccc.h>
-#include <asm/asm-offsets.h>
+#include <generated/asm-offsets.h>
.macro SMCCC instr
.cfi_startproc
diff --git a/arch/arm/include/asm/opcodes-sec.h b/arch/arm/include/asm/opcodes-sec.h
index bc3a917..16dee8f 100644
--- a/arch/arm/include/asm/opcodes-sec.h
+++ b/arch/arm/include/asm/opcodes-sec.h
@@ -1,14 +1,7 @@
/*
- * 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.
- *
* Copyright (C) 2012 ARM Limited
+ *
+ * SPDX-License-Identifier: GPL-2.0
*/
#ifndef __ASM_ARM_OPCODES_SEC_H
diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
index efcfdf9..923f257 100644
--- a/arch/arm/include/asm/opcodes-virt.h
+++ b/arch/arm/include/asm/opcodes-virt.h
@@ -2,19 +2,7 @@
* opcodes-virt.h: Opcode definitions for the ARM virtualization extensions
* Copyright (C) 2012 Linaro Limited
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0
*/
#ifndef __ASM_ARM_OPCODES_VIRT_H
#define __ASM_ARM_OPCODES_VIRT_H
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index e796c59..199f0ba 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -1,9 +1,7 @@
/*
* arch/arm/include/asm/opcodes.h
*
- * 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.
+ * SPDX-License-Identifier: GPL-2.0
*/
#ifndef __ASM_ARM_OPCODES_H
diff --git a/arch/arm/lib/asm-offsets.c b/arch/arm/lib/asm-offsets.c
index e5bcaea..d620dc0 100644
--- a/arch/arm/lib/asm-offsets.c
+++ b/arch/arm/lib/asm-offsets.c
@@ -14,6 +14,7 @@
#include <common.h>
#include <linux/kbuild.h>
+#include <linux/arm-smccc.h>
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) \
|| defined(CONFIG_MX51) || defined(CONFIG_MX53)
@@ -198,5 +199,12 @@ int main(void)
DEFINE(PLL_DP_HFS_MFN, offsetof(struct dpll, dp_hfs_mfn));
#endif
+#ifdef CONFIG_ARM_SMCCC
+ DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
+ DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
+ DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
+ DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
+#endif
+
return 0;
}
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 4c5bca3..28e61ce 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -1,15 +1,7 @@
/*
* Copyright (c) 2015, Linaro Limited
*
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
+ * SPDX-License-Identifier: GPL-2.0
*/
#ifndef __LINUX_ARM_SMCCC_H
#define __LINUX_ARM_SMCCC_H
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI
2017-04-13 2:39 [U-Boot] [PATCH v2 0/3] ARM: support System Reset via PSCI Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 1/3] ARM: import arm-smccc code from Linux 4.11-rc6 Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 2/3] ARM: adjust arm-smccc code for use in U-Boot Masahiro Yamada
@ 2017-04-13 2:39 ` Masahiro Yamada
2017-04-16 19:31 ` Simon Glass
2 siblings, 1 reply; 7+ messages in thread
From: Masahiro Yamada @ 2017-04-13 2:39 UTC (permalink / raw)
To: u-boot
If the system is running PSCI firmware, the System Reset function
(func ID: 0x80000009) is supposed to be handled by PSCI, that is,
the SoC/board specific reset implementation should be moved to PSCI.
U-Boot should call the PSCI service according to the arm-smccc
manner.
The arm-smccc is supported on ARMv7 or later. Especially, ARMv8
generation SoCs are likely to run ARM Trusted Firmware BL31. In
this case, U-Boot is a non-secure world boot loader, so it should
not be able to reset the system directly.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
Changes in v2: None
arch/arm/Kconfig | 1 +
drivers/Kconfig | 2 +
drivers/Makefile | 5 +-
drivers/firmware/Kconfig | 6 +++
drivers/firmware/Makefile | 2 +
drivers/firmware/firmware-uclass.c | 11 +++++
drivers/firmware/psci.c | 94 ++++++++++++++++++++++++++++++++++++++
drivers/sysreset/Kconfig | 10 ++++
drivers/sysreset/Makefile | 1 +
drivers/sysreset/sysreset_psci.c | 41 +++++++++++++++++
include/dm/uclass-id.h | 1 +
include/linux/psci.h | 13 ++++++
12 files changed, 185 insertions(+), 2 deletions(-)
create mode 100644 drivers/firmware/Kconfig
create mode 100644 drivers/firmware/Makefile
create mode 100644 drivers/firmware/firmware-uclass.c
create mode 100644 drivers/firmware/psci.c
create mode 100644 drivers/sysreset/sysreset_psci.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 84744ef..64984dc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -177,6 +177,7 @@ config SYS_CACHELINE_SIZE
config ARM_SMCCC
bool "Support for ARM SMC Calling Convention (SMCCC)"
depends on CPU_V7 || ARM64
+ select ARM_PSCI_FW
help
Say Y here if you want to enable ARM SMC Calling Convention.
This should be enabled if U-Boot needs to communicate with system
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 0e5d97d..d0a36ab 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -22,6 +22,8 @@ source "drivers/dfu/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/firmware/Kconfig"
+
source "drivers/fpga/Kconfig"
source "drivers/gpio/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5d8baa5..4a4b237 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -23,7 +23,7 @@ obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/
obj-$(CONFIG_SPL_SPI_SUPPORT) += spi/
obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/
obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/
-obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/
+obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/
obj-$(CONFIG_SPL_NAND_SUPPORT) += mtd/nand/
obj-$(CONFIG_SPL_ONENAND_SUPPORT) += mtd/onenand/
@@ -52,7 +52,7 @@ endif
ifdef CONFIG_TPL_BUILD
obj-$(CONFIG_TPL_I2C_SUPPORT) += i2c/
-obj-$(CONFIG_TPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/
+obj-$(CONFIG_TPL_DRIVERS_MISC_SUPPORT) += misc/ sysreset/ firmware/
obj-$(CONFIG_TPL_MMC_SUPPORT) += mmc/
obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
obj-$(CONFIG_TPL_NAND_SUPPORT) += mtd/nand/
@@ -71,6 +71,7 @@ obj-y += block/
obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_CPU) += cpu/
obj-y += crypto/
+obj-y += firmware/
obj-$(CONFIG_FPGA) += fpga/
obj-y += hwmon/
obj-y += misc/
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
new file mode 100644
index 0000000..4c32426
--- /dev/null
+++ b/drivers/firmware/Kconfig
@@ -0,0 +1,6 @@
+config FIRMWARE
+ bool
+
+config ARM_PSCI_FW
+ bool
+ select FIRMWARE
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
new file mode 100644
index 0000000..b208255
--- /dev/null
+++ b/drivers/firmware/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_FIRMWARE) += firmware-uclass.o
+obj-$(CONFIG_ARM_PSCI_FW) += psci.o
diff --git a/drivers/firmware/firmware-uclass.c b/drivers/firmware/firmware-uclass.c
new file mode 100644
index 0000000..01b6a44
--- /dev/null
+++ b/drivers/firmware/firmware-uclass.c
@@ -0,0 +1,11 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/uclass.h>
+
+/* Firmware access is platform-dependent. No generic code in uclass */
+UCLASS_DRIVER(firmware) = {
+ .id = UCLASS_FIRMWARE,
+ .name = "firmware",
+};
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
new file mode 100644
index 0000000..40fba64
--- /dev/null
+++ b/drivers/firmware/psci.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * Based on drivers/firmware/psci.c from Linux:
+ * Copyright (C) 2015 ARM Limited
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm/device.h>
+#include <dm/lists.h>
+#include <libfdt.h>
+#include <linux/arm-smccc.h>
+#include <linux/errno.h>
+#include <linux/psci.h>
+
+psci_fn *invoke_psci_fn;
+
+static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
+ unsigned long arg0, unsigned long arg1,
+ unsigned long arg2)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
+ unsigned long arg0, unsigned long arg1,
+ unsigned long arg2)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static int psci_bind(struct udevice *dev)
+{
+ /* No SYSTEM_RESET support for PSCI 0.1 */
+ if (of_device_is_compatible(dev, "arm,psci-0.2") ||
+ of_device_is_compatible(dev, "arm,psci-1.0")) {
+ int ret;
+
+ /* bind psci-sysreset optionally */
+ ret = device_bind_driver(dev, "psci-sysreset", "psci-sysreset",
+ NULL);
+ if (ret)
+ debug("PSCI System Reset was not bound.\n");
+ }
+
+ return 0;
+}
+
+static int psci_probe(struct udevice *dev)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ const char *method;
+
+ method = fdt_stringlist_get(gd->fdt_blob, dev->of_offset, "method", 0,
+ NULL);
+ if (!method) {
+ printf("missing \"method\" property\n");
+ return -ENXIO;
+ }
+
+ if (!strcmp("hvc", method)) {
+ invoke_psci_fn = __invoke_psci_fn_hvc;
+ } else if (!strcmp("smc", method)) {
+ invoke_psci_fn = __invoke_psci_fn_smc;
+ } else {
+ printf("invalid \"method\" property: %s\n", method);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id psci_of_match[] = {
+ { .compatible = "arm,psci" },
+ { .compatible = "arm,psci-0.2" },
+ { .compatible = "arm,psci-1.0" },
+ {},
+};
+
+U_BOOT_DRIVER(psci) = {
+ .name = "psci",
+ .id = UCLASS_FIRMWARE,
+ .of_match = psci_of_match,
+ .bind = psci_bind,
+ .probe = psci_probe,
+};
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index 05a37b9..9664630 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -13,4 +13,14 @@ config SYSRESET
to effect a reset. The uclass will try all available drivers when
reset_walk() is called.
+if SYSRESET
+
+config SYSRESET_PSCI
+ bool "Enable support for PSCI System Reset"
+ depends on ARM_PSCI_FW
+ help
+ Enable PSCI SYSTEM_RESET function call. To use this, PSCI firmware
+ must be running on your system.
+
+endif
endmenu
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index 49b8bb6..7bb8406 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -5,6 +5,7 @@
#
obj-$(CONFIG_SYSRESET) += sysreset-uclass.o
+obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ROCKCHIP_RK3036) += sysreset_rk3036.o
diff --git a/drivers/sysreset/sysreset_psci.c b/drivers/sysreset/sysreset_psci.c
new file mode 100644
index 0000000..a4911b7
--- /dev/null
+++ b/drivers/sysreset/sysreset_psci.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <dm/device.h>
+#include <sysreset.h>
+#include <linux/errno.h>
+#include <linux/psci.h>
+
+static int psci_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+ unsigned long function_id;
+
+ switch (type) {
+ case SYSRESET_WARM:
+ case SYSRESET_COLD:
+ function_id = PSCI_0_2_FN_SYSTEM_RESET;
+ break;
+ case SYSRESET_POWER:
+ function_id = PSCI_0_2_FN_SYSTEM_OFF;
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ invoke_psci_fn(function_id, 0, 0, 0);
+
+ return -EINPROGRESS;
+}
+
+static struct sysreset_ops psci_sysreset_ops = {
+ .request = psci_sysreset_request,
+};
+
+U_BOOT_DRIVER(psci_sysreset) = {
+ .name = "psci-sysreset",
+ .id = UCLASS_SYSRESET,
+ .ops = &psci_sysreset_ops,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 8c92d0b..1b635e4 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -35,6 +35,7 @@ enum uclass_id {
UCLASS_DMA, /* Direct Memory Access */
UCLASS_ETH, /* Ethernet device */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
+ UCLASS_FIRMWARE, /* Firmware */
UCLASS_I2C, /* I2C bus */
UCLASS_I2C_EEPROM, /* I2C EEPROM device */
UCLASS_I2C_GENERIC, /* Generic I2C device */
diff --git a/include/linux/psci.h b/include/linux/psci.h
index 310d83e..8d13bd2 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -87,4 +87,17 @@
#define PSCI_RET_NOT_PRESENT -7
#define PSCI_RET_DISABLED -8
+#ifdef CONFIG_ARM_PSCI_FW
+typedef unsigned long (psci_fn)(unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
+extern psci_fn *invoke_psci_fn;
+#else
+unsigned long invoke_psci_fn(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3)
+{
+ return PSCI_RET_DISABLED;
+}
+#endif
+
#endif /* _UAPI_LINUX_PSCI_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [U-Boot] [PATCH v2 2/3] ARM: adjust arm-smccc code for use in U-Boot
2017-04-13 2:39 ` [U-Boot] [PATCH v2 2/3] ARM: adjust arm-smccc code for use in U-Boot Masahiro Yamada
@ 2017-04-13 13:57 ` Masahiro Yamada
0 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2017-04-13 13:57 UTC (permalink / raw)
To: u-boot
Self-review.
2017-04-13 11:39 GMT+09:00 Masahiro Yamada <yamada.masahiro@socionext.com>:
> Adjust ARM SMC Calling Convention code for U-Boot:
> - Replace the license block with SPDX
> - Change path to asm-offsets.h
> - Define UNWIND() as no-op
> - Add Kconfig entry
> - Add asm-offsets
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> #ifndef __ASM_ARM_OPCODES_SEC_H
> diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
> index efcfdf9..923f257 100644
> --- a/arch/arm/include/asm/opcodes-virt.h
> +++ b/arch/arm/include/asm/opcodes-virt.h
> @@ -2,19 +2,7 @@
> * opcodes-virt.h: Opcode definitions for the ARM virtualization extensions
> * Copyright (C) 2012 Linaro Limited
> *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * 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, write to the Free Software Foundation, Inc.,
> - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + * SPDX-License-Identifier: GPL-2.0
> */
I noticed my misconversion.
This should be GPL-2.0+
--
Best Regards
Masahiro Yamada
^ permalink raw reply [flat|nested] 7+ messages in thread
* [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI
2017-04-13 2:39 ` [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI Masahiro Yamada
@ 2017-04-16 19:31 ` Simon Glass
2017-04-17 2:26 ` Masahiro Yamada
0 siblings, 1 reply; 7+ messages in thread
From: Simon Glass @ 2017-04-16 19:31 UTC (permalink / raw)
To: u-boot
Hi Masahiro,
On 12 April 2017 at 20:39, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> If the system is running PSCI firmware, the System Reset function
> (func ID: 0x80000009) is supposed to be handled by PSCI, that is,
> the SoC/board specific reset implementation should be moved to PSCI.
> U-Boot should call the PSCI service according to the arm-smccc
> manner.
>
> The arm-smccc is supported on ARMv7 or later. Especially, ARMv8
> generation SoCs are likely to run ARM Trusted Firmware BL31. In
> this case, U-Boot is a non-secure world boot loader, so it should
> not be able to reset the system directly.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
> Changes in v2: None
>
> arch/arm/Kconfig | 1 +
> drivers/Kconfig | 2 +
> drivers/Makefile | 5 +-
> drivers/firmware/Kconfig | 6 +++
> drivers/firmware/Makefile | 2 +
> drivers/firmware/firmware-uclass.c | 11 +++++
> drivers/firmware/psci.c | 94 ++++++++++++++++++++++++++++++++++++++
> drivers/sysreset/Kconfig | 10 ++++
> drivers/sysreset/Makefile | 1 +
> drivers/sysreset/sysreset_psci.c | 41 +++++++++++++++++
> include/dm/uclass-id.h | 1 +
> include/linux/psci.h | 13 ++++++
> 12 files changed, 185 insertions(+), 2 deletions(-)
> create mode 100644 drivers/firmware/Kconfig
> create mode 100644 drivers/firmware/Makefile
> create mode 100644 drivers/firmware/firmware-uclass.c
> create mode 100644 drivers/firmware/psci.c
> create mode 100644 drivers/sysreset/sysreset_psci.c
Reviewed-by: Simon Glass <sjg@chromium.org>
It is not clear what the firmware uclass is for. Also there are no
operations. How about adding a header file with at least a comment in
it?
- Simon
^ permalink raw reply [flat|nested] 7+ messages in thread
* [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI
2017-04-16 19:31 ` Simon Glass
@ 2017-04-17 2:26 ` Masahiro Yamada
0 siblings, 0 replies; 7+ messages in thread
From: Masahiro Yamada @ 2017-04-17 2:26 UTC (permalink / raw)
To: u-boot
Hi Simon,
2017-04-17 4:31 GMT+09:00 Simon Glass <sjg@chromium.org>:
> Hi Masahiro,
>
> On 12 April 2017 at 20:39, Masahiro Yamada
> <yamada.masahiro@socionext.com> wrote:
>> If the system is running PSCI firmware, the System Reset function
>> (func ID: 0x80000009) is supposed to be handled by PSCI, that is,
>> the SoC/board specific reset implementation should be moved to PSCI.
>> U-Boot should call the PSCI service according to the arm-smccc
>> manner.
>>
>> The arm-smccc is supported on ARMv7 or later. Especially, ARMv8
>> generation SoCs are likely to run ARM Trusted Firmware BL31. In
>> this case, U-Boot is a non-secure world boot loader, so it should
>> not be able to reset the system directly.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>> ---
>>
>> Changes in v2: None
>>
>> arch/arm/Kconfig | 1 +
>> drivers/Kconfig | 2 +
>> drivers/Makefile | 5 +-
>> drivers/firmware/Kconfig | 6 +++
>> drivers/firmware/Makefile | 2 +
>> drivers/firmware/firmware-uclass.c | 11 +++++
>> drivers/firmware/psci.c | 94 ++++++++++++++++++++++++++++++++++++++
>> drivers/sysreset/Kconfig | 10 ++++
>> drivers/sysreset/Makefile | 1 +
>> drivers/sysreset/sysreset_psci.c | 41 +++++++++++++++++
>> include/dm/uclass-id.h | 1 +
>> include/linux/psci.h | 13 ++++++
>> 12 files changed, 185 insertions(+), 2 deletions(-)
>> create mode 100644 drivers/firmware/Kconfig
>> create mode 100644 drivers/firmware/Makefile
>> create mode 100644 drivers/firmware/firmware-uclass.c
>> create mode 100644 drivers/firmware/psci.c
>> create mode 100644 drivers/sysreset/sysreset_psci.c
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> It is not clear what the firmware uclass is for. Also there are no
> operations. How about adding a header file with at least a comment in
> it?
Actually, the firmware uclass does not provide
any generalized operation, but in the DM framework,
a driver must belong to some uclass.
I thought about this a bit, then
another idea is perhaps to re-use UCLASS_MISC
instead of adding a new opaque uclass.
We can use misc_ioctl() for PSCI call.
--
Best Regards
Masahiro Yamada
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-04-17 2:26 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-13 2:39 [U-Boot] [PATCH v2 0/3] ARM: support System Reset via PSCI Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 1/3] ARM: import arm-smccc code from Linux 4.11-rc6 Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 2/3] ARM: adjust arm-smccc code for use in U-Boot Masahiro Yamada
2017-04-13 13:57 ` Masahiro Yamada
2017-04-13 2:39 ` [U-Boot] [PATCH v2 3/3] sysreset: psci: support system reset in a generic way with PSCI Masahiro Yamada
2017-04-16 19:31 ` Simon Glass
2017-04-17 2:26 ` Masahiro Yamada
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.