diff options
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/Kconfig | 40 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/clk_synthesizer.c | 104 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/config.mk | 20 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap-common/Kconfig | 17 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap-common/clocks-common.c | 8 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap-common/config_secure.mk | 66 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap-common/hwinit-common.c | 22 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap5/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap5/config.mk | 6 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/omap5/fdt.c | 184 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/cache.S | 26 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fwcall.c | 16 |
13 files changed, 491 insertions, 21 deletions
diff --git a/arch/arm/cpu/armv7/am33xx/Kconfig b/arch/arm/cpu/armv7/am33xx/Kconfig new file mode 100644 index 0000000000..dc51e9b697 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/Kconfig @@ -0,0 +1,40 @@ +if AM43XX +config TARGET_AM43XX_EVM + bool "Support am43xx_evm" + select TI_I2C_BOARD_DETECT + help + This option specifies support for the AM43xx + GP and HS EVM development platforms.The AM437x + GP EVM is a standalone test, development, and + evaluation module system that enables developers + to write software and develop hardware around + an AM43xx processor subsystem. + +config ISW_ENTRY_ADDR + hex "Address in memory or XIP flash of bootloader entry point" + help + After any reset, the boot ROM on the AM43XX SOC + searches the boot media for a valid boot image. + For non-XIP devices, the ROM then copies the + image into internal memory. + For all boot modes, after the ROM processes the + boot image it eventually computes the entry + point address depending on the device type + (secure/non-secure), boot media (xip/non-xip) and + image headers. + default 0x402F4000 + +config PUB_ROM_DATA_SIZE + hex "Size in bytes of the L3 SRAM reserved by ROM to store data" + help + During the device boot, the public ROM uses the top of + the public L3 OCMC RAM to store r/w data like stack, + heap, globals etc. When the ROM is copying the boot + image from the boot media into memory, the image must + not spill over into this area. This value can be used + during compile time to determine the maximum size of a + boot image. Once the ROM transfers control to the boot + image, this area is no longer used, and can be reclaimed + for run time use by the boot image. + default 0x8400 +endif diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile index aae3f096b2..6fda4825fc 100644 --- a/arch/arm/cpu/armv7/am33xx/Makefile +++ b/arch/arm/cpu/armv7/am33xx/Makefile @@ -18,3 +18,5 @@ obj-y += ddr.o obj-y += emif4.o obj-y += board.o obj-y += mux.o + +obj-$(CONFIG_CLOCK_SYNTHESIZER) += clk_synthesizer.o diff --git a/arch/arm/cpu/armv7/am33xx/clk_synthesizer.c b/arch/arm/cpu/armv7/am33xx/clk_synthesizer.c new file mode 100644 index 0000000000..316e677c65 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/clk_synthesizer.c @@ -0,0 +1,104 @@ +/* + * clk-synthesizer.c + * + * Clock synthesizer apis + * + * Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include <common.h> +#include <asm/arch/clk_synthesizer.h> +#include <i2c.h> + +/** + * clk_synthesizer_reg_read - Read register from synthesizer. + * @addr: addr within the i2c device + * buf: Buffer to which value is to be read. + * + * For reading the register from this clock synthesizer, a command needs to + * be send along with enabling byte read more, and then read can happen. + * Returns 0 on success + */ +static int clk_synthesizer_reg_read(int addr, uint8_t *buf) +{ + int rc; + + /* Enable Bye read */ + addr = addr | CLK_SYNTHESIZER_BYTE_MODE; + + /* Send the command byte */ + rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); + if (rc) + printf("Failed to send command to clock synthesizer\n"); + + /* Read the Data */ + return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); +} + +/** + * clk_synthesizer_reg_write - Write a value to register in synthesizer. + * @addr: addr within the i2c device + * val: Value to be written in the addr. + * + * Enable the byte read mode in the address and start the i2c transfer. + * Returns 0 on success + */ +static int clk_synthesizer_reg_write(int addr, uint8_t val) +{ + uint8_t cmd[2]; + int rc = 0; + + /* Enable byte write */ + cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE; + cmd[1] = val; + + rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2); + if (rc) + printf("Clock synthesizer reg write failed at addr = 0x%x\n", + addr); + return rc; +} + +/** + * setup_clock_syntherizer - Program the clock synthesizer to get the desired + * frequency. + * @data: Data containing the desired output + * + * This is a PLL-based high performance synthesizer which gives 3 outputs + * as per the PLL_DIV and load capacitor programmed. + */ +int setup_clock_synthesizer(struct clk_synth *data) +{ + int rc; + uint8_t val; + + rc = i2c_probe(CLK_SYNTHESIZER_I2C_ADDR); + if (rc) { + printf("i2c probe failed at address 0x%x\n", + CLK_SYNTHESIZER_I2C_ADDR); + return rc; + } + + rc = clk_synthesizer_reg_read(CLK_SYNTHESIZER_ID_REG, &val); + if (val != data->id) + return rc; + + /* Crystal Load capacitor selection */ + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_XCSEL, data->capacitor); + if (rc) + return rc; + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_MUX_REG, data->mux); + if (rc) + return rc; + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV2_REG, data->pdiv2); + if (rc) + return rc; + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV3_REG, data->pdiv3); + if (rc) + return rc; + + return 0; +} diff --git a/arch/arm/cpu/armv7/am33xx/config.mk b/arch/arm/cpu/armv7/am33xx/config.mk index 5294d16708..6d95d327b4 100644 --- a/arch/arm/cpu/armv7/am33xx/config.mk +++ b/arch/arm/cpu/armv7/am33xx/config.mk @@ -3,9 +3,29 @@ # # SPDX-License-Identifier: GPL-2.0+ # + +include $(srctree)/$(CPUDIR)/omap-common/config_secure.mk + ifdef CONFIG_SPL_BUILD +ifeq ($(CONFIG_TI_SECURE_DEVICE),y) +# +# For booting from SPI use +# u-boot-spl_HS_SPI_X-LOADER to program flash +# +# For booting spl from all other media +# use u-boot-spl_HS_ISSW +# +# Refer to README.ti-secure for more info +# +ALL-y += u-boot-spl_HS_ISSW +ALL-$(CONFIG_SPL_SPI_SUPPORT) += u-boot-spl_HS_SPI_X-LOADER +else ALL-y += MLO ALL-$(CONFIG_SPL_SPI_SUPPORT) += MLO.byteswap +endif else +ifeq ($(CONFIG_TI_SECURE_DEVICE),y) +ALL-$(CONFIG_QSPI_BOOT) += u-boot_HS_XIP_X-LOADER +endif ALL-y += u-boot.img endif diff --git a/arch/arm/cpu/armv7/omap-common/Kconfig b/arch/arm/cpu/armv7/omap-common/Kconfig new file mode 100644 index 0000000000..7b39506ae8 --- /dev/null +++ b/arch/arm/cpu/armv7/omap-common/Kconfig @@ -0,0 +1,17 @@ +config TI_SECURE_DEVICE + bool "HS Device Type Support" + depends on OMAP54XX || AM43XX + help + If a high secure (HS) device type is being used, this config + must be set. This option impacts various aspects of the + build system (to create signed boot images that can be + authenticated) and the code. See the doc/README.ti-secure + file for further details. + +source "arch/arm/cpu/armv7/omap3/Kconfig" + +source "arch/arm/cpu/armv7/omap4/Kconfig" + +source "arch/arm/cpu/armv7/omap5/Kconfig" + +source "arch/arm/cpu/armv7/am33xx/Kconfig" diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c index ef2ac98217..2de9935765 100644 --- a/arch/arm/cpu/armv7/omap-common/clocks-common.c +++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c @@ -236,6 +236,8 @@ static void do_setup_dpll(u32 const base, const struct dpll_params *params, /* Dpll locked with ideal values for nominal opps. */ debug("\n %s Dpll already locked with ideal" "nominal opp values", dpll); + + bypass_dpll(base); goto setup_post_dividers; } } @@ -251,13 +253,13 @@ static void do_setup_dpll(u32 const base, const struct dpll_params *params, writel(temp, &dpll_regs->cm_clksel_dpll); +setup_post_dividers: + setup_post_dividers(base, params); + /* Lock */ if (lock) do_lock_dpll(base); -setup_post_dividers: - setup_post_dividers(base, params); - /* Wait till the DPLL locks */ if (lock) wait_for_lock(base); diff --git a/arch/arm/cpu/armv7/omap-common/config_secure.mk b/arch/arm/cpu/armv7/omap-common/config_secure.mk new file mode 100644 index 0000000000..c7bb101be8 --- /dev/null +++ b/arch/arm/cpu/armv7/omap-common/config_secure.mk @@ -0,0 +1,66 @@ +# +# Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# +quiet_cmd_mkomapsecimg = MKIMAGE $@ +ifneq ($(TI_SECURE_DEV_PKG),) +ifneq ($(wildcard $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh),) +ifneq ($(CONFIG_SPL_BUILD),) +cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \ + $(patsubst u-boot-spl_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) +else +cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \ + $(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) +endif +else +cmd_mkomapsecimg = echo "WARNING:" \ + "$(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh not found." \ + "$@ was NOT created!" +endif +else +cmd_mkomapsecimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \ + "variable must be defined for TI secure devices. $@ was NOT created!" +endif + +# Standard X-LOADER target (QPSI, NOR flash) +u-boot-spl_HS_X-LOADER: $(obj)/u-boot-spl.bin + $(call if_changed,mkomapsecimg) + +# For MLO targets (SD card boot) the final file name +# that is copied to the SD card fAT partition must +# be MLO, so we make a copy of the output file to a +# new file with that name +u-boot-spl_HS_MLO: $(obj)/u-boot-spl.bin + $(call if_changed,mkomapsecimg) + @if [ -f $@ ]; then \ + cp -f $@ MLO; \ + fi + +# Standard 2ND target (certain peripheral boot modes) +u-boot-spl_HS_2ND: $(obj)/u-boot-spl.bin + $(call if_changed,mkomapsecimg) + +# Standard ULO target (certain peripheral boot modes) +u-boot-spl_HS_ULO: $(obj)/u-boot-spl.bin + $(call if_changed,mkomapsecimg) + +# Standard ISSW target (certain devices, various boot modes) +u-boot-spl_HS_ISSW: $(obj)/u-boot-spl.bin + $(call if_changed,mkomapsecimg) + +# For SPI flash on AM335x and AM43xx, these +# require special byte swap handling so we use +# the SPI_X-LOADER target instead of X-LOADER +# and let the create-boot-image.sh script handle +# that +u-boot-spl_HS_SPI_X-LOADER: $(obj)/u-boot-spl.bin + $(call if_changed,mkomapsecimg) + +# For supporting single stage XiP QSPI on AM43xx, the +# image is a full u-boot file, not an SPL. In this case +# the mkomapsecimg command looks for a u-boot-HS_* prefix +u-boot_HS_XIP_X-LOADER: $(obj)/u-boot.bin + $(call if_changed,mkomapsecimg) diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index 01c2d576c9..078bdd800c 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -65,12 +65,30 @@ static void omap_rev_string(void) u32 major_rev = (omap_rev & 0x00000F00) >> 8; u32 minor_rev = (omap_rev & 0x000000F0) >> 4; + const char *sec_s; + + switch (get_device_type()) { + case TST_DEVICE: + sec_s = "TST"; + break; + case EMU_DEVICE: + sec_s = "EMU"; + break; + case HS_DEVICE: + sec_s = "HS"; + break; + case GP_DEVICE: + sec_s = "GP"; + break; + default: + sec_s = "?"; + } + if (soc_variant) printf("OMAP"); else printf("DRA"); - printf("%x ES%x.%x\n", omap_variant, major_rev, - minor_rev); + printf("%x-%s ES%x.%x\n", omap_variant, sec_s, major_rev, minor_rev); } #ifdef CONFIG_SPL_BUILD diff --git a/arch/arm/cpu/armv7/omap5/Makefile b/arch/arm/cpu/armv7/omap5/Makefile index f2930d521c..3caba86791 100644 --- a/arch/arm/cpu/armv7/omap5/Makefile +++ b/arch/arm/cpu/armv7/omap5/Makefile @@ -12,4 +12,5 @@ obj-y += sdram.o obj-y += prcm-regs.o obj-y += hw_data.o obj-y += abb.o +obj-y += fdt.o obj-$(CONFIG_IODELAY_RECALIBRATION) += dra7xx_iodelay.o diff --git a/arch/arm/cpu/armv7/omap5/config.mk b/arch/arm/cpu/armv7/omap5/config.mk index ef2725affa..a7e55a5e24 100644 --- a/arch/arm/cpu/armv7/omap5/config.mk +++ b/arch/arm/cpu/armv7/omap5/config.mk @@ -6,8 +6,14 @@ # SPDX-License-Identifier: GPL-2.0+ # +include $(srctree)/$(CPUDIR)/omap-common/config_secure.mk + ifdef CONFIG_SPL_BUILD +ifeq ($(CONFIG_TI_SECURE_DEVICE),y) +ALL-y += u-boot-spl_HS_MLO u-boot-spl_HS_X-LOADER +else ALL-y += MLO +endif else ALL-y += u-boot.img endif diff --git a/arch/arm/cpu/armv7/omap5/fdt.c b/arch/arm/cpu/armv7/omap5/fdt.c new file mode 100644 index 0000000000..0493cd1eab --- /dev/null +++ b/arch/arm/cpu/armv7/omap5/fdt.c @@ -0,0 +1,184 @@ +/* + * Copyright 2016 Texas Instruments, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <libfdt.h> +#include <fdt_support.h> +#include <malloc.h> + +#include <asm/omap_common.h> +#include <asm/arch-omap5/sys_proto.h> + +#ifdef CONFIG_TI_SECURE_DEVICE + +/* Give zero values if not already defined */ +#ifndef TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ +#define TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ (0) +#endif +#ifndef CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ +#define CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ (0) +#endif + +static u32 hs_irq_skip[] = { + 8, /* Secure violation reporting interrupt */ + 15, /* One interrupt for SDMA by secure world */ + 118 /* One interrupt for Crypto DMA by secure world */ +}; + +static int ft_hs_fixup_crossbar(void *fdt, bd_t *bd) +{ + const char *path; + int offs; + int ret; + int len, i, old_cnt, new_cnt; + u32 *temp; + const u32 *p_data; + + /* + * Increase the size of the fdt + * so we have some breathing room + */ + ret = fdt_increase_size(fdt, 512); + if (ret < 0) { + printf("Could not increase size of device tree: %s\n", + fdt_strerror(ret)); + return ret; + } + + /* Reserve IRQs that are used/needed by secure world */ + path = "/ocp/crossbar"; + offs = fdt_path_offset(fdt, path); + if (offs < 0) { + debug("Node %s not found.\n", path); + return 0; + } + + /* Get current entries */ + p_data = fdt_getprop(fdt, offs, "ti,irqs-skip", &len); + if (p_data) + old_cnt = len / sizeof(u32); + else + old_cnt = 0; + + new_cnt = sizeof(hs_irq_skip) / + sizeof(hs_irq_skip[0]); + + /* Create new/updated skip list for HS parts */ + temp = malloc(sizeof(u32) * (old_cnt + new_cnt)); + for (i = 0; i < new_cnt; i++) + temp[i] = cpu_to_fdt32(hs_irq_skip[i]); + for (i = 0; i < old_cnt; i++) + temp[i + new_cnt] = p_data[i]; + + /* Blow away old data and set new data */ + fdt_delprop(fdt, offs, "ti,irqs-skip"); + ret = fdt_setprop(fdt, offs, "ti,irqs-skip", + temp, + (old_cnt + new_cnt) * sizeof(u32)); + free(temp); + + /* Check if the update worked */ + if (ret < 0) { + printf("Could not add ti,irqs-skip property to node %s: %s\n", + path, fdt_strerror(ret)); + return ret; + } + + return 0; +} + +static int ft_hs_disable_rng(void *fdt, bd_t *bd) +{ + const char *path; + int offs; + int ret; + + /* Make HW RNG reserved for secure world use */ + path = "/ocp/rng"; + offs = fdt_path_offset(fdt, path); + if (offs < 0) { + debug("Node %s not found.\n", path); + return 0; + } + ret = fdt_setprop_string(fdt, offs, + "status", "disabled"); + if (ret < 0) { + printf("Could not add status property to node %s: %s\n", + path, fdt_strerror(ret)); + return ret; + } + return 0; +} + +#if ((TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ != 0) || \ + (CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ != 0)) +static int ft_hs_fixup_sram(void *fdt, bd_t *bd) +{ + const char *path; + int offs; + int ret; + u32 temp[2]; + + /* + * Update SRAM reservations on secure devices. The OCMC RAM + * is always reserved for secure use from the start of that + * memory region + */ + path = "/ocp/ocmcram@40300000/sram-hs"; + offs = fdt_path_offset(fdt, path); + if (offs < 0) { + debug("Node %s not found.\n", path); + return 0; + } + + /* relative start offset */ + temp[0] = cpu_to_fdt32(0); + /* reservation size */ + temp[1] = cpu_to_fdt32(max(TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ, + CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ)); + fdt_delprop(fdt, offs, "reg"); + ret = fdt_setprop(fdt, offs, "reg", temp, 2 * sizeof(u32)); + if (ret < 0) { + printf("Could not add reg property to node %s: %s\n", + path, fdt_strerror(ret)); + return ret; + } + + return 0; +} +#else +static int ft_hs_fixup_sram(void *fdt, bd_t *bd) { return 0; } +#endif + +static void ft_hs_fixups(void *fdt, bd_t *bd) +{ + /* Check we are running on an HS/EMU device type */ + if (GP_DEVICE != get_device_type()) { + if ((ft_hs_fixup_crossbar(fdt, bd) == 0) && + (ft_hs_disable_rng(fdt, bd) == 0) && + (ft_hs_fixup_sram(fdt, bd) == 0)) + return; + } else { + printf("ERROR: Incorrect device type (GP) detected!"); + } + /* Fixup failed or wrong device type */ + hang(); +} +#else +static void ft_hs_fixups(void *fdt, bd_t *bd) +{ +} +#endif + +/* + * Place for general cpu/SoC FDT fixups. Board specific + * fixups should remain in the board files which is where + * this function should be called from. + */ +void ft_cpu_setup(void *fdt, bd_t *bd) +{ + ft_hs_fixups(fdt, bd); +} diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S index a9f4fec387..46f25e63f0 100644 --- a/arch/arm/cpu/armv8/cache.S +++ b/arch/arm/cpu/armv8/cache.S @@ -14,15 +14,15 @@ #include <linux/linkage.h> /* - * void __asm_flush_dcache_level(level) + * void __asm_dcache_level(level) * - * clean and invalidate one level cache. + * flush or invalidate one level cache. * * x0: cache level - * x1: 0 flush & invalidate, 1 invalidate only + * x1: 0 clean & invalidate, 1 invalidate only * x2~x9: clobbered */ -ENTRY(__asm_flush_dcache_level) +ENTRY(__asm_dcache_level) lsl x12, x0, #1 msr csselr_el1, x12 /* select cache level */ isb /* sync change of cssidr_el1 */ @@ -57,14 +57,14 @@ loop_way: b.ge loop_set ret -ENDPROC(__asm_flush_dcache_level) +ENDPROC(__asm_dcache_level) /* * void __asm_flush_dcache_all(int invalidate_only) * - * x0: 0 flush & invalidate, 1 invalidate only + * x0: 0 clean & invalidate, 1 invalidate only * - * clean and invalidate all data cache by SET/WAY. + * flush or invalidate all data cache by SET/WAY. */ ENTRY(__asm_dcache_all) mov x1, x0 @@ -87,7 +87,7 @@ loop_level: and x12, x12, #7 /* x12 <- cache type */ cmp x12, #2 b.lt skip /* skip if no cache or icache */ - bl __asm_flush_dcache_level /* x1 = 0 flush, 1 invalidate */ + bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */ skip: add x0, x0, #1 /* increment cache level */ cmp x11, x0 @@ -104,19 +104,13 @@ finished: ENDPROC(__asm_dcache_all) ENTRY(__asm_flush_dcache_all) - mov x16, lr mov x0, #0 - bl __asm_dcache_all - mov lr, x16 - ret + b __asm_dcache_all ENDPROC(__asm_flush_dcache_all) ENTRY(__asm_invalidate_dcache_all) - mov x16, lr mov x0, #0x1 - bl __asm_dcache_all - mov lr, x16 - ret + b __asm_dcache_all ENDPROC(__asm_invalidate_dcache_all) /* diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c index 9efcc5ada9..079e250cbe 100644 --- a/arch/arm/cpu/armv8/fwcall.c +++ b/arch/arm/cpu/armv8/fwcall.c @@ -8,6 +8,7 @@ #include <config.h> #include <version.h> #include <asm/macro.h> +#include <asm/psci.h> #include <asm/system.h> /* @@ -73,3 +74,18 @@ void smc_call(struct pt_regs *args) "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"); } + +void __noreturn psci_system_reset(bool conduit_smc) +{ + struct pt_regs regs; + + regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET; + + if (conduit_smc) + smc_call(®s); + else + hvc_call(®s); + + while (1) + ; +} |