
From: Chee Hong Ang chee.hong.ang@intel.com
These secure register access functions allow U-Boot proper running at EL2 (non-secure) to access System Manager's secure registers by calling the ATF's PSCI runtime services (EL3/secure). If these helper functions are called from secure mode (EL3), the helper function will direct access the secure registers without calling the ATF's PSCI runtime services.
Signed-off-by: Chee Hong Ang chee.hong.ang@intel.com --- arch/arm/mach-socfpga/Makefile | 2 + .../mach-socfpga/include/mach/secure_reg_helper.h | 20 +++++++ arch/arm/mach-socfpga/secure_reg_helper.c | 67 ++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 arch/arm/mach-socfpga/include/mach/secure_reg_helper.h create mode 100644 arch/arm/mach-socfpga/secure_reg_helper.c
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 3310e92..4b46b65 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -34,6 +34,7 @@ obj-y += mailbox_s10.o obj-y += misc_s10.o obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o +obj-y += secure_reg_helper.o obj-y += system_manager_s10.o obj-y += timer_s10.o obj-y += wrap_pinmux_config_s10.o @@ -47,6 +48,7 @@ obj-y += mailbox_s10.o obj-y += misc_s10.o obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o +obj-y += secure_reg_helper.o obj-y += system_manager_s10.o obj-y += timer_s10.o obj-y += wrap_pinmux_config_s10.o diff --git a/arch/arm/mach-socfpga/include/mach/secure_reg_helper.h b/arch/arm/mach-socfpga/include/mach/secure_reg_helper.h new file mode 100644 index 0000000..0dc6534 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/secure_reg_helper.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2019 Intel Corporation <www.intel.com> + * + */ + +#ifndef _SECURE_REG_HELPER_H_ +#define _SECURE_REG_HELPER_H_ + +#ifdef CONFIG_ARM_SMCCC +u32 socfpga_secure_reg_read32(phys_addr_t reg_addr); +void socfpga_secure_reg_write32(u32 val, phys_addr_t reg_addr); +void socfpga_secure_reg_update32(phys_addr_t reg_addr, u32 mask, u32 val); +#else +#define socfpga_secure_reg_read32 readl +#define socfpga_secure_reg_write32 writel +#define socfpga_secure_reg_update32 clrsetbits_le32 +#endif + +#endif /* _SECURE_REG_HELPER_H_ */ diff --git a/arch/arm/mach-socfpga/secure_reg_helper.c b/arch/arm/mach-socfpga/secure_reg_helper.c new file mode 100644 index 0000000..2968fab --- /dev/null +++ b/arch/arm/mach-socfpga/secure_reg_helper.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch/misc.h> +#include <linux/intel-smc.h> + +u32 socfpga_secure_reg_read32(phys_addr_t reg_addr) +{ + int ret; + u64 ret_arg; + u64 args[1]; + + if (current_el() == 3) + return readl(reg_addr); + + args[0] = (u64)reg_addr; + ret = invoke_smc(INTEL_SIP_SMC_REG_READ, args, 1, &ret_arg, 1); + if (ret) { + /* SMC call return error */ + hang(); + } + + return ret_arg; +} + +void socfpga_secure_reg_write32(u32 val, phys_addr_t reg_addr) +{ + int ret; + u64 args[2]; + + if (current_el() == 3) { + writel(val, (u32 *)reg_addr); + } else { + args[0] = (u64)reg_addr; + args[1] = val; + ret = invoke_smc(INTEL_SIP_SMC_REG_WRITE, args, 2, NULL, 0); + if (ret) { + /* SMC call return error */ + hang(); + } + } +} + +void socfpga_secure_reg_update32(phys_addr_t reg_addr, u32 mask, u32 val) +{ + int ret; + u64 args[3]; + + if (current_el() == 3) { + clrsetbits_le32(reg_addr, mask, val); + } else { + args[0] = (u64)reg_addr; + args[1] = mask; + args[2] = val; + ret = invoke_smc(INTEL_SIP_SMC_REG_UPDATE, args, 3, NULL, 0); + if (ret) { + /* SMC call return error */ + hang(); + } + } +}