diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/arm/lib | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/arm/lib')
49 files changed, 6363 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/lib/Makefile b/roms/u-boot/arch/arm/lib/Makefile new file mode 100644 index 000000000..7f6633271 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/Makefile @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +lib-$(CONFIG_USE_PRIVATE_LIBGCC) += ashldi3.o ashrdi3.o lshrdi3.o \ + lib1funcs.o uldivmod.o div0.o \ + div64.o muldi3.o + +ifdef CONFIG_CPU_V7M +obj-y += vectors_m.o crt0.o +else ifdef CONFIG_ARM64 +obj-y += crt0_64.o +else +obj-y += vectors.o crt0.o +endif + +ifdef CONFIG_ARM64 +obj-y += setjmp_aarch64.o +else +obj-y += setjmp.o +endif + +ifndef CONFIG_SPL_BUILD +ifdef CONFIG_ARM64 +obj-y += relocate_64.o +else +obj-y += relocate.o +endif + +obj-$(CONFIG_CPU_V7M) += cmd_boot.o +obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o +obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o +obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_CMD_BOOTZ) += bootm.o zimage.o +obj-$(CONFIG_SYS_L2_PL310) += cache-pl310.o +else +obj-$(CONFIG_$(SPL_TPL_)FRAMEWORK) += spl.o +obj-$(CONFIG_SPL_FRAMEWORK) += zimage.o +obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o +endif +obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o +obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o +obj-$(CONFIG_SEMIHOSTING) += semihosting.o + +obj-y += bdinfo.o +obj-y += sections.o +CFLAGS_REMOVE_sections.o := $(LTO_CFLAGS) + +obj-y += stack.o +ifdef CONFIG_CPU_V7M +obj-y += interrupts_m.o +else ifdef CONFIG_ARM64 +obj-$(CONFIG_FSL_LAYERSCAPE) += ccn504.o +ifneq ($(CONFIG_GICV2)$(CONFIG_GICV3),) +obj-y += gic_64.o +endif +obj-$(CONFIG_GIC_V3_ITS) += gic-v3-its.o +obj-y += interrupts_64.o +else +obj-y += interrupts.o +endif +ifndef CONFIG_$(SPL_TPL_)SYSRESET +obj-y += reset.o +endif + +obj-y += cache.o +obj-$(CONFIG_SYS_ARM_CACHE_CP15) += cache-cp15.o +CFLAGS_REMOVE_cache-cp15.o := $(LTO_CFLAGS) + +obj-y += psci-dt.o + +obj-$(CONFIG_DEBUG_LL) += debug.o + +# For EABI conformant tool chains, provide eabi_compat() +ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS))) +extra-y += eabi_compat.o +endif + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_$(SPL_)SYS_THUMB_BUILD +asflags-$(CONFIG_HAS_THUMB2) += -DCONFIG_THUMB2_KERNEL +ifndef CONFIG_HAS_THUMB2 + +# for C files, just apend -marm, which will override previous -mthumb* + +ifndef CONFIG_ARM64 +CFLAGS_cache.o := -marm +CFLAGS_cache-cp15.o := -marm +endif + +# For .S, drop -mthumb* and other thumb-related options. +# CFLAGS_REMOVE_* would not have an effet, so AFLAGS_REMOVE_* +# was implemented and is used here. +# Also, define ${target}_NO_THUMB_BUILD for these two targets +# so that the code knows it should not use Thumb. + +AFLAGS_REMOVE_memset.o := -mthumb -mthumb-interwork +AFLAGS_REMOVE_memcpy.o := -mthumb -mthumb-interwork +AFLAGS_memset.o := -DMEMSET_NO_THUMB_BUILD +AFLAGS_memcpy.o := -DMEMCPY_NO_THUMB_BUILD +endif +endif + +# For building EFI apps +CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) +CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI) + +CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI) +CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI) + +extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC) +# TODO: As of v2019.01 the relocation code for the EFI application cannot +# be built on ARMv7-M. +ifndef CONFIG_CPU_V7M +#extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC) +endif +extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC) diff --git a/roms/u-boot/arch/arm/lib/ashldi3.S b/roms/u-boot/arch/arm/lib/ashldi3.S new file mode 100644 index 000000000..6330de483 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/ashldi3.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +.pushsection .text.__ashldi3, "ax" +ENTRY(__ashldi3) +ENTRY(__aeabi_llsl) + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi ah, ah, lsl r2 + movpl ah, al, lsl r3 + ARM( orrmi ah, ah, al, lsr ip ) + THUMB( lsrmi r3, al, ip ) + THUMB( orrmi ah, ah, r3 ) + mov al, al, lsl r2 + ret lr + +ENDPROC(__ashldi3) +ENDPROC(__aeabi_llsl) +.popsection diff --git a/roms/u-boot/arch/arm/lib/ashrdi3.S b/roms/u-boot/arch/arm/lib/ashrdi3.S new file mode 100644 index 000000000..642031234 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/ashrdi3.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +.pushsection .text.__ashrdi3, "ax" +ENTRY(__ashrdi3) +ENTRY(__aeabi_lasr) + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, asr r3 + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) + mov ah, ah, asr r2 + ret lr + +ENDPROC(__ashrdi3) +ENDPROC(__aeabi_lasr) +.popsection diff --git a/roms/u-boot/arch/arm/lib/asm-offsets.c b/roms/u-boot/arch/arm/lib/asm-offsets.c new file mode 100644 index 000000000..1a306ec41 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/asm-offsets.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Adapted from Linux v2.6.36 kernel: arch/powerpc/kernel/asm-offsets.c + * + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ + +#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) +#include <asm/arch/imx-regs.h> +#endif + +int main(void) +{ + /* + * TODO : Check if each entry in this file is really necessary. + * - struct esdramc_regs + * - struct max_regs + * - struct aips_regs + * - struct aipi_regs + * - struct clkctl + * - struct dpll + * are used only for generating asm-offsets.h. + * It means their offset addresses are referenced only from assembly + * code. Is it better to define the macros directly in headers? + */ + +#if defined(CONFIG_MX25) + /* Clock Control Module */ + DEFINE(CCM_CCTL, offsetof(struct ccm_regs, cctl)); + DEFINE(CCM_CGCR0, offsetof(struct ccm_regs, cgr0)); + DEFINE(CCM_CGCR1, offsetof(struct ccm_regs, cgr1)); + DEFINE(CCM_CGCR2, offsetof(struct ccm_regs, cgr2)); + DEFINE(CCM_PCDR2, offsetof(struct ccm_regs, pcdr[2])); + DEFINE(CCM_MCR, offsetof(struct ccm_regs, mcr)); + + /* Enhanced SDRAM Controller */ + DEFINE(ESDRAMC_ESDCTL0, offsetof(struct esdramc_regs, ctl0)); + DEFINE(ESDRAMC_ESDCFG0, offsetof(struct esdramc_regs, cfg0)); + DEFINE(ESDRAMC_ESDMISC, offsetof(struct esdramc_regs, misc)); + + /* Multi-Layer AHB Crossbar Switch */ + DEFINE(MAX_MPR0, offsetof(struct max_regs, mpr0)); + DEFINE(MAX_SGPCR0, offsetof(struct max_regs, sgpcr0)); + DEFINE(MAX_MPR1, offsetof(struct max_regs, mpr1)); + DEFINE(MAX_SGPCR1, offsetof(struct max_regs, sgpcr1)); + DEFINE(MAX_MPR2, offsetof(struct max_regs, mpr2)); + DEFINE(MAX_SGPCR2, offsetof(struct max_regs, sgpcr2)); + DEFINE(MAX_MPR3, offsetof(struct max_regs, mpr3)); + DEFINE(MAX_SGPCR3, offsetof(struct max_regs, sgpcr3)); + DEFINE(MAX_MPR4, offsetof(struct max_regs, mpr4)); + DEFINE(MAX_SGPCR4, offsetof(struct max_regs, sgpcr4)); + DEFINE(MAX_MGPCR0, offsetof(struct max_regs, mgpcr0)); + DEFINE(MAX_MGPCR1, offsetof(struct max_regs, mgpcr1)); + DEFINE(MAX_MGPCR2, offsetof(struct max_regs, mgpcr2)); + DEFINE(MAX_MGPCR3, offsetof(struct max_regs, mgpcr3)); + DEFINE(MAX_MGPCR4, offsetof(struct max_regs, mgpcr4)); + + /* AHB <-> IP-Bus Interface */ + DEFINE(AIPS_MPR_0_7, offsetof(struct aips_regs, mpr_0_7)); + DEFINE(AIPS_MPR_8_15, offsetof(struct aips_regs, mpr_8_15)); +#endif + +#if defined(CONFIG_MX27) + DEFINE(AIPI1_PSR0, IMX_AIPI1_BASE + offsetof(struct aipi_regs, psr0)); + DEFINE(AIPI1_PSR1, IMX_AIPI1_BASE + offsetof(struct aipi_regs, psr1)); + DEFINE(AIPI2_PSR0, IMX_AIPI2_BASE + offsetof(struct aipi_regs, psr0)); + DEFINE(AIPI2_PSR1, IMX_AIPI2_BASE + offsetof(struct aipi_regs, psr1)); + + DEFINE(CSCR, IMX_PLL_BASE + offsetof(struct pll_regs, cscr)); + DEFINE(MPCTL0, IMX_PLL_BASE + offsetof(struct pll_regs, mpctl0)); + DEFINE(SPCTL0, IMX_PLL_BASE + offsetof(struct pll_regs, spctl0)); + DEFINE(PCDR0, IMX_PLL_BASE + offsetof(struct pll_regs, pcdr0)); + DEFINE(PCDR1, IMX_PLL_BASE + offsetof(struct pll_regs, pcdr1)); + DEFINE(PCCR0, IMX_PLL_BASE + offsetof(struct pll_regs, pccr0)); + DEFINE(PCCR1, IMX_PLL_BASE + offsetof(struct pll_regs, pccr1)); + + DEFINE(ESDCTL0_ROF, offsetof(struct esdramc_regs, esdctl0)); + DEFINE(ESDCFG0_ROF, offsetof(struct esdramc_regs, esdcfg0)); + DEFINE(ESDCTL1_ROF, offsetof(struct esdramc_regs, esdctl1)); + DEFINE(ESDCFG1_ROF, offsetof(struct esdramc_regs, esdcfg1)); + DEFINE(ESDMISC_ROF, offsetof(struct esdramc_regs, esdmisc)); + + DEFINE(GPCR, IMX_SYSTEM_CTL_BASE + + offsetof(struct system_control_regs, gpcr)); + DEFINE(FMCR, IMX_SYSTEM_CTL_BASE + + offsetof(struct system_control_regs, fmcr)); +#endif + +#if defined(CONFIG_MX35) + /* Round up to make sure size gives nice stack alignment */ + DEFINE(CLKCTL_CCMR, offsetof(struct ccm_regs, ccmr)); + DEFINE(CLKCTL_PDR0, offsetof(struct ccm_regs, pdr0)); + DEFINE(CLKCTL_PDR1, offsetof(struct ccm_regs, pdr1)); + DEFINE(CLKCTL_PDR2, offsetof(struct ccm_regs, pdr2)); + DEFINE(CLKCTL_PDR3, offsetof(struct ccm_regs, pdr3)); + DEFINE(CLKCTL_PDR4, offsetof(struct ccm_regs, pdr4)); + DEFINE(CLKCTL_RCSR, offsetof(struct ccm_regs, rcsr)); + DEFINE(CLKCTL_MPCTL, offsetof(struct ccm_regs, mpctl)); + DEFINE(CLKCTL_PPCTL, offsetof(struct ccm_regs, ppctl)); + DEFINE(CLKCTL_ACMR, offsetof(struct ccm_regs, acmr)); + DEFINE(CLKCTL_COSR, offsetof(struct ccm_regs, cosr)); + DEFINE(CLKCTL_CGR0, offsetof(struct ccm_regs, cgr0)); + DEFINE(CLKCTL_CGR1, offsetof(struct ccm_regs, cgr1)); + DEFINE(CLKCTL_CGR2, offsetof(struct ccm_regs, cgr2)); + DEFINE(CLKCTL_CGR3, offsetof(struct ccm_regs, cgr3)); + + /* Multi-Layer AHB Crossbar Switch */ + DEFINE(MAX_MPR0, offsetof(struct max_regs, mpr0)); + DEFINE(MAX_SGPCR0, offsetof(struct max_regs, sgpcr0)); + DEFINE(MAX_MPR1, offsetof(struct max_regs, mpr1)); + DEFINE(MAX_SGPCR1, offsetof(struct max_regs, sgpcr1)); + DEFINE(MAX_MPR2, offsetof(struct max_regs, mpr2)); + DEFINE(MAX_SGPCR2, offsetof(struct max_regs, sgpcr2)); + DEFINE(MAX_MPR3, offsetof(struct max_regs, mpr3)); + DEFINE(MAX_SGPCR3, offsetof(struct max_regs, sgpcr3)); + DEFINE(MAX_MPR4, offsetof(struct max_regs, mpr4)); + DEFINE(MAX_SGPCR4, offsetof(struct max_regs, sgpcr4)); + DEFINE(MAX_MGPCR0, offsetof(struct max_regs, mgpcr0)); + DEFINE(MAX_MGPCR1, offsetof(struct max_regs, mgpcr1)); + DEFINE(MAX_MGPCR2, offsetof(struct max_regs, mgpcr2)); + DEFINE(MAX_MGPCR3, offsetof(struct max_regs, mgpcr3)); + DEFINE(MAX_MGPCR4, offsetof(struct max_regs, mgpcr4)); + DEFINE(MAX_MGPCR5, offsetof(struct max_regs, mgpcr5)); + + /* AHB <-> IP-Bus Interface */ + DEFINE(AIPS_MPR_0_7, offsetof(struct aips_regs, mpr_0_7)); + DEFINE(AIPS_MPR_8_15, offsetof(struct aips_regs, mpr_8_15)); + DEFINE(AIPS_PACR_0_7, offsetof(struct aips_regs, pacr_0_7)); + DEFINE(AIPS_PACR_8_15, offsetof(struct aips_regs, pacr_8_15)); + DEFINE(AIPS_PACR_16_23, offsetof(struct aips_regs, pacr_16_23)); + DEFINE(AIPS_PACR_24_31, offsetof(struct aips_regs, pacr_24_31)); + DEFINE(AIPS_OPACR_0_7, offsetof(struct aips_regs, opacr_0_7)); + DEFINE(AIPS_OPACR_8_15, offsetof(struct aips_regs, opacr_8_15)); + DEFINE(AIPS_OPACR_16_23, offsetof(struct aips_regs, opacr_16_23)); + DEFINE(AIPS_OPACR_24_31, offsetof(struct aips_regs, opacr_24_31)); + DEFINE(AIPS_OPACR_32_39, offsetof(struct aips_regs, opacr_32_39)); +#endif + +#if defined(CONFIG_MX51) || defined(CONFIG_MX53) + /* Round up to make sure size gives nice stack alignment */ + DEFINE(CLKCTL_CCMR, offsetof(struct clkctl, ccr)); + DEFINE(CLKCTL_CCDR, offsetof(struct clkctl, ccdr)); + DEFINE(CLKCTL_CSR, offsetof(struct clkctl, csr)); + DEFINE(CLKCTL_CCSR, offsetof(struct clkctl, ccsr)); + DEFINE(CLKCTL_CACRR, offsetof(struct clkctl, cacrr)); + DEFINE(CLKCTL_CBCDR, offsetof(struct clkctl, cbcdr)); + DEFINE(CLKCTL_CBCMR, offsetof(struct clkctl, cbcmr)); + DEFINE(CLKCTL_CSCMR1, offsetof(struct clkctl, cscmr1)); + DEFINE(CLKCTL_CSCMR2, offsetof(struct clkctl, cscmr2)); + DEFINE(CLKCTL_CSCDR1, offsetof(struct clkctl, cscdr1)); + DEFINE(CLKCTL_CS1CDR, offsetof(struct clkctl, cs1cdr)); + DEFINE(CLKCTL_CS2CDR, offsetof(struct clkctl, cs2cdr)); + DEFINE(CLKCTL_CDCDR, offsetof(struct clkctl, cdcdr)); + DEFINE(CLKCTL_CHSCCDR, offsetof(struct clkctl, chsccdr)); + DEFINE(CLKCTL_CSCDR2, offsetof(struct clkctl, cscdr2)); + DEFINE(CLKCTL_CSCDR3, offsetof(struct clkctl, cscdr3)); + DEFINE(CLKCTL_CSCDR4, offsetof(struct clkctl, cscdr4)); + DEFINE(CLKCTL_CWDR, offsetof(struct clkctl, cwdr)); + DEFINE(CLKCTL_CDHIPR, offsetof(struct clkctl, cdhipr)); + DEFINE(CLKCTL_CDCR, offsetof(struct clkctl, cdcr)); + DEFINE(CLKCTL_CTOR, offsetof(struct clkctl, ctor)); + DEFINE(CLKCTL_CLPCR, offsetof(struct clkctl, clpcr)); + DEFINE(CLKCTL_CISR, offsetof(struct clkctl, cisr)); + DEFINE(CLKCTL_CIMR, offsetof(struct clkctl, cimr)); + DEFINE(CLKCTL_CCOSR, offsetof(struct clkctl, ccosr)); + DEFINE(CLKCTL_CGPR, offsetof(struct clkctl, cgpr)); + DEFINE(CLKCTL_CCGR0, offsetof(struct clkctl, ccgr0)); + DEFINE(CLKCTL_CCGR1, offsetof(struct clkctl, ccgr1)); + DEFINE(CLKCTL_CCGR2, offsetof(struct clkctl, ccgr2)); + DEFINE(CLKCTL_CCGR3, offsetof(struct clkctl, ccgr3)); + DEFINE(CLKCTL_CCGR4, offsetof(struct clkctl, ccgr4)); + DEFINE(CLKCTL_CCGR5, offsetof(struct clkctl, ccgr5)); + DEFINE(CLKCTL_CCGR6, offsetof(struct clkctl, ccgr6)); + DEFINE(CLKCTL_CMEOR, offsetof(struct clkctl, cmeor)); +#if defined(CONFIG_MX53) + DEFINE(CLKCTL_CCGR7, offsetof(struct clkctl, ccgr7)); +#endif + + /* DPLL */ + DEFINE(PLL_DP_CTL, offsetof(struct dpll, dp_ctl)); + DEFINE(PLL_DP_CONFIG, offsetof(struct dpll, dp_config)); + DEFINE(PLL_DP_OP, offsetof(struct dpll, dp_op)); + DEFINE(PLL_DP_MFD, offsetof(struct dpll, dp_mfd)); + DEFINE(PLL_DP_MFN, offsetof(struct dpll, dp_mfn)); + DEFINE(PLL_DP_HFS_OP, offsetof(struct dpll, dp_hfs_op)); + DEFINE(PLL_DP_HFS_MFD, offsetof(struct dpll, dp_hfs_mfd)); + 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/roms/u-boot/arch/arm/lib/bdinfo.c b/roms/u-boot/arch/arm/lib/bdinfo.c new file mode 100644 index 000000000..b22ee07b8 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/bdinfo.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ARM-specific information for the 'bd' command + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <common.h> +#include <init.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +void arch_print_bdinfo(void) +{ + struct bd_info *bd = gd->bd; + + bdinfo_print_num_l("arch_number", bd->bi_arch_number); +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + if (gd->arch.secure_ram & MEM_RESERVE_SECURE_SECURED) { + bdinfo_print_num_ll("Secure ram", + gd->arch.secure_ram & + MEM_RESERVE_SECURE_ADDR_MASK); + } +#endif +#ifdef CONFIG_RESV_RAM + if (gd->arch.resv_ram) + bdinfo_print_num_ll("Reserved ram", gd->arch.resv_ram); +#endif +#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + bdinfo_print_num_l("TLB addr", gd->arch.tlb_addr); +#endif + bdinfo_print_num_l("irq_sp", gd->irq_sp); /* irq stack pointer */ + bdinfo_print_num_l("sp start ", gd->start_addr_sp); + /* + * TODO: Currently only support for davinci SOC's is added. + * Remove this check once all the board implement this. + */ +#ifdef CONFIG_CLOCKS + printf("ARM frequency = %ld MHz\n", bd->bi_arm_freq); + printf("DSP frequency = %ld MHz\n", bd->bi_dsp_freq); + printf("DDR frequency = %ld MHz\n", bd->bi_ddr_freq); +#endif +#ifdef CONFIG_BOARD_TYPES + printf("Board Type = %ld\n", gd->board_type); +#endif +#if CONFIG_VAL(SYS_MALLOC_F_LEN) + printf("Early malloc usage: %lx / %x\n", gd->malloc_ptr, + CONFIG_VAL(SYS_MALLOC_F_LEN)); +#endif +} diff --git a/roms/u-boot/arch/arm/lib/bootm-fdt.c b/roms/u-boot/arch/arm/lib/bootm-fdt.c new file mode 100644 index 000000000..29020bd1c --- /dev/null +++ b/roms/u-boot/arch/arm/lib/bootm-fdt.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013, Google Inc. + * + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de> + * - Added prep subcommand support + * - Reorganized source - modeled after powerpc version + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + */ + +#include <common.h> +#include <fdt_support.h> +#ifdef CONFIG_ARMV7_NONSEC +#include <asm/armv7.h> +#endif +#include <asm/global_data.h> +#include <asm/psci.h> +#include <asm/spin_table.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_FMAN_ENET +__weak int fdt_update_ethernet_dt(void *blob) +{ + return 0; +} +#endif + +int arch_fixup_fdt(void *blob) +{ + __maybe_unused int ret = 0; +#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_OF_LIBFDT) + struct bd_info *bd = gd->bd; + int bank; + u64 start[CONFIG_NR_DRAM_BANKS]; + u64 size[CONFIG_NR_DRAM_BANKS]; + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + start[bank] = bd->bi_dram[bank].start; + size[bank] = bd->bi_dram[bank].size; +#ifdef CONFIG_ARMV7_NONSEC + ret = armv7_apply_memory_carveout(&start[bank], &size[bank]); + if (ret) + return ret; +#endif + } + +#ifdef CONFIG_OF_LIBFDT + ret = fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); + if (ret) + return ret; +#endif + +#ifdef CONFIG_ARMV8_SPIN_TABLE + ret = spin_table_update_dt(blob); + if (ret) + return ret; +#endif + +#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV8_PSCI) || \ + CONFIG_IS_ENABLED(SEC_FIRMWARE_ARMV8_PSCI) + ret = psci_update_dt(blob); + if (ret) + return ret; +#endif +#endif + +#ifdef CONFIG_FMAN_ENET + ret = fdt_update_ethernet_dt(blob); + if (ret) + return ret; +#endif + return 0; +} diff --git a/roms/u-boot/arch/arm/lib/bootm.c b/roms/u-boot/arch/arm/lib/bootm.c new file mode 100644 index 000000000..f60ee3a7e --- /dev/null +++ b/roms/u-boot/arch/arm/lib/bootm.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de> + * - Added prep subcommand support + * - Reorganized source - modeled after powerpc version + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + */ + +#include <common.h> +#include <bootstage.h> +#include <command.h> +#include <cpu_func.h> +#include <dm.h> +#include <lmb.h> +#include <log.h> +#include <asm/global_data.h> +#include <dm/root.h> +#include <env.h> +#include <image.h> +#include <u-boot/zlib.h> +#include <asm/byteorder.h> +#include <linux/libfdt.h> +#include <mapmem.h> +#include <fdt_support.h> +#include <asm/bootm.h> +#include <asm/secure.h> +#include <linux/compiler.h> +#include <bootm.h> +#include <vxworks.h> +#include <asm/cache.h> + +#ifdef CONFIG_ARMV7_NONSEC +#include <asm/armv7.h> +#endif +#include <asm/setup.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct tag *params; + +static ulong get_sp(void) +{ + ulong ret; + + asm("mov %0, sp" : "=r"(ret) : ); + return ret; +} + +void arch_lmb_reserve(struct lmb *lmb) +{ + ulong sp, bank_end; + int bank; + + /* + * Booting a (Linux) kernel image + * + * Allocate space for command line and board info - the + * address should be as high as possible within the reach of + * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused + * memory, which means far enough below the current stack + * pointer. + */ + sp = get_sp(); + debug("## Current stack ends at 0x%08lx ", sp); + + /* adjust sp by 4K to be safe */ + sp -= 4096; + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (!gd->bd->bi_dram[bank].size || + sp < gd->bd->bi_dram[bank].start) + continue; + /* Watch out for RAM at end of address space! */ + bank_end = gd->bd->bi_dram[bank].start + + gd->bd->bi_dram[bank].size - 1; + if (sp > bank_end) + continue; + if (bank_end > gd->ram_top) + bank_end = gd->ram_top - 1; + + lmb_reserve(lmb, sp, bank_end - sp + 1); + break; + } +} + +__weak void board_quiesce_devices(void) +{ +} + +/** + * announce_and_cleanup() - Print message and prepare for kernel boot + * + * @fake: non-zero to do everything except actually boot + */ +static void announce_and_cleanup(int fake) +{ + bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); +#ifdef CONFIG_BOOTSTAGE_FDT + bootstage_fdt_add_report(); +#endif +#ifdef CONFIG_BOOTSTAGE_REPORT + bootstage_report(); +#endif + +#ifdef CONFIG_USB_DEVICE + udc_disconnect(); +#endif + + board_quiesce_devices(); + + printf("\nStarting kernel ...%s\n\n", fake ? + "(fake run for tracing)" : ""); + /* + * Call remove function of all devices with a removal flag set. + * This may be useful for last-stage operations, like cancelling + * of DMA operation or releasing device internal buffers. + */ + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL | DM_REMOVE_NON_VITAL); + + /* Remove all active vital devices next */ + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + + cleanup_before_linux(); +} + +static void setup_start_tag (struct bd_info *bd) +{ + params = (struct tag *)bd->bi_boot_params; + + params->hdr.tag = ATAG_CORE; + params->hdr.size = tag_size (tag_core); + + params->u.core.flags = 0; + params->u.core.pagesize = 0; + params->u.core.rootdev = 0; + + params = tag_next (params); +} + +static void setup_memory_tags(struct bd_info *bd) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + params->hdr.tag = ATAG_MEM; + params->hdr.size = tag_size (tag_mem32); + + params->u.mem.start = bd->bi_dram[i].start; + params->u.mem.size = bd->bi_dram[i].size; + + params = tag_next (params); + } +} + +static void setup_commandline_tag(struct bd_info *bd, char *commandline) +{ + char *p; + + if (!commandline) + return; + + /* eat leading white space */ + for (p = commandline; *p == ' '; p++); + + /* skip non-existent command lines so the kernel will still + * use its default command line. + */ + if (*p == '\0') + return; + + params->hdr.tag = ATAG_CMDLINE; + params->hdr.size = + (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2; + + strcpy (params->u.cmdline.cmdline, p); + + params = tag_next (params); +} + +static void setup_initrd_tag(struct bd_info *bd, ulong initrd_start, + ulong initrd_end) +{ + /* an ATAG_INITRD node tells the kernel where the compressed + * ramdisk can be found. ATAG_RDIMG is a better name, actually. + */ + params->hdr.tag = ATAG_INITRD2; + params->hdr.size = tag_size (tag_initrd); + + params->u.initrd.start = initrd_start; + params->u.initrd.size = initrd_end - initrd_start; + + params = tag_next (params); +} + +static void setup_serial_tag(struct tag **tmp) +{ + struct tag *params = *tmp; + struct tag_serialnr serialnr; + + get_board_serial(&serialnr); + params->hdr.tag = ATAG_SERIAL; + params->hdr.size = tag_size (tag_serialnr); + params->u.serialnr.low = serialnr.low; + params->u.serialnr.high= serialnr.high; + params = tag_next (params); + *tmp = params; +} + +static void setup_revision_tag(struct tag **in_params) +{ + u32 rev = 0; + + rev = get_board_rev(); + params->hdr.tag = ATAG_REVISION; + params->hdr.size = tag_size (tag_revision); + params->u.revision.rev = rev; + params = tag_next (params); +} + +static void setup_end_tag(struct bd_info *bd) +{ + params->hdr.tag = ATAG_NONE; + params->hdr.size = 0; +} + +__weak void setup_board_tags(struct tag **in_params) {} + +#ifdef CONFIG_ARM64 +static void do_nonsec_virt_switch(void) +{ + smp_kick_all_cpus(); + dcache_disable(); /* flush cache before swtiching to EL2 */ +} +#endif + +__weak void board_prep_linux(bootm_headers_t *images) { } + +/* Subcommand: PREP */ +static void boot_prep_linux(bootm_headers_t *images) +{ + char *commandline = env_get("bootargs"); + + if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) { +#ifdef CONFIG_OF_LIBFDT + debug("using: FDT\n"); + if (image_setup_linux(images)) { + panic("FDT creation failed!"); + } +#endif + } else if (BOOTM_ENABLE_TAGS) { + debug("using: ATAGS\n"); + setup_start_tag(gd->bd); + if (BOOTM_ENABLE_SERIAL_TAG) + setup_serial_tag(¶ms); + if (BOOTM_ENABLE_CMDLINE_TAG) + setup_commandline_tag(gd->bd, commandline); + if (BOOTM_ENABLE_REVISION_TAG) + setup_revision_tag(¶ms); + if (BOOTM_ENABLE_MEMORY_TAGS) + setup_memory_tags(gd->bd); + if (BOOTM_ENABLE_INITRD_TAG) { + /* + * In boot_ramdisk_high(), it may relocate ramdisk to + * a specified location. And set images->initrd_start & + * images->initrd_end to relocated ramdisk's start/end + * addresses. So use them instead of images->rd_start & + * images->rd_end when possible. + */ + if (images->initrd_start && images->initrd_end) { + setup_initrd_tag(gd->bd, images->initrd_start, + images->initrd_end); + } else if (images->rd_start && images->rd_end) { + setup_initrd_tag(gd->bd, images->rd_start, + images->rd_end); + } + } + setup_board_tags(¶ms); + setup_end_tag(gd->bd); + } else { + panic("FDT and ATAGS support not compiled in\n"); + } + + board_prep_linux(images); +} + +__weak bool armv7_boot_nonsec_default(void) +{ +#ifdef CONFIG_ARMV7_BOOT_SEC_DEFAULT + return false; +#else + return true; +#endif +} + +#ifdef CONFIG_ARMV7_NONSEC +bool armv7_boot_nonsec(void) +{ + char *s = env_get("bootm_boot_mode"); + bool nonsec = armv7_boot_nonsec_default(); + + if (s && !strcmp(s, "sec")) + nonsec = false; + + if (s && !strcmp(s, "nonsec")) + nonsec = true; + + return nonsec; +} +#endif + +#ifdef CONFIG_ARM64 +__weak void update_os_arch_secondary_cores(uint8_t os_arch) +{ +} + +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 +static void switch_to_el1(void) +{ + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images.os.arch == IH_ARCH_ARM)) + armv8_switch_to_el1(0, (u64)gd->bd->bi_arch_number, + (u64)images.ft_addr, 0, + (u64)images.ep, + ES_TO_AARCH32); + else + armv8_switch_to_el1((u64)images.ft_addr, 0, 0, 0, + images.ep, + ES_TO_AARCH64); +} +#endif +#endif + +/* Subcommand: GO */ +static void boot_jump_linux(bootm_headers_t *images, int flag) +{ +#ifdef CONFIG_ARM64 + void (*kernel_entry)(void *fdt_addr, void *res0, void *res1, + void *res2); + int fake = (flag & BOOTM_STATE_OS_FAKE_GO); + + kernel_entry = (void (*)(void *fdt_addr, void *res0, void *res1, + void *res2))images->ep; + + debug("## Transferring control to Linux (at address %lx)...\n", + (ulong) kernel_entry); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + announce_and_cleanup(fake); + + if (!fake) { +#ifdef CONFIG_ARMV8_PSCI + armv8_setup_psci(); +#endif + do_nonsec_virt_switch(); + + update_os_arch_secondary_cores(images->os.arch); + +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, + (u64)switch_to_el1, ES_TO_AARCH64); +#else + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images->os.arch == IH_ARCH_ARM)) + armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number, + (u64)images->ft_addr, 0, + (u64)images->ep, + ES_TO_AARCH32); + else + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, + images->ep, + ES_TO_AARCH64); +#endif + } +#else + unsigned long machid = gd->bd->bi_arch_number; + char *s; + void (*kernel_entry)(int zero, int arch, uint params); + unsigned long r2; + int fake = (flag & BOOTM_STATE_OS_FAKE_GO); + + kernel_entry = (void (*)(int, int, uint))images->ep; +#ifdef CONFIG_CPU_V7M + ulong addr = (ulong)kernel_entry | 1; + kernel_entry = (void *)addr; +#endif + s = env_get("machid"); + if (s) { + if (strict_strtoul(s, 16, &machid) < 0) { + debug("strict_strtoul failed!\n"); + return; + } + printf("Using machid 0x%lx from environment\n", machid); + } + + debug("## Transferring control to Linux (at address %08lx)" \ + "...\n", (ulong) kernel_entry); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + announce_and_cleanup(fake); + + if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) + r2 = (unsigned long)images->ft_addr; + else + r2 = gd->bd->bi_boot_params; + + if (!fake) { +#ifdef CONFIG_ARMV7_NONSEC + if (armv7_boot_nonsec()) { + armv7_init_nonsec(); + secure_ram_addr(_do_nonsec_entry)(kernel_entry, + 0, machid, r2); + } else +#endif + kernel_entry(0, machid, r2); + } +#endif +} + +/* Main Entry point for arm bootm implementation + * + * Modeled after the powerpc implementation + * DIFFERENCE: Instead of calling prep and go at the end + * they are called if subcommand is equal 0. + */ +int do_bootm_linux(int flag, int argc, char *const argv[], + bootm_headers_t *images) +{ + /* No need for those on ARM */ + if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) + return -1; + + if (flag & BOOTM_STATE_OS_PREP) { + boot_prep_linux(images); + return 0; + } + + if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { + boot_jump_linux(images, flag); + return 0; + } + + boot_prep_linux(images); + boot_jump_linux(images, flag); + return 0; +} + +#if defined(CONFIG_BOOTM_VXWORKS) +void boot_prep_vxworks(bootm_headers_t *images) +{ +#if defined(CONFIG_OF_LIBFDT) + int off; + + if (images->ft_addr) { + off = fdt_path_offset(images->ft_addr, "/memory"); + if (off > 0) { + if (arch_fixup_fdt(images->ft_addr)) + puts("## WARNING: fixup memory failed!\n"); + } + } +#endif + cleanup_before_linux(); +} +void boot_jump_vxworks(bootm_headers_t *images) +{ +#if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI) + armv8_setup_psci(); + smp_kick_all_cpus(); +#endif + + /* ARM VxWorks requires device tree physical address to be passed */ + ((void (*)(void *))images->ep)(images->ft_addr); +} +#endif diff --git a/roms/u-boot/arch/arm/lib/cache-cp15.c b/roms/u-boot/arch/arm/lib/cache-cp15.c new file mode 100644 index 000000000..aab1bf436 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/cache-cp15.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <common.h> +#include <cpu_func.h> +#include <log.h> +#include <asm/global_data.h> +#include <asm/system.h> +#include <asm/cache.h> +#include <linux/compiler.h> +#include <asm/armv7_mpu.h> + +#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SYS_ARM_MMU +__weak void arm_init_before_mmu(void) +{ +} + +static void set_section_phys(int section, phys_addr_t phys, + enum dcache_option option) +{ +#ifdef CONFIG_ARMV7_LPAE + u64 *page_table = (u64 *)gd->arch.tlb_addr; + /* Need to set the access flag to not fault */ + u64 value = TTB_SECT_AP | TTB_SECT_AF; +#else + u32 *page_table = (u32 *)gd->arch.tlb_addr; + u32 value = TTB_SECT_AP; +#endif + + /* Add the page offset */ + value |= phys; + + /* Add caching bits */ + value |= option; + + /* Set PTE */ + page_table[section] = value; +} + +void set_section_dcache(int section, enum dcache_option option) +{ + set_section_phys(section, (u32)section << MMU_SECTION_SHIFT, option); +} + +__weak void mmu_page_table_flush(unsigned long start, unsigned long stop) +{ + debug("%s: Warning: not implemented\n", __func__); +} + +void mmu_set_region_dcache_behaviour_phys(phys_addr_t start, phys_addr_t phys, + size_t size, enum dcache_option option) +{ +#ifdef CONFIG_ARMV7_LPAE + u64 *page_table = (u64 *)gd->arch.tlb_addr; +#else + u32 *page_table = (u32 *)gd->arch.tlb_addr; +#endif + unsigned long startpt, stoppt; + unsigned long upto, end; + + /* div by 2 before start + size to avoid phys_addr_t overflow */ + end = ALIGN((start / 2) + (size / 2), MMU_SECTION_SIZE / 2) + >> (MMU_SECTION_SHIFT - 1); + start = start >> MMU_SECTION_SHIFT; + +#ifdef CONFIG_ARMV7_LPAE + debug("%s: start=%pa, size=%zu, option=%llx\n", __func__, &start, size, + option); +#else + debug("%s: start=%pa, size=%zu, option=0x%x\n", __func__, &start, size, + option); +#endif + for (upto = start; upto < end; upto++, phys += MMU_SECTION_SIZE) + set_section_phys(upto, phys, option); + + /* + * Make sure range is cache line aligned + * Only CPU maintains page tables, hence it is safe to always + * flush complete cache lines... + */ + + startpt = (unsigned long)&page_table[start]; + startpt &= ~(CONFIG_SYS_CACHELINE_SIZE - 1); + stoppt = (unsigned long)&page_table[end]; + stoppt = ALIGN(stoppt, CONFIG_SYS_CACHELINE_SIZE); + mmu_page_table_flush(startpt, stoppt); +} + +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option) +{ + mmu_set_region_dcache_behaviour_phys(start, start, size, option); +} + +__weak void dram_bank_mmu_setup(int bank) +{ + struct bd_info *bd = gd->bd; + int i; + + /* bd->bi_dram is available only after relocation */ + if ((gd->flags & GD_FLG_RELOC) == 0) + return; + + debug("%s: bank: %d\n", __func__, bank); + for (i = bd->bi_dram[bank].start >> MMU_SECTION_SHIFT; + i < (bd->bi_dram[bank].start >> MMU_SECTION_SHIFT) + + (bd->bi_dram[bank].size >> MMU_SECTION_SHIFT); + i++) + set_section_dcache(i, DCACHE_DEFAULT_OPTION); +} + +/* to activate the MMU we need to set up virtual memory: use 1M areas */ +static inline void mmu_setup(void) +{ + int i; + u32 reg; + + arm_init_before_mmu(); + /* Set up an identity-mapping for all 4GB, rw for everyone */ + for (i = 0; i < ((4096ULL * 1024 * 1024) >> MMU_SECTION_SHIFT); i++) + set_section_dcache(i, DCACHE_OFF); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + dram_bank_mmu_setup(i); + } + +#if defined(CONFIG_ARMV7_LPAE) && __LINUX_ARM_ARCH__ != 4 + /* Set up 4 PTE entries pointing to our 4 1GB page tables */ + for (i = 0; i < 4; i++) { + u64 *page_table = (u64 *)(gd->arch.tlb_addr + (4096 * 4)); + u64 tpt = gd->arch.tlb_addr + (4096 * i); + page_table[i] = tpt | TTB_PAGETABLE; + } + + reg = TTBCR_EAE; +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) + reg |= TTBCR_ORGN0_WT | TTBCR_IRGN0_WT; +#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC) + reg |= TTBCR_ORGN0_WBWA | TTBCR_IRGN0_WBWA; +#else + reg |= TTBCR_ORGN0_WBNWA | TTBCR_IRGN0_WBNWA; +#endif + + if (is_hyp()) { + /* Set HTCR to enable LPAE */ + asm volatile("mcr p15, 4, %0, c2, c0, 2" + : : "r" (reg) : "memory"); + /* Set HTTBR0 */ + asm volatile("mcrr p15, 4, %0, %1, c2" + : + : "r"(gd->arch.tlb_addr + (4096 * 4)), "r"(0) + : "memory"); + /* Set HMAIR */ + asm volatile("mcr p15, 4, %0, c10, c2, 0" + : : "r" (MEMORY_ATTRIBUTES) : "memory"); + } else { + /* Set TTBCR to enable LPAE */ + asm volatile("mcr p15, 0, %0, c2, c0, 2" + : : "r" (reg) : "memory"); + /* Set 64-bit TTBR0 */ + asm volatile("mcrr p15, 0, %0, %1, c2" + : + : "r"(gd->arch.tlb_addr + (4096 * 4)), "r"(0) + : "memory"); + /* Set MAIR */ + asm volatile("mcr p15, 0, %0, c10, c2, 0" + : : "r" (MEMORY_ATTRIBUTES) : "memory"); + } +#elif defined(CONFIG_CPU_V7A) + if (is_hyp()) { + /* Set HTCR to disable LPAE */ + asm volatile("mcr p15, 4, %0, c2, c0, 2" + : : "r" (0) : "memory"); + } else { + /* Set TTBCR to disable LPAE */ + asm volatile("mcr p15, 0, %0, c2, c0, 2" + : : "r" (0) : "memory"); + } + /* Set TTBR0 */ + reg = gd->arch.tlb_addr & TTBR0_BASE_ADDR_MASK; +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) + reg |= TTBR0_RGN_WT | TTBR0_IRGN_WT; +#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC) + reg |= TTBR0_RGN_WBWA | TTBR0_IRGN_WBWA; +#else + reg |= TTBR0_RGN_WB | TTBR0_IRGN_WB; +#endif + asm volatile("mcr p15, 0, %0, c2, c0, 0" + : : "r" (reg) : "memory"); +#else + /* Copy the page table address to cp15 */ + asm volatile("mcr p15, 0, %0, c2, c0, 0" + : : "r" (gd->arch.tlb_addr) : "memory"); +#endif + /* + * initial value of Domain Access Control Register (DACR) + * Set the access control to client (1U) for each of the 16 domains + */ + asm volatile("mcr p15, 0, %0, c3, c0, 0" + : : "r" (0x55555555)); + + /* and enable the mmu */ + reg = get_cr(); /* get control reg. */ + set_cr(reg | CR_M); +} + +static int mmu_enabled(void) +{ + return get_cr() & CR_M; +} +#endif /* CONFIG_SYS_ARM_MMU */ + +/* cache_bit must be either CR_I or CR_C */ +static void cache_enable(uint32_t cache_bit) +{ + uint32_t reg; + + /* The data cache is not active unless the mmu/mpu is enabled too */ +#ifdef CONFIG_SYS_ARM_MMU + if ((cache_bit == CR_C) && !mmu_enabled()) + mmu_setup(); +#elif defined(CONFIG_SYS_ARM_MPU) + if ((cache_bit == CR_C) && !mpu_enabled()) { + printf("Consider enabling MPU before enabling caches\n"); + return; + } +#endif + reg = get_cr(); /* get control reg. */ + set_cr(reg | cache_bit); +} + +/* cache_bit must be either CR_I or CR_C */ +static void cache_disable(uint32_t cache_bit) +{ + uint32_t reg; + + reg = get_cr(); + + if (cache_bit == CR_C) { + /* if cache isn;t enabled no need to disable */ + if ((reg & CR_C) != CR_C) + return; +#ifdef CONFIG_SYS_ARM_MMU + /* if disabling data cache, disable mmu too */ + cache_bit |= CR_M; +#endif + } + reg = get_cr(); + +#ifdef CONFIG_SYS_ARM_MMU + if (cache_bit == (CR_C | CR_M)) +#elif defined(CONFIG_SYS_ARM_MPU) + if (cache_bit == CR_C) +#endif + flush_dcache_all(); + set_cr(reg & ~cache_bit); +} +#endif + +#if CONFIG_IS_ENABLED(SYS_ICACHE_OFF) +void icache_enable(void) +{ + return; +} + +void icache_disable(void) +{ + return; +} + +int icache_status(void) +{ + return 0; /* always off */ +} +#else +void icache_enable(void) +{ + cache_enable(CR_I); +} + +void icache_disable(void) +{ + cache_disable(CR_I); +} + +int icache_status(void) +{ + return (get_cr() & CR_I) != 0; +} +#endif + +#if CONFIG_IS_ENABLED(SYS_DCACHE_OFF) +void dcache_enable(void) +{ + return; +} + +void dcache_disable(void) +{ + return; +} + +int dcache_status(void) +{ + return 0; /* always off */ +} +#else +void dcache_enable(void) +{ + cache_enable(CR_C); +} + +void dcache_disable(void) +{ + cache_disable(CR_C); +} + +int dcache_status(void) +{ + return (get_cr() & CR_C) != 0; +} +#endif diff --git a/roms/u-boot/arch/arm/lib/cache-pl310.c b/roms/u-boot/arch/arm/lib/cache-pl310.c new file mode 100644 index 000000000..bbaaaa415 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/cache-pl310.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + */ +#include <linux/types.h> +#include <asm/io.h> +#include <asm/armv7.h> +#include <asm/pl310.h> +#include <config.h> +#include <common.h> + +struct pl310_regs *const pl310 = (struct pl310_regs *)CONFIG_SYS_PL310_BASE; + +static void pl310_cache_sync(void) +{ + writel(0, &pl310->pl310_cache_sync); +} + +static void pl310_background_op_all_ways(u32 *op_reg) +{ + u32 assoc_16, associativity, way_mask; + + assoc_16 = readl(&pl310->pl310_aux_ctrl) & + PL310_AUX_CTRL_ASSOCIATIVITY_MASK; + if (assoc_16) + associativity = 16; + else + associativity = 8; + + way_mask = (1 << associativity) - 1; + /* Invalidate all ways */ + writel(way_mask, op_reg); + /* Wait for all ways to be invalidated */ + while (readl(op_reg) & way_mask) + ; + pl310_cache_sync(); +} + +void v7_outer_cache_inval_all(void) +{ + pl310_background_op_all_ways(&pl310->pl310_inv_way); +} + +void v7_outer_cache_flush_all(void) +{ + pl310_background_op_all_ways(&pl310->pl310_clean_inv_way); +} + +/* Flush(clean invalidate) memory from start to stop-1 */ +void v7_outer_cache_flush_range(u32 start, u32 stop) +{ + /* PL310 currently supports only 32 bytes cache line */ + u32 pa, line_size = 32; + + /* + * Align to the beginning of cache-line - this ensures that + * the first 5 bits are 0 as required by PL310 TRM + */ + start &= ~(line_size - 1); + + for (pa = start; pa < stop; pa = pa + line_size) + writel(pa, &pl310->pl310_clean_inv_line_pa); + + pl310_cache_sync(); +} + +/* invalidate memory from start to stop-1 */ +void v7_outer_cache_inval_range(u32 start, u32 stop) +{ + /* PL310 currently supports only 32 bytes cache line */ + u32 pa, line_size = 32; + + /* + * If start address is not aligned to cache-line do not + * invalidate the first cache-line + */ + if (start & (line_size - 1)) { + printf("ERROR: %s - start address is not aligned - 0x%08x\n", + __func__, start); + /* move to next cache line */ + start = (start + line_size - 1) & ~(line_size - 1); + } + + /* + * If stop address is not aligned to cache-line do not + * invalidate the last cache-line + */ + if (stop & (line_size - 1)) { + printf("ERROR: %s - stop address is not aligned - 0x%08x\n", + __func__, stop); + /* align to the beginning of this cache line */ + stop &= ~(line_size - 1); + } + + for (pa = start; pa < stop; pa = pa + line_size) + writel(pa, &pl310->pl310_inv_line_pa); + + pl310_cache_sync(); +} diff --git a/roms/u-boot/arch/arm/lib/cache.c b/roms/u-boot/arch/arm/lib/cache.c new file mode 100644 index 000000000..a2bf2e57b --- /dev/null +++ b/roms/u-boot/arch/arm/lib/cache.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +/* for now: just dummy functions to satisfy the linker */ + +#include <common.h> +#include <cpu_func.h> +#include <log.h> +#include <malloc.h> +#include <asm/cache.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Flush range from all levels of d-cache/unified-cache. + * Affects the range [start, start + size - 1]. + */ +__weak void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} + +/* + * Default implementation: + * do a range flush for the entire range + */ +__weak void flush_dcache_all(void) +{ + flush_cache(0, ~0); +} + +/* + * Default implementation of enable_caches() + * Real implementation should be in platform code + */ +__weak void enable_caches(void) +{ + puts("WARNING: Caches not enabled\n"); +} + +__weak void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + /* An empty stub, real implementation should be in platform code */ +} +__weak void flush_dcache_range(unsigned long start, unsigned long stop) +{ + /* An empty stub, real implementation should be in platform code */ +} + +int check_cache_range(unsigned long start, unsigned long stop) +{ + int ok = 1; + + if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (!ok) { + warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n", + start, stop); + } + + return ok; +} + +#ifdef CONFIG_SYS_NONCACHED_MEMORY +/* + * Reserve one MMU section worth of address space below the malloc() area that + * will be mapped uncached. + */ +static unsigned long noncached_start; +static unsigned long noncached_end; +static unsigned long noncached_next; + +void noncached_set_region(void) +{ +#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) + mmu_set_region_dcache_behaviour(noncached_start, + noncached_end - noncached_start, + DCACHE_OFF); +#endif +} + +int noncached_init(void) +{ + phys_addr_t start, end; + size_t size; + + /* If this calculation changes, update board_f.c:reserve_noncached() */ + end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE; + size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE); + start = end - size; + + debug("mapping memory %pa-%pa non-cached\n", &start, &end); + + noncached_start = start; + noncached_end = end; + noncached_next = start; + + noncached_set_region(); + + return 0; +} + +phys_addr_t noncached_alloc(size_t size, size_t align) +{ + phys_addr_t next = ALIGN(noncached_next, align); + + if (next >= noncached_end || (noncached_end - next) < size) + return 0; + + debug("allocated %zu bytes of uncached memory @%pa\n", size, &next); + noncached_next = next + size; + + return next; +} +#endif /* CONFIG_SYS_NONCACHED_MEMORY */ + +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) +void invalidate_l2_cache(void) +{ + unsigned int val = 0; + + asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache" + : : "r" (val) : "cc"); + isb(); +} +#endif + +int arch_reserve_mmu(void) +{ + return arm_reserve_mmu(); +} + +__weak int arm_reserve_mmu(void) +{ +#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + /* reserve TLB table */ + gd->arch.tlb_size = PGTABLE_SIZE; + gd->relocaddr -= gd->arch.tlb_size; + + /* round down to next 64 kB limit */ + gd->relocaddr &= ~(0x10000 - 1); + + gd->arch.tlb_addr = gd->relocaddr; + debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + /* + * Record allocated tlb_addr in case gd->tlb_addr to be overwritten + * with location within secure ram. + */ + gd->arch.tlb_allocated = gd->arch.tlb_addr; +#endif +#endif + + return 0; +} diff --git a/roms/u-boot/arch/arm/lib/ccn504.S b/roms/u-boot/arch/arm/lib/ccn504.S new file mode 100644 index 000000000..2c584095c --- /dev/null +++ b/roms/u-boot/arch/arm/lib/ccn504.S @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2015 Freescale Semiconductor + * + * Extracted from gic_64.S + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +/************************************************************************* + * + * void ccn504_add_masters_to_dvm(CCI_MN_BASE, CCI_MN_RNF_NODEID_LIST, + * CCI_MN_DVM_DOMAIN_CTL_SET); + * + * Add fully-coherent masters to DVM domain + * + *************************************************************************/ +ENTRY(ccn504_add_masters_to_dvm) + /* + * x0: CCI_MN_BASE + * x1: CCI_MN_RNF_NODEID_LIST + * x2: CCI_MN_DVM_DOMAIN_CTL_SET + */ + + /* Add fully-coherent masters to DVM domain */ + ldr x9, [x0, x1] + str x9, [x0, x2] +1: ldr x10, [x0, x2] + mvn x11, x10 + tst x11, x10 /* Wait for domain addition to complete */ + b.ne 1b + + ret +ENDPROC(ccn504_add_masters_to_dvm) + +/************************************************************************* + * + * void ccn504_set_qos(CCI_Sx_QOS_CONTROL_BASE, QoS Value); + * + * Initialize QoS settings for AR/AW override. + * Right now, this function sets the same QoS value for all RN-I ports + * + *************************************************************************/ +ENTRY(ccn504_set_qos) + /* + * x0: CCI_Sx_QOS_CONTROL_BASE + * x1: QoS Value + */ + + /* Set all RN-I ports to QoS value denoted by x1 */ + ldr x9, [x0] + mov x10, x1 + orr x9, x9, x10 + str x9, [x0] + + ret +ENDPROC(ccn504_set_qos) + +/************************************************************************* + * + * void ccn504_set_aux(CCI_AUX_CONTROL_BASE, Value); + * + * Initialize AUX control settings + * + *************************************************************************/ +ENTRY(ccn504_set_aux) + /* + * x0: CCI_AUX_CONTROL_BASE + * x1: Value + */ + + ldr x9, [x0] + mov x10, x1 + orr x9, x9, x10 + str x9, [x0] + + ret +ENDPROC(ccn504_set_aux) + diff --git a/roms/u-boot/arch/arm/lib/cmd_boot.c b/roms/u-boot/arch/arm/lib/cmd_boot.c new file mode 100644 index 000000000..c905ecc4b --- /dev/null +++ b/roms/u-boot/arch/arm/lib/cmd_boot.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2008-2011 + * Graeme Russ, <graeme.russ@gmail.com> + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se> + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright 2015 ATS Advanced Telematics Systems GmbH + * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com> + */ + +#include <common.h> +#include <command.h> + +/* + * ARMv7M does not support ARM instruction mode. However, the + * interworking BLX and BX instructions do encode the ARM/Thumb + * field in bit 0. This means that when executing any Branch + * and eXchange instruction we must set bit 0 to one to guarantee + * that we keep the processor in Thumb instruction mode. From The + * ARMv7-M Instruction Set A4.1.1: + * "ARMv7-M only supports the Thumb instruction execution state, + * therefore the value of address bit [0] must be 1 in interworking + * instructions, otherwise a fault occurs." + */ +unsigned long do_go_exec(ulong (*entry)(int, char * const []), + int argc, char *const argv[]) +{ + ulong addr = (ulong)entry | 1; + entry = (void *)addr; + + return entry(argc, argv); +} diff --git a/roms/u-boot/arch/arm/lib/crt0.S b/roms/u-boot/arch/arm/lib/crt0.S new file mode 100644 index 000000000..46b6be21a --- /dev/null +++ b/roms/u-boot/arch/arm/lib/crt0.S @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * crt0 - C-runtime startup Code for ARM U-Boot + * + * Copyright (c) 2012 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <config.h> +#include <asm-offsets.h> +#include <linux/linkage.h> +#include <asm/assembler.h> + +/* + * This file handles the target-independent stages of the U-Boot + * start-up where a C runtime environment is needed. Its entry point + * is _main and is branched into from the target's start.S file. + * + * _main execution sequence is: + * + * 1. Set up initial environment for calling board_init_f(). + * This environment only provides a stack and a place to store + * the GD ('global data') structure, both located in some readily + * available RAM (SRAM, locked cache...). In this context, VARIABLE + * global data, initialized or not (BSS), are UNAVAILABLE; only + * CONSTANT initialized data are available. GD should be zeroed + * before board_init_f() is called. + * + * 2. Call board_init_f(). This function prepares the hardware for + * execution from system RAM (DRAM, DDR...) As system RAM may not + * be available yet, , board_init_f() must use the current GD to + * store any data which must be passed on to later stages. These + * data include the relocation destination, the future stack, and + * the future GD location. + * + * 3. Set up intermediate environment where the stack and GD are the + * ones allocated by board_init_f() in system RAM, but BSS and + * initialized non-const data are still not available. + * + * 4a.For U-Boot proper (not SPL), call relocate_code(). This function + * relocates U-Boot from its current location into the relocation + * destination computed by board_init_f(). + * + * 4b.For SPL, board_init_f() just returns (to crt0). There is no + * code relocation in SPL. + * + * 5. Set up final environment for calling board_init_r(). This + * environment has BSS (initialized to 0), initialized non-const + * data (initialized to their intended value), and stack in system + * RAM (for SPL moving the stack and GD into RAM is optional - see + * CONFIG_SPL_STACK_R). GD has retained values set by board_init_f(). + * + * 6. For U-Boot proper (not SPL), some CPUs have some work left to do + * at this point regarding memory, so call c_runtime_cpu_setup. + * + * 7. Branch to board_init_r(). + * + * For more information see 'Board Initialisation Flow in README. + */ + +/* + * Macro for clearing BSS during SPL execution. Usually called during the + * relocation process for most boards before entering board_init_r(), but + * can also be done early before entering board_init_f() on plaforms that + * can afford it due to sufficient memory being available early. + */ + +.macro CLEAR_BSS + ldr r0, =__bss_start /* this is auto-relocated! */ + +#ifdef CONFIG_USE_ARCH_MEMSET + ldr r3, =__bss_end /* this is auto-relocated! */ + mov r1, #0x00000000 /* prepare zero to clear BSS */ + + subs r2, r3, r0 /* r2 = memset len */ + bl memset +#else + ldr r1, =__bss_end /* this is auto-relocated! */ + mov r2, #0x00000000 /* prepare zero to clear BSS */ + +clbss_l:cmp r0, r1 /* while not at end of BSS */ + strlo r2, [r0] /* clear 32-bit BSS word */ + addlo r0, r0, #4 /* move to next */ + blo clbss_l +#endif +.endm + +/* + * entry point of crt0 sequence + */ + +ENTRY(_main) + +/* + * Set up initial C runtime environment and call board_init_f(0). + */ + +#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK) + ldr r0, =(CONFIG_TPL_STACK) +#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) + ldr r0, =(CONFIG_SPL_STACK) +#else + ldr r0, =(CONFIG_SYS_INIT_SP_ADDR) +#endif + bic r0, r0, #7 /* 8-byte alignment for ABI compliance */ + mov sp, r0 + bl board_init_f_alloc_reserve + mov sp, r0 + /* set up gd here, outside any C code */ + mov r9, r0 + bl board_init_f_init_reserve + +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_EARLY_BSS) + CLEAR_BSS +#endif + + mov r0, #0 + bl board_init_f + +#if ! defined(CONFIG_SPL_BUILD) + +/* + * Set up intermediate environment (new sp and gd) and call + * relocate_code(addr_moni). Trick here is that we'll return + * 'here' but relocated. + */ + + ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ + bic r0, r0, #7 /* 8-byte alignment for ABI compliance */ + mov sp, r0 + ldr r9, [r9, #GD_NEW_GD] /* r9 <- gd->new_gd */ + + adr lr, here + ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ + add lr, lr, r0 +#if defined(CONFIG_CPU_V7M) + orr lr, #1 /* As required by Thumb-only */ +#endif + ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ + b relocate_code +here: +/* + * now relocate vectors + */ + + bl relocate_vectors + +/* Set up final (full) environment */ + + bl c_runtime_cpu_setup /* we still call old routine here */ +#endif +#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK) + +#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_SPL_EARLY_BSS) + CLEAR_BSS +#endif + +# ifdef CONFIG_SPL_BUILD + /* Use a DRAM stack for the rest of SPL, if requested */ + bl spl_relocate_stack_gd + cmp r0, #0 + movne sp, r0 + movne r9, r0 +# endif + +#if ! defined(CONFIG_SPL_BUILD) + bl coloured_LED_init + bl red_led_on +#endif + /* call board_init_r(gd_t *id, ulong dest_addr) */ + mov r0, r9 /* gd_t */ + ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */ + /* call board_init_r */ +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) + ldr lr, =board_init_r /* this is auto-relocated! */ + bx lr +#else + ldr pc, =board_init_r /* this is auto-relocated! */ +#endif + /* we should not return here. */ +#endif + +ENDPROC(_main) diff --git a/roms/u-boot/arch/arm/lib/crt0_64.S b/roms/u-boot/arch/arm/lib/crt0_64.S new file mode 100644 index 000000000..680e674fa --- /dev/null +++ b/roms/u-boot/arch/arm/lib/crt0_64.S @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * crt0 - C-runtime startup Code for AArch64 U-Boot + * + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * (C) Copyright 2012 + * Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <config.h> +#include <asm-offsets.h> +#include <asm/macro.h> +#include <linux/linkage.h> + +/* + * This file handles the target-independent stages of the U-Boot + * start-up where a C runtime environment is needed. Its entry point + * is _main and is branched into from the target's start.S file. + * + * _main execution sequence is: + * + * 1. Set up initial environment for calling board_init_f(). + * This environment only provides a stack and a place to store + * the GD ('global data') structure, both located in some readily + * available RAM (SRAM, locked cache...). In this context, VARIABLE + * global data, initialized or not (BSS), are UNAVAILABLE; only + * CONSTANT initialized data are available. GD should be zeroed + * before board_init_f() is called. + * + * 2. Call board_init_f(). This function prepares the hardware for + * execution from system RAM (DRAM, DDR...) As system RAM may not + * be available yet, , board_init_f() must use the current GD to + * store any data which must be passed on to later stages. These + * data include the relocation destination, the future stack, and + * the future GD location. + * + * 3. Set up intermediate environment where the stack and GD are the + * ones allocated by board_init_f() in system RAM, but BSS and + * initialized non-const data are still not available. + * + * 4a.For U-Boot proper (not SPL), call relocate_code(). This function + * relocates U-Boot from its current location into the relocation + * destination computed by board_init_f(). + * + * 4b.For SPL, board_init_f() just returns (to crt0). There is no + * code relocation in SPL. + * + * 5. Set up final environment for calling board_init_r(). This + * environment has BSS (initialized to 0), initialized non-const + * data (initialized to their intended value), and stack in system + * RAM (for SPL moving the stack and GD into RAM is optional - see + * CONFIG_SPL_STACK_R). GD has retained values set by board_init_f(). + * + * TODO: For SPL, implement stack relocation on AArch64. + * + * 6. For U-Boot proper (not SPL), some CPUs have some work left to do + * at this point regarding memory, so call c_runtime_cpu_setup. + * + * 7. Branch to board_init_r(). + * + * For more information see 'Board Initialisation Flow in README. + */ + +ENTRY(_main) + +/* + * Set up initial C runtime environment and call board_init_f(0). + */ +#if defined(CONFIG_TPL_BUILD) && defined(CONFIG_TPL_NEEDS_SEPARATE_STACK) + ldr x0, =(CONFIG_TPL_STACK) +#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) + ldr x0, =(CONFIG_SPL_STACK) +#elif defined(CONFIG_INIT_SP_RELATIVE) +#if CONFIG_POSITION_INDEPENDENT + adrp x0, __bss_start /* x0 <- Runtime &__bss_start */ + add x0, x0, #:lo12:__bss_start +#else + adr x0, __bss_start +#endif + add x0, x0, #CONFIG_SYS_INIT_SP_BSS_OFFSET +#else + ldr x0, =(CONFIG_SYS_INIT_SP_ADDR) +#endif + bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ + mov x0, sp + bl board_init_f_alloc_reserve + mov sp, x0 + /* set up gd here, outside any C code */ + mov x18, x0 + bl board_init_f_init_reserve + + mov x0, #0 + bl board_init_f + +#if !defined(CONFIG_SPL_BUILD) +/* + * Set up intermediate environment (new sp and gd) and call + * relocate_code(addr_moni). Trick here is that we'll return + * 'here' but relocated. + */ + ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */ + bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ + ldr x18, [x18, #GD_NEW_GD] /* x18 <- gd->new_gd */ + + adr lr, relocation_return +#if CONFIG_POSITION_INDEPENDENT + /* Add in link-vs-runtime offset */ + adrp x0, _start /* x0 <- Runtime value of _start */ + add x0, x0, #:lo12:_start + ldr x9, _TEXT_BASE /* x9 <- Linked value of _start */ + sub x9, x9, x0 /* x9 <- Run-vs-link offset */ + add lr, lr, x9 +#if defined(CONFIG_SYS_RELOC_GD_ENV_ADDR) + ldr x0, [x18, #GD_ENV_ADDR] /* x0 <- gd->env_addr */ + add x0, x0, x9 + str x0, [x18, #GD_ENV_ADDR] +#endif +#endif + /* Add in link-vs-relocation offset */ + ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */ + add lr, lr, x9 /* new return address after relocation */ + ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */ + b relocate_code + +relocation_return: + +/* + * Set up final (full) environment + */ + bl c_runtime_cpu_setup /* still call old routine */ +#endif /* !CONFIG_SPL_BUILD */ +#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(FRAMEWORK) +#if defined(CONFIG_SPL_BUILD) + bl spl_relocate_stack_gd /* may return NULL */ + /* set up gd here, outside any C code, if new stack is returned */ + cmp x0, #0 + csel x18, x0, x18, ne + /* + * Perform 'sp = (x0 != NULL) ? x0 : sp' while working + * around the constraint that conditional moves can not + * have 'sp' as an operand + */ + mov x1, sp + cmp x0, #0 + csel x0, x0, x1, ne + mov sp, x0 +#endif + +/* + * Clear BSS section + */ + ldr x0, =__bss_start /* this is auto-relocated! */ + ldr x1, =__bss_end /* this is auto-relocated! */ +clear_loop: + str xzr, [x0], #8 + cmp x0, x1 + b.lo clear_loop + + /* call board_init_r(gd_t *id, ulong dest_addr) */ + mov x0, x18 /* gd_t */ + ldr x1, [x18, #GD_RELOCADDR] /* dest_addr */ + b board_init_r /* PC relative jump */ + + /* NOTREACHED - board_init_r() does not return */ +#endif + +ENDPROC(_main) diff --git a/roms/u-boot/arch/arm/lib/crt0_aarch64_efi.S b/roms/u-boot/arch/arm/lib/crt0_aarch64_efi.S new file mode 100644 index 000000000..492195f76 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/crt0_aarch64_efi.S @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ +/* + * crt0-efi-aarch64.S - PE/COFF header for aarch64 EFI applications + * + * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> + * + * + * This file is taken and modified from the gnu-efi project. + */ + +#include <asm-generic/pe.h> + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .short IMAGE_DOS_SIGNATURE /* 'MZ' */ + .skip 54 /* 'MZ' + pad + offset == 64 */ + .long LINUX_ARM64_MAGIC /* For GRUB's linux command */ + .long pe_header - ImageBase /* Offset to the PE header */ +pe_header: + .long IMAGE_NT_SIGNATURE /* 'PE' */ +coff_header: + .short IMAGE_FILE_MACHINE_ARM64 /* AArch64 */ + .short 2 /* nr_sections */ + .long 0 /* TimeDateStamp */ + .long 0 /* PointerToSymbolTable */ + .long 0 /* NumberOfSymbols */ + .short section_table - optional_header /* SizeOfOptionalHeader */ + /* Characteristics */ + .short (IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_LINE_NUMS_STRIPPED | \ + IMAGE_FILE_LOCAL_SYMS_STRIPPED | \ + IMAGE_FILE_DEBUG_STRIPPED) +optional_header: + .short IMAGE_NT_OPTIONAL_HDR64_MAGIC /* PE32+ format */ + .byte 0x02 /* MajorLinkerVersion */ + .byte 0x14 /* MinorLinkerVersion */ + .long _edata - _start /* SizeOfCode */ + .long 0 /* SizeOfInitializedData */ + .long 0 /* SizeOfUninitializedData */ + .long _start - ImageBase /* AddressOfEntryPoint */ + .long _start - ImageBase /* BaseOfCode */ + +extra_header_fields: + .quad 0 /* ImageBase */ + .long 0x20 /* SectionAlignment */ + .long 0x8 /* FileAlignment */ + .short 0 /* MajorOperatingSystemVersion */ + .short 0 /* MinorOperatingSystemVersion */ + .short 0 /* MajorImageVersion */ + .short 0 /* MinorImageVersion */ + .short 0 /* MajorSubsystemVersion */ + .short 0 /* MinorSubsystemVersion */ + .long 0 /* Win32VersionValue */ + + .long _edata - ImageBase /* SizeOfImage */ + + /* + * Everything before the kernel image is considered part of the header + */ + .long _start - ImageBase /* SizeOfHeaders */ + .long 0 /* CheckSum */ + .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */ + .short 0 /* DllCharacteristics */ + .quad 0 /* SizeOfStackReserve */ + .quad 0 /* SizeOfStackCommit */ + .quad 0 /* SizeOfHeapReserve */ + .quad 0 /* SizeOfHeapCommit */ + .long 0 /* LoaderFlags */ + .long 0x6 /* NumberOfRvaAndSizes */ + + .quad 0 /* ExportTable */ + .quad 0 /* ImportTable */ + .quad 0 /* ResourceTable */ + .quad 0 /* ExceptionTable */ + .quad 0 /* CertificationTable */ + .quad 0 /* BaseRelocationTable */ + + /* Section table */ +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long 0 + .long 0 + .long 0 /* SizeOfRawData */ + .long 0 /* PointerToRawData */ + .long 0 /* PointerToRelocations */ + .long 0 /* PointerToLineNumbers */ + .short 0 /* NumberOfRelocations */ + .short 0 /* NumberOfLineNumbers */ + .long 0x42100040 /* Characteristics (section flags) */ + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long _edata - _start /* VirtualSize */ + .long _start - ImageBase /* VirtualAddress */ + .long _edata - _start /* SizeOfRawData */ + .long _start - ImageBase /* PointerToRawData */ + + .long 0 /* PointerToRelocations (0 for executables) */ + .long 0 /* PointerToLineNumbers (0 for executables) */ + .short 0 /* NumberOfRelocations (0 for executables) */ + .short 0 /* NumberOfLineNumbers (0 for executables) */ + .long 0xe0500020 /* Characteristics (section flags) */ + +_start: + stp x29, x30, [sp, #-32]! + mov x29, sp + + stp x0, x1, [sp, #16] + adr x0, ImageBase + adrp x1, _DYNAMIC + add x1, x1, #:lo12:_DYNAMIC + bl _relocate + cbnz x0, 0f + + ldp x0, x1, [sp, #16] + bl efi_main + +0: ldp x29, x30, [sp], #32 + ret diff --git a/roms/u-boot/arch/arm/lib/crt0_arm_efi.S b/roms/u-boot/arch/arm/lib/crt0_arm_efi.S new file mode 100644 index 000000000..cc8a115f3 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/crt0_arm_efi.S @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ +/* + * crt0-efi-arm.S - PE/COFF header for ARM EFI applications + * + * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> + * + * This file is taken and modified from the gnu-efi project. + */ + +#include <asm-generic/pe.h> + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl image_base +image_base: + .short IMAGE_DOS_SIGNATURE /* 'MZ' */ + .skip 58 /* 'MZ' + pad + offset == 64 */ + .long pe_header - image_base /* Offset to the PE header */ +pe_header: + .long IMAGE_NT_SIGNATURE /* 'PE' */ +coff_header: + .short IMAGE_FILE_MACHINE_THUMB /* Mixed ARM/Thumb */ + .short 2 /* nr_sections */ + .long 0 /* TimeDateStamp */ + .long 0 /* PointerToSymbolTable */ + .long 0 /* NumberOfSymbols */ + .short section_table - optional_header /* SizeOfOptionalHeader */ + /* Characteristics */ + .short (IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_LINE_NUMS_STRIPPED | \ + IMAGE_FILE_LOCAL_SYMS_STRIPPED | \ + IMAGE_FILE_32BIT_MACHINE | \ + IMAGE_FILE_DEBUG_STRIPPED) +optional_header: + .short IMAGE_NT_OPTIONAL_HDR32_MAGIC /* PE32 format */ + .byte 0x02 /* MajorLinkerVersion */ + .byte 0x14 /* MinorLinkerVersion */ + .long _edata - _start /* SizeOfCode */ + .long 0 /* SizeOfInitializedData */ + .long 0 /* SizeOfUninitializedData */ + .long _start - image_base /* AddressOfEntryPoint */ + .long _start - image_base /* BaseOfCode */ + .long 0 /* BaseOfData */ + +extra_header_fields: + .long 0 /* image_base */ + .long 0x20 /* SectionAlignment */ + .long 0x8 /* FileAlignment */ + .short 0 /* MajorOperatingSystemVersion */ + .short 0 /* MinorOperatingSystemVersion */ + .short 0 /* MajorImageVersion */ + .short 0 /* MinorImageVersion */ + .short 0 /* MajorSubsystemVersion */ + .short 0 /* MinorSubsystemVersion */ + .long 0 /* Win32VersionValue */ + + .long _edata - image_base /* SizeOfImage */ + + /* + * Everything before the kernel image is considered part of the header + */ + .long _start - image_base /* SizeOfHeaders */ + .long 0 /* CheckSum */ + .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */ + .short 0 /* DllCharacteristics */ + .long 0 /* SizeOfStackReserve */ + .long 0 /* SizeOfStackCommit */ + .long 0 /* SizeOfHeapReserve */ + .long 0 /* SizeOfHeapCommit */ + .long 0 /* LoaderFlags */ + .long 0x6 /* NumberOfRvaAndSizes */ + + .quad 0 /* ExportTable */ + .quad 0 /* ImportTable */ + .quad 0 /* ResourceTable */ + .quad 0 /* ExceptionTable */ + .quad 0 /* CertificationTable */ + .quad 0 /* BaseRelocationTable */ + +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long 0 + .long 0 + .long 0 /* SizeOfRawData */ + .long 0 /* PointerToRawData */ + .long 0 /* PointerToRelocations */ + .long 0 /* PointerToLineNumbers */ + .short 0 /* NumberOfRelocations */ + .short 0 /* NumberOfLineNumbers */ + .long 0x42100040 /* Characteristics (section flags) */ + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 /* end of 0 padding of section name */ + .long _edata - _start /* VirtualSize */ + .long _start - image_base /* VirtualAddress */ + .long _edata - _start /* SizeOfRawData */ + .long _start - image_base /* PointerToRawData */ + + .long 0 /* PointerToRelocations (0 for executables) */ + .long 0 /* PointerToLineNumbers (0 for executables) */ + .short 0 /* NumberOfRelocations (0 for executables) */ + .short 0 /* NumberOfLineNumbers (0 for executables) */ + .long 0xe0500020 /* Characteristics (section flags) */ + +_start: + stmfd sp!, {r0-r2, lr} + + adr r1, .L_DYNAMIC + ldr r0, [r1] + add r1, r0, r1 + adr r0, image_base + bl _relocate + teq r0, #0 + bne 0f + + ldmfd sp, {r0-r1} + bl efi_main + +0: add sp, sp, #12 + ldr pc, [sp], #4 + +.L_DYNAMIC: + .word _DYNAMIC - . diff --git a/roms/u-boot/arch/arm/lib/debug.S b/roms/u-boot/arch/arm/lib/debug.S new file mode 100644 index 000000000..5983f2c04 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/debug.S @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * linux/arch/arm/kernel/debug.S + * + * Copyright (C) 1994-1999 Russell King + * + * 32-bit debugging code + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + + .text + +/* + * Some debugging routines (useful if you've got MM problems and + * printk isn't working). For DEBUGGING ONLY!!! Do not leave + * references to these in a production kernel! + */ + +#if !defined(CONFIG_DEBUG_SEMIHOSTING) +#include CONFIG_DEBUG_LL_INCLUDE +#endif + +#ifdef CONFIG_MMU + .macro addruart_current, rx, tmp1, tmp2 + addruart \tmp1, \tmp2, \rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + moveq \rx, \tmp1 + movne \rx, \tmp2 + .endm + +#else /* !CONFIG_MMU */ + .macro addruart_current, rx, tmp1, tmp2 + addruart \rx, \tmp1, \tmp2 + .endm + +#endif /* CONFIG_MMU */ + +/* + * Useful debugging routines + */ +ENTRY(printhex8) + mov r1, #8 + b printhex +ENDPROC(printhex8) + +ENTRY(printhex4) + mov r1, #4 + b printhex +ENDPROC(printhex4) + +ENTRY(printhex2) + mov r1, #2 +printhex: adr r2, hexbuf + add r3, r2, r1 + mov r1, #0 + strb r1, [r3] +1: and r1, r0, #15 + mov r0, r0, lsr #4 + cmp r1, #10 + addlt r1, r1, #'0' + addge r1, r1, #'a' - 10 + strb r1, [r3, #-1]! + teq r3, r2 + bne 1b + mov r0, r2 + b printascii +ENDPROC(printhex2) + +hexbuf: .space 16 + + .ltorg + +#ifndef CONFIG_DEBUG_SEMIHOSTING + +ENTRY(printascii) + addruart_current r3, r1, r2 + b 2f +1: waituart r2, r3 + senduart r1, r3 + busyuart r2, r3 + teq r1, #'\n' + moveq r1, #'\r' + beq 1b +2: teq r0, #0 + ldrneb r1, [r0], #1 + teqne r1, #0 + bne 1b + mov pc, lr +ENDPROC(printascii) + +ENTRY(printch) + addruart_current r3, r1, r2 + mov r1, r0 + mov r0, #0 + b 1b +ENDPROC(printch) + +#ifdef CONFIG_MMU +ENTRY(debug_ll_addr) + addruart r2, r3, ip + str r2, [r0] + str r3, [r1] + mov pc, lr +ENDPROC(debug_ll_addr) +#endif + +#else + +ENTRY(printascii) + mov r1, r0 + mov r0, #0x04 @ SYS_WRITE0 + ARM( svc #0x123456 ) + THUMB( svc #0xab ) + mov pc, lr +ENDPROC(printascii) + +ENTRY(printch) + adr r1, hexbuf + strb r0, [r1] + mov r0, #0x03 @ SYS_WRITEC + ARM( svc #0x123456 ) + THUMB( svc #0xab ) + mov pc, lr +ENDPROC(printch) + +ENTRY(debug_ll_addr) + mov r2, #0 + str r2, [r0] + str r2, [r1] + mov pc, lr +ENDPROC(debug_ll_addr) + +#endif diff --git a/roms/u-boot/arch/arm/lib/div0.c b/roms/u-boot/arch/arm/lib/div0.c new file mode 100644 index 000000000..b91b408f6 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/div0.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <hang.h> + +/* Replacement (=dummy) for GNU/Linux division-by zero handler */ +void __div0 (void) +{ + hang(); +} diff --git a/roms/u-boot/arch/arm/lib/div64.S b/roms/u-boot/arch/arm/lib/div64.S new file mode 100644 index 000000000..3ef1ce1ff --- /dev/null +++ b/roms/u-boot/arch/arm/lib/div64.S @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * linux/arch/arm/lib/div64.S + * + * Optimized computation of 64-bit dividend / 32-bit divisor + * + * Author: Nicolas Pitre + * Created: Oct 5, 2003 + * Copyright: Monta Vista Software, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#ifdef __UBOOT__ +#define UNWIND(x...) +#endif + +#ifdef __ARMEB__ +#define xh r0 +#define xl r1 +#define yh r2 +#define yl r3 +#else +#define xl r0 +#define xh r1 +#define yl r2 +#define yh r3 +#endif + +/* + * __do_div64: perform a division with 64-bit dividend and 32-bit divisor. + * + * Note: Calling convention is totally non standard for optimal code. + * This is meant to be used by do_div() from include/asm/div64.h only. + * + * Input parameters: + * xh-xl = dividend (clobbered) + * r4 = divisor (preserved) + * + * Output values: + * yh-yl = result + * xh = remainder + * + * Clobbered regs: xl, ip + */ + +.pushsection .text.__do_div64, "ax" +ENTRY(__do_div64) +UNWIND(.fnstart) + + @ Test for easy paths first. + subs ip, r4, #1 + bls 9f @ divisor is 0 or 1 + tst ip, r4 + beq 8f @ divisor is power of 2 + + @ See if we need to handle upper 32-bit result. + cmp xh, r4 + mov yh, #0 + blo 3f + + @ Align divisor with upper part of dividend. + @ The aligned divisor is stored in yl preserving the original. + @ The bit position is stored in ip. + +#if __LINUX_ARM_ARCH__ >= 5 + + clz yl, r4 + clz ip, xh + sub yl, yl, ip + mov ip, #1 + mov ip, ip, lsl yl + mov yl, r4, lsl yl + +#else + + mov yl, r4 + mov ip, #1 +1: cmp yl, #0x80000000 + cmpcc yl, xh + movcc yl, yl, lsl #1 + movcc ip, ip, lsl #1 + bcc 1b + +#endif + + @ The division loop for needed upper bit positions. + @ Break out early if dividend reaches 0. +2: cmp xh, yl + orrcs yh, yh, ip + subscs xh, xh, yl + movsne ip, ip, lsr #1 + mov yl, yl, lsr #1 + bne 2b + + @ See if we need to handle lower 32-bit result. +3: cmp xh, #0 + mov yl, #0 + cmpeq xl, r4 + movlo xh, xl + retlo lr + + @ The division loop for lower bit positions. + @ Here we shift remainer bits leftwards rather than moving the + @ divisor for comparisons, considering the carry-out bit as well. + mov ip, #0x80000000 +4: movs xl, xl, lsl #1 + adcs xh, xh, xh + beq 6f + cmpcc xh, r4 +5: orrcs yl, yl, ip + subcs xh, xh, r4 + movs ip, ip, lsr #1 + bne 4b + ret lr + + @ The top part of remainder became zero. If carry is set + @ (the 33th bit) this is a false positive so resume the loop. + @ Otherwise, if lower part is also null then we are done. +6: bcs 5b + cmp xl, #0 + reteq lr + + @ We still have remainer bits in the low part. Bring them up. + +#if __LINUX_ARM_ARCH__ >= 5 + + clz xh, xl @ we know xh is zero here so... + add xh, xh, #1 + mov xl, xl, lsl xh + mov ip, ip, lsr xh + +#else + +7: movs xl, xl, lsl #1 + mov ip, ip, lsr #1 + bcc 7b + +#endif + + @ Current remainder is now 1. It is worthless to compare with + @ divisor at this point since divisor can not be smaller than 3 here. + @ If possible, branch for another shift in the division loop. + @ If no bit position left then we are done. + movs ip, ip, lsr #1 + mov xh, #1 + bne 4b + ret lr + +8: @ Division by a power of 2: determine what that divisor order is + @ then simply shift values around + +#if __LINUX_ARM_ARCH__ >= 5 + + clz ip, r4 + rsb ip, ip, #31 + +#else + + mov yl, r4 + cmp r4, #(1 << 16) + mov ip, #0 + movhs yl, yl, lsr #16 + movhs ip, #16 + + cmp yl, #(1 << 8) + movhs yl, yl, lsr #8 + addhs ip, ip, #8 + + cmp yl, #(1 << 4) + movhs yl, yl, lsr #4 + addhs ip, ip, #4 + + cmp yl, #(1 << 2) + addhi ip, ip, #3 + addls ip, ip, yl, lsr #1 + +#endif + + mov yh, xh, lsr ip + mov yl, xl, lsr ip + rsb ip, ip, #32 + ARM( orr yl, yl, xh, lsl ip ) + THUMB( lsl xh, xh, ip ) + THUMB( orr yl, yl, xh ) + mov xh, xl, lsl ip + mov xh, xh, lsr ip + ret lr + + @ eq -> division by 1: obvious enough... +9: moveq yl, xl + moveq yh, xh + moveq xh, #0 + reteq lr +UNWIND(.fnend) + +UNWIND(.fnstart) +UNWIND(.pad #4) +UNWIND(.save {lr}) +Ldiv0_64: + @ Division by 0: + str lr, [sp, #-8]! + bl __div0 + + @ as wrong as it could be... + mov yl, #0 + mov yh, #0 + mov xh, #0 + ldr pc, [sp], #8 + +UNWIND(.fnend) +ENDPROC(__do_div64) +.popsection diff --git a/roms/u-boot/arch/arm/lib/eabi_compat.c b/roms/u-boot/arch/arm/lib/eabi_compat.c new file mode 100644 index 000000000..f7029918d --- /dev/null +++ b/roms/u-boot/arch/arm/lib/eabi_compat.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Utility functions needed for (some) EABI conformant tool chains. + * + * (C) Copyright 2009 Wolfgang Denk <wd@denx.de> + */ + +#include <common.h> + +int raise (int signum) +{ + /* Even if printf() is available, it's large. Punt it for SPL builds */ +#if !defined(CONFIG_SPL_BUILD) + printf("raise: Signal # %d caught\n", signum); +#endif + return 0; +} + +/* Dummy function to avoid linker complaints */ +void __aeabi_unwind_cpp_pr0(void) +{ +} + +void __aeabi_unwind_cpp_pr1(void) +{ +} + +/* Copy memory like memcpy, but no return value required. */ +void __aeabi_memcpy(void *dest, const void *src, size_t n) +{ + (void) memcpy(dest, src, n); +} + +void __aeabi_memset(void *dest, size_t n, int c) +{ + (void) memset(dest, c, n); +} diff --git a/roms/u-boot/arch/arm/lib/elf_aarch64_efi.lds b/roms/u-boot/arch/arm/lib/elf_aarch64_efi.lds new file mode 100644 index 000000000..90af469f4 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/elf_aarch64_efi.lds @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * U-Boot aarch64 EFI linker script + * + * Modified from elf_aarch64_efi.lds in gnu-efi + */ + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * The EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + _edata = .; + } + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + .rela.got : { *(.rela.got) } + .rela.data : { *(.rela.data) *(.rela.data*) } + _data_size = . - _etext; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/roms/u-boot/arch/arm/lib/elf_arm_efi.lds b/roms/u-boot/arch/arm/lib/elf_arm_efi.lds new file mode 100644 index 000000000..d6d742e86 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/elf_arm_efi.lds @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * U-Boot ARM EFI linker script + * + * Modified from elf_arm_efi.lds in gnu-efi + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * The EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + _edata = .; + } + .rel.dyn : { *(.rel.dyn) } + .rel.plt : { *(.rel.plt) } + .rel.got : { *(.rel.got) } + .rel.data : { *(.rel.data) *(.rel.data*) } + _data_size = . - _etext; + + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + *(.dynsym) + *(.dynstr) + *(.note.gnu.build-id) + *(.comment) + } +} diff --git a/roms/u-boot/arch/arm/lib/gic-v3-its.c b/roms/u-boot/arch/arm/lib/gic-v3-its.c new file mode 100644 index 000000000..2d3fdb600 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/gic-v3-its.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Broadcom. + */ +#include <common.h> +#include <cpu_func.h> +#include <dm.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/gic.h> +#include <asm/gic-v3.h> +#include <asm/io.h> +#include <linux/bitops.h> +#include <linux/sizes.h> + +static u32 lpi_id_bits; + +#define LPI_NRBITS lpi_id_bits +#define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K) +#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) + +/* Number of GIC re-distributors */ +#define MAX_GIC_REDISTRIBUTORS 8 + +/* + * gic_v3_its_priv - gic details + * + * @gicd_base: gicd base address + * @gicr_base: gicr base address + * @lpi_base: gic lpi base address + * @num_redist: number of gic re-distributors + */ +struct gic_v3_its_priv { + ulong gicd_base; + ulong gicr_base; + ulong lpi_base; + u32 num_redist; +}; + +static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv) +{ + struct udevice *dev; + fdt_addr_t addr; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_IRQ, + DM_DRIVER_GET(arm_gic_v3_its), &dev); + if (ret) { + pr_err("%s: failed to get %s irq device\n", __func__, + DM_DRIVER_GET(arm_gic_v3_its)->name); + return ret; + } + + addr = dev_read_addr_index(dev, 0); + if (addr == FDT_ADDR_T_NONE) { + pr_err("%s: failed to get GICD address\n", __func__); + return -EINVAL; + } + priv->gicd_base = addr; + + addr = dev_read_addr_index(dev, 1); + if (addr == FDT_ADDR_T_NONE) { + pr_err("%s: failed to get GICR address\n", __func__); + return -EINVAL; + } + priv->gicr_base = addr; + + return 0; +} + +static int gic_v3_its_get_gic_lpi_addr(struct gic_v3_its_priv *priv) +{ + struct regmap *regmap; + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_SYSCON, + DM_DRIVER_GET(gic_lpi_syscon), &dev); + if (ret) { + pr_err("%s: failed to get %s syscon device\n", __func__, + DM_DRIVER_GET(gic_lpi_syscon)->name); + return ret; + } + + regmap = syscon_get_regmap(dev); + if (!regmap) { + pr_err("%s: failed to regmap for %s syscon device\n", __func__, + DM_DRIVER_GET(gic_lpi_syscon)->name); + return -ENODEV; + } + priv->lpi_base = regmap->ranges[0].start; + + priv->num_redist = dev_read_u32_default(dev, "max-gic-redistributors", + MAX_GIC_REDISTRIBUTORS); + + return 0; +} + +/* + * Program the GIC LPI configuration tables for all + * the re-distributors and enable the LPI table + */ +int gic_lpi_tables_init(void) +{ + struct gic_v3_its_priv priv; + u32 gicd_typer; + u64 val; + u64 tmp; + int i; + u64 redist_lpi_base; + u64 pend_base; + ulong pend_tab_total_sz; + void *pend_tab_va; + + if (gic_v3_its_get_gic_addr(&priv)) + return -EINVAL; + + if (gic_v3_its_get_gic_lpi_addr(&priv)) + return -EINVAL; + + gicd_typer = readl((uintptr_t)(priv.gicd_base + GICD_TYPER)); + /* GIC support for Locality specific peripheral interrupts (LPI's) */ + if (!(gicd_typer & GICD_TYPER_LPIS)) { + pr_err("GIC implementation does not support LPI's\n"); + return -EINVAL; + } + + /* + * Check for LPI is disabled for all the redistributors. + * Once the LPI table is enabled, can not program the + * LPI configuration tables again, unless the GIC is reset. + */ + for (i = 0; i < priv.num_redist; i++) { + u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; + + if ((readl((uintptr_t)(priv.gicr_base + offset))) & + GICR_CTLR_ENABLE_LPIS) { + pr_err("Re-Distributor %d LPI is already enabled\n", + i); + return -EINVAL; + } + } + + /* lpi_id_bits to get LPI_PENDBASE_SZ and LPi_PROPBASE_SZ */ + lpi_id_bits = min_t(u32, GICD_TYPER_ID_BITS(gicd_typer), + ITS_MAX_LPI_NRBITS); + + /* Set PropBase */ + val = (priv.lpi_base | + GICR_PROPBASER_INNERSHAREABLE | + GICR_PROPBASER_RAWAWB | + ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK)); + + writeq(val, (uintptr_t)(priv.gicr_base + GICR_PROPBASER)); + tmp = readl((uintptr_t)(priv.gicr_base + GICR_PROPBASER)); + if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { + if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { + val &= ~(GICR_PROPBASER_SHAREABILITY_MASK | + GICR_PROPBASER_CACHEABILITY_MASK); + val |= GICR_PROPBASER_NC; + writeq(val, + (uintptr_t)(priv.gicr_base + GICR_PROPBASER)); + } + } + + redist_lpi_base = priv.lpi_base + LPI_PROPBASE_SZ; + pend_tab_total_sz = priv.num_redist * LPI_PENDBASE_SZ; + pend_tab_va = map_physmem(redist_lpi_base, pend_tab_total_sz, + MAP_NOCACHE); + memset(pend_tab_va, 0, pend_tab_total_sz); + flush_cache((ulong)pend_tab_va, pend_tab_total_sz); + unmap_physmem(pend_tab_va, MAP_NOCACHE); + + pend_base = priv.gicr_base + GICR_PENDBASER; + for (i = 0; i < priv.num_redist; i++) { + u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; + + val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) | + GICR_PENDBASER_INNERSHAREABLE | + GICR_PENDBASER_RAWAWB | + GICR_PENDBASER_PTZ); + + writeq(val, (uintptr_t)(pend_base + offset)); + tmp = readq((uintptr_t)(pend_base + offset)); + if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { + val &= ~(GICR_PENDBASER_SHAREABILITY_MASK | + GICR_PENDBASER_CACHEABILITY_MASK); + val |= GICR_PENDBASER_NC; + writeq(val, (uintptr_t)(pend_base + offset)); + } + + /* Enable LPI for the redistributor */ + writel(GICR_CTLR_ENABLE_LPIS, + (uintptr_t)(priv.gicr_base + offset)); + } + + return 0; +} + +static const struct udevice_id gic_v3_its_ids[] = { + { .compatible = "arm,gic-v3" }, + {} +}; + +U_BOOT_DRIVER(arm_gic_v3_its) = { + .name = "gic-v3", + .id = UCLASS_IRQ, + .of_match = gic_v3_its_ids, +}; + +static const struct udevice_id gic_lpi_syscon_ids[] = { + { .compatible = "gic-lpi-base" }, + {} +}; + +U_BOOT_DRIVER(gic_lpi_syscon) = { + .name = "gic-lpi-base", + .id = UCLASS_SYSCON, + .of_match = gic_lpi_syscon_ids, +}; diff --git a/roms/u-boot/arch/arm/lib/gic_64.S b/roms/u-boot/arch/arm/lib/gic_64.S new file mode 100644 index 000000000..155212a41 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/gic_64.S @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * GIC Initialization Routines. + * + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/gic.h> +#include <asm/macro.h> + + +/************************************************************************* + * + * void gic_init_secure(DistributorBase); + * + * Initialize secure copy of GIC at EL3. + * + *************************************************************************/ +ENTRY(gic_init_secure) + /* + * Initialize Distributor + * x0: Distributor Base + */ +#if defined(CONFIG_GICV3) + mov w9, #0x37 /* EnableGrp0 | EnableGrp1NS */ + /* EnableGrp1S | ARE_S | ARE_NS */ + str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */ + ldr w9, [x0, GICD_TYPER] + and w10, w9, #0x1f /* ITLinesNumber */ + cbz w10, 1f /* No SPIs */ + add x11, x0, (GICD_IGROUPRn + 4) + add x12, x0, (GICD_IGROUPMODRn + 4) + mov w9, #~0 +0: str w9, [x11], #0x4 + str wzr, [x12], #0x4 /* Config SPIs as Group1NS */ + sub w10, w10, #0x1 + cbnz w10, 0b +#elif defined(CONFIG_GICV2) + mov w9, #0x3 /* EnableGrp0 | EnableGrp1 */ + str w9, [x0, GICD_CTLR] /* Secure GICD_CTLR */ + ldr w9, [x0, GICD_TYPER] + and w10, w9, #0x1f /* ITLinesNumber */ + cbz w10, 1f /* No SPIs */ + add x11, x0, GICD_IGROUPRn + mov w9, #~0 /* Config SPIs as Grp1 */ + str w9, [x11], #0x4 +0: str w9, [x11], #0x4 + sub w10, w10, #0x1 + cbnz w10, 0b + + ldr x1, =GICC_BASE /* GICC_CTLR */ + mov w0, #3 /* EnableGrp0 | EnableGrp1 */ + str w0, [x1] + + mov w0, #1 << 7 /* allow NS access to GICC_PMR */ + str w0, [x1, #4] /* GICC_PMR */ +#endif +1: + ret +ENDPROC(gic_init_secure) + + +/************************************************************************* + * For Gicv2: + * void gic_init_secure_percpu(DistributorBase, CpuInterfaceBase); + * For Gicv3: + * void gic_init_secure_percpu(ReDistributorBase); + * + * Initialize secure copy of GIC at EL3. + * + *************************************************************************/ +ENTRY(gic_init_secure_percpu) +#if defined(CONFIG_GICV3) + /* + * Initialize ReDistributor + * x0: ReDistributor Base + */ + mrs x10, mpidr_el1 + lsr x9, x10, #32 + bfi x10, x9, #24, #8 /* w10 is aff3:aff2:aff1:aff0 */ + mov x9, x0 +1: ldr x11, [x9, GICR_TYPER] + lsr x11, x11, #32 /* w11 is aff3:aff2:aff1:aff0 */ + cmp w10, w11 + b.eq 2f + add x9, x9, #(2 << 16) + b 1b + + /* x9: ReDistributor Base Address of Current CPU */ +2: mov w10, #~0x2 + ldr w11, [x9, GICR_WAKER] + and w11, w11, w10 /* Clear ProcessorSleep */ + str w11, [x9, GICR_WAKER] + dsb st + isb +3: ldr w10, [x9, GICR_WAKER] + tbnz w10, #2, 3b /* Wait Children be Alive */ + + add x10, x9, #(1 << 16) /* SGI_Base */ + mov w11, #~0 + str w11, [x10, GICR_IGROUPRn] + str wzr, [x10, GICR_IGROUPMODRn] /* SGIs|PPIs Group1NS */ + mov w11, #0x1 /* Enable SGI 0 */ + str w11, [x10, GICR_ISENABLERn] + + switch_el x10, 3f, 2f, 1f +3: + /* Initialize Cpu Interface */ + mrs x10, ICC_SRE_EL3 + orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */ + /* Allow EL2 access to ICC_SRE_EL2 */ + msr ICC_SRE_EL3, x10 + isb + + mov x10, #0x3 /* EnableGrp1NS | EnableGrp1S */ + msr ICC_IGRPEN1_EL3, x10 + isb + + msr ICC_CTLR_EL3, xzr + isb +2: + mrs x10, ICC_SRE_EL2 + orr x10, x10, #0xf /* SRE & Disable IRQ/FIQ Bypass & */ + /* Allow EL1 access to ICC_SRE_EL1 */ + msr ICC_SRE_EL2, x10 + isb +1: + msr ICC_CTLR_EL1, xzr /* NonSecure ICC_CTLR_EL1 */ + isb + + mov x10, #0x1 << 7 /* Non-Secure access to ICC_PMR_EL1 */ + msr ICC_PMR_EL1, x10 + isb +#elif defined(CONFIG_GICV2) + /* + * Initialize SGIs and PPIs + * x0: Distributor Base + * x1: Cpu Interface Base + */ + mov w9, #~0 /* Config SGIs and PPIs as Grp1 */ + str w9, [x0, GICD_IGROUPRn] /* GICD_IGROUPR0 */ + mov w9, #0x1 /* Enable SGI 0 */ + str w9, [x0, GICD_ISENABLERn] + + /* Initialize Cpu Interface */ + mov w9, #0x1e7 /* Disable IRQ/FIQ Bypass & */ + /* Enable Ack Group1 Interrupt & */ + /* EnableGrp0 & EnableGrp1 */ + str w9, [x1, GICC_CTLR] /* Secure GICC_CTLR */ + + mov w9, #0x1 << 7 /* Non-Secure access to GICC_PMR */ + str w9, [x1, GICC_PMR] +#endif + ret +ENDPROC(gic_init_secure_percpu) + + +/************************************************************************* + * For Gicv2: + * void gic_kick_secondary_cpus(DistributorBase); + * For Gicv3: + * void gic_kick_secondary_cpus(void); + * + *************************************************************************/ +ENTRY(gic_kick_secondary_cpus) +#if defined(CONFIG_GICV3) + mov x9, #(1 << 40) + msr ICC_ASGI1R_EL1, x9 + isb +#elif defined(CONFIG_GICV2) + mov w9, #0x8000 + movk w9, #0x100, lsl #16 + str w9, [x0, GICD_SGIR] +#endif + ret +ENDPROC(gic_kick_secondary_cpus) + + +/************************************************************************* + * For Gicv2: + * void gic_wait_for_interrupt(CpuInterfaceBase); + * For Gicv3: + * void gic_wait_for_interrupt(void); + * + * Wait for SGI 0 from master. + * + *************************************************************************/ +ENTRY(gic_wait_for_interrupt) +#if defined(CONFIG_GICV3) + gic_wait_for_interrupt_m x9 +#elif defined(CONFIG_GICV2) + gic_wait_for_interrupt_m x0, w9 +#endif + ret +ENDPROC(gic_wait_for_interrupt) diff --git a/roms/u-boot/arch/arm/lib/image.c b/roms/u-boot/arch/arm/lib/image.c new file mode 100644 index 000000000..e394c1ad9 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/image.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + */ + +#include <common.h> +#include <image.h> +#include <mapmem.h> +#include <asm/global_data.h> +#include <linux/bitops.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define LINUX_ARM64_IMAGE_MAGIC 0x644d5241 + +/* See Documentation/arm64/booting.txt in the Linux kernel */ +struct Image_header { + uint32_t code0; /* Executable code */ + uint32_t code1; /* Executable code */ + uint64_t text_offset; /* Image load offset, LE */ + uint64_t image_size; /* Effective Image size, LE */ + uint64_t flags; /* Kernel flags, LE */ + uint64_t res2; /* reserved */ + uint64_t res3; /* reserved */ + uint64_t res4; /* reserved */ + uint32_t magic; /* Magic number */ + uint32_t res5; +}; + +int booti_setup(ulong image, ulong *relocated_addr, ulong *size, + bool force_reloc) +{ + struct Image_header *ih; + uint64_t dst; + uint64_t image_size, text_offset; + + *relocated_addr = image; + + ih = (struct Image_header *)map_sysmem(image, 0); + + if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) { + puts("Bad Linux ARM64 Image magic!\n"); + return 1; + } + + /* + * Prior to Linux commit a2c1d73b94ed, the text_offset field + * is of unknown endianness. In these cases, the image_size + * field is zero, and we can assume a fixed value of 0x80000. + */ + if (ih->image_size == 0) { + puts("Image lacks image_size field, assuming 16MiB\n"); + image_size = 16 << 20; + text_offset = 0x80000; + } else { + image_size = le64_to_cpu(ih->image_size); + text_offset = le64_to_cpu(ih->text_offset); + } + + *size = image_size; + + /* + * If bit 3 of the flags field is set, the 2MB aligned base of the + * kernel image can be anywhere in physical memory, so respect + * images->ep. Otherwise, relocate the image to the base of RAM + * since memory below it is not accessible via the linear mapping. + */ + if (!force_reloc && (le64_to_cpu(ih->flags) & BIT(3))) + dst = image - text_offset; + else + dst = gd->bd->bi_dram[0].start; + + *relocated_addr = ALIGN(dst, SZ_2M) + text_offset; + + unmap_sysmem(ih); + + return 0; +} diff --git a/roms/u-boot/arch/arm/lib/interrupts.c b/roms/u-boot/arch/arm/lib/interrupts.c new file mode 100644 index 000000000..6dc27d1d5 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/interrupts.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + */ + +#include <common.h> +#include <cpu_func.h> +#include <efi_loader.h> +#include <irq_func.h> +#include <asm/global_data.h> +#include <asm/proc-armv/ptrace.h> +#include <asm/ptrace.h> +#include <asm/u-boot-arm.h> + +DECLARE_GLOBAL_DATA_PTR; + +int interrupt_init(void) +{ + /* + * setup up stacks if necessary + */ + IRQ_STACK_START_IN = gd->irq_sp + 8; + + enable_interrupts(); + + return 0; +} + +void enable_interrupts(void) +{ + return; +} +int disable_interrupts(void) +{ + return 0; +} + +void bad_mode (void) +{ + panic ("Resetting CPU ...\n"); + reset_cpu(); +} + +static void show_efi_loaded_images(struct pt_regs *regs) +{ + efi_print_image_infos((void *)instruction_pointer(regs)); +} + +static void dump_instr(struct pt_regs *regs) +{ + unsigned long addr = instruction_pointer(regs); + const int thumb = thumb_mode(regs); + const int width = thumb ? 4 : 8; + int i; + + if (thumb) + addr &= ~1L; + else + addr &= ~3L; + printf("Code: "); + for (i = -4; i < 1 + !!thumb; i++) { + unsigned int val; + + if (thumb) + val = ((u16 *)addr)[i]; + else + val = ((u32 *)addr)[i]; + printf(i == 0 ? "(%0*x) " : "%0*x ", width, val); + } + printf("\n"); +} + +void show_regs (struct pt_regs *regs) +{ + unsigned long __maybe_unused flags; + const char __maybe_unused *processor_modes[] = { + "USER_26", "FIQ_26", "IRQ_26", "SVC_26", + "UK4_26", "UK5_26", "UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", + "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", + "UK4_32", "UK5_32", "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "HYP_32", "UND_32", + "UK12_32", "UK13_32", "UK14_32", "SYS_32", + }; + + flags = condition_codes (regs); + + printf("pc : [<%08lx>] lr : [<%08lx>]\n", + instruction_pointer(regs), regs->ARM_lr); + if (gd->flags & GD_FLG_RELOC) { + printf("reloc pc : [<%08lx>] lr : [<%08lx>]\n", + instruction_pointer(regs) - gd->reloc_off, + regs->ARM_lr - gd->reloc_off); + } + printf("sp : %08lx ip : %08lx fp : %08lx\n", + regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf ("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf (" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled (regs) ? "on" : "off", + fast_interrupts_enabled (regs) ? "on" : "off", + processor_modes[processor_mode (regs)], + thumb_mode (regs) ? " (T)" : ""); + dump_instr(regs); +} + +/* fixup PC to point to the instruction leading to the exception */ +static inline void fixup_pc(struct pt_regs *regs, int offset) +{ + uint32_t pc = instruction_pointer(regs) + offset; + regs->ARM_pc = pc | (regs->ARM_pc & PCMASK); +} + +void do_undefined_instruction (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("undefined instruction\n"); + fixup_pc(pt_regs, -4); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} + +void do_software_interrupt (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("software interrupt\n"); + fixup_pc(pt_regs, -4); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} + +void do_prefetch_abort (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("prefetch abort\n"); + fixup_pc(pt_regs, -8); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} + +void do_data_abort (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("data abort\n"); + fixup_pc(pt_regs, -8); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} + +void do_not_used (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("not used\n"); + fixup_pc(pt_regs, -8); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} + +void do_fiq (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("fast interrupt request\n"); + fixup_pc(pt_regs, -8); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} + +void do_irq (struct pt_regs *pt_regs) +{ + efi_restore_gd(); + printf ("interrupt request\n"); + fixup_pc(pt_regs, -8); + show_regs (pt_regs); + show_efi_loaded_images(pt_regs); + bad_mode (); +} diff --git a/roms/u-boot/arch/arm/lib/interrupts_64.c b/roms/u-boot/arch/arm/lib/interrupts_64.c new file mode 100644 index 000000000..c653e67db --- /dev/null +++ b/roms/u-boot/arch/arm/lib/interrupts_64.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <common.h> +#include <asm/global_data.h> +#include <asm/ptrace.h> +#include <irq_func.h> +#include <linux/compiler.h> +#include <efi_loader.h> + +DECLARE_GLOBAL_DATA_PTR; + +int interrupt_init(void) +{ + enable_interrupts(); + + return 0; +} + +void enable_interrupts(void) +{ + return; +} + +int disable_interrupts(void) +{ + return 0; +} + +static void show_efi_loaded_images(struct pt_regs *regs) +{ + efi_print_image_infos((void *)regs->elr); +} + +static void dump_instr(struct pt_regs *regs) +{ + u32 *addr = (u32 *)(regs->elr & ~3UL); + int i; + + printf("Code: "); + for (i = -4; i < 1; i++) + printf(i == 0 ? "(%08x) " : "%08x ", addr[i]); + printf("\n"); +} + +void show_regs(struct pt_regs *regs) +{ + int i; + + if (gd->flags & GD_FLG_RELOC) + printf("elr: %016lx lr : %016lx (reloc)\n", + regs->elr - gd->reloc_off, + regs->regs[30] - gd->reloc_off); + printf("elr: %016lx lr : %016lx\n", regs->elr, regs->regs[30]); + + for (i = 0; i < 29; i += 2) + printf("x%-2d: %016lx x%-2d: %016lx\n", + i, regs->regs[i], i+1, regs->regs[i+1]); + printf("\n"); + dump_instr(regs); +} + +/* + * do_bad_sync handles the impossible case in the Synchronous Abort vector. + */ +void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_bad_irq handles the impossible case in the Irq vector. + */ +void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_bad_fiq handles the impossible case in the Fiq vector. + */ +void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_bad_error handles the impossible case in the Error vector. + */ +void do_bad_error(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_sync handles the Synchronous Abort exception. + */ +void do_sync(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_irq handles the Irq exception. + */ +void do_irq(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("\"Irq\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_fiq handles the Fiq exception. + */ +void do_fiq(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("\"Fiq\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} + +/* + * do_error handles the Error exception. + * Errors are more likely to be processor specific, + * it is defined with weak attribute and can be redefined + * in processor specific code. + */ +void __weak do_error(struct pt_regs *pt_regs, unsigned int esr) +{ + efi_restore_gd(); + printf("\"Error\" handler, esr 0x%08x\n", esr); + show_regs(pt_regs); + show_efi_loaded_images(pt_regs); + panic("Resetting CPU ...\n"); +} diff --git a/roms/u-boot/arch/arm/lib/interrupts_m.c b/roms/u-boot/arch/arm/lib/interrupts_m.c new file mode 100644 index 000000000..277854aa8 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/interrupts_m.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + */ + +#include <common.h> +#include <cpu_func.h> +#include <irq_func.h> + +/* + * Upon exception entry ARMv7-M processors automatically save stack + * frames containing some registers. For simplicity initial + * implementation uses only this auto-saved stack frame. + * This does not contain complete register set dump, + * only R0-R3, R12, LR, PC and xPSR are saved. + */ + +struct autosave_regs { + long uregs[8]; +}; + +#define ARM_XPSR uregs[7] +#define ARM_PC uregs[6] +#define ARM_LR uregs[5] +#define ARM_R12 uregs[4] +#define ARM_R3 uregs[3] +#define ARM_R2 uregs[2] +#define ARM_R1 uregs[1] +#define ARM_R0 uregs[0] + +int interrupt_init(void) +{ + enable_interrupts(); + + return 0; +} + +void enable_interrupts(void) +{ + return; +} + +int disable_interrupts(void) +{ + return 0; +} + +void dump_regs(struct autosave_regs *regs) +{ + printf("pc : %08lx lr : %08lx xPSR : %08lx\n", + regs->ARM_PC, regs->ARM_LR, regs->ARM_XPSR); + printf("r12 : %08lx r3 : %08lx r2 : %08lx\n" + "r1 : %08lx r0 : %08lx\n", + regs->ARM_R12, regs->ARM_R3, regs->ARM_R2, + regs->ARM_R1, regs->ARM_R0); +} + +void bad_mode(void) +{ + panic("Resetting CPU ...\n"); + reset_cpu(); +} + +void do_hard_fault(struct autosave_regs *autosave_regs) +{ + printf("Hard fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_mm_fault(struct autosave_regs *autosave_regs) +{ + printf("Memory management fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_bus_fault(struct autosave_regs *autosave_regs) +{ + printf("Bus fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_usage_fault(struct autosave_regs *autosave_regs) +{ + printf("Usage fault\n"); + dump_regs(autosave_regs); + bad_mode(); +} + +void do_invalid_entry(struct autosave_regs *autosave_regs) +{ + printf("Exception\n"); + dump_regs(autosave_regs); + bad_mode(); +} diff --git a/roms/u-boot/arch/arm/lib/lib1funcs.S b/roms/u-boot/arch/arm/lib/lib1funcs.S new file mode 100644 index 000000000..0798d098a --- /dev/null +++ b/roms/u-boot/arch/arm/lib/lib1funcs.S @@ -0,0 +1,427 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines + * + * Author: Nicolas Pitre <nico@fluxnic.net> + * - contributed to gcc-3.4 on Sep 30, 2003 + * - adapted for the Linux kernel on Oct 2, 2003 + */ +/* + * Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +/* + * U-Boot compatibility bit, define empty UNWIND() macro as, since we + * do not support stack unwinding and define CONFIG_AEABI to make all + * of the functions available without diverging from Linux code. + */ +#ifdef __UBOOT__ +#define UNWIND(x...) +#define CONFIG_AEABI +#endif + +.macro ARM_DIV_BODY dividend, divisor, result, curbit + +#if __LINUX_ARM_ARCH__ >= 5 + + clz \curbit, \divisor + clz \result, \dividend + sub \result, \curbit, \result + mov \curbit, #1 + mov \divisor, \divisor, lsl \result + mov \curbit, \curbit, lsl \result + mov \result, #0 + +#else + + @ Initially shift the divisor left 3 bits if possible, + @ set curbit accordingly. This allows for curbit to be located + @ at the left end of each 4 bit nibbles in the division loop + @ to save one loop in most cases. + tst \divisor, #0xe0000000 + moveq \divisor, \divisor, lsl #3 + moveq \curbit, #8 + movne \curbit, #1 + + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + movlo \curbit, \curbit, lsl #4 + blo 1b + + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + movlo \curbit, \curbit, lsl #1 + blo 1b + + mov \result, #0 + +#endif + + @ Division loop +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + orrhs \result, \result, \curbit + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + orrhs \result, \result, \curbit, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + orrhs \result, \result, \curbit, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + orrhs \result, \result, \curbit, lsr #3 + cmp \dividend, #0 @ Early termination? + movsne \curbit, \curbit, lsr #4 @ No, any more bits to do? + movne \divisor, \divisor, lsr #4 + bne 1b + +.endm + + +.macro ARM_DIV2_ORDER divisor, order + +#if __LINUX_ARM_ARCH__ >= 5 + + clz \order, \divisor + rsb \order, \order, #31 + +#else + + cmp \divisor, #(1 << 16) + movhs \divisor, \divisor, lsr #16 + movhs \order, #16 + movlo \order, #0 + + cmp \divisor, #(1 << 8) + movhs \divisor, \divisor, lsr #8 + addhs \order, \order, #8 + + cmp \divisor, #(1 << 4) + movhs \divisor, \divisor, lsr #4 + addhs \order, \order, #4 + + cmp \divisor, #(1 << 2) + addhi \order, \order, #3 + addls \order, \order, \divisor, lsr #1 + +#endif + +.endm + + +.macro ARM_MOD_BODY dividend, divisor, order, spare + +#if __LINUX_ARM_ARCH__ >= 5 + + clz \order, \divisor + clz \spare, \dividend + sub \order, \order, \spare + mov \divisor, \divisor, lsl \order + +#else + + mov \order, #0 + + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. +1: cmp \divisor, #0x10000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #4 + addlo \order, \order, #4 + blo 1b + + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. +1: cmp \divisor, #0x80000000 + cmplo \divisor, \dividend + movlo \divisor, \divisor, lsl #1 + addlo \order, \order, #1 + blo 1b + +#endif + + @ Perform all needed subtractions to keep only the reminder. + @ Do comparisons in batch of 4 first. + subs \order, \order, #3 @ yes, 3 is intended here + blt 2f + +1: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + cmp \dividend, \divisor, lsr #1 + subhs \dividend, \dividend, \divisor, lsr #1 + cmp \dividend, \divisor, lsr #2 + subhs \dividend, \dividend, \divisor, lsr #2 + cmp \dividend, \divisor, lsr #3 + subhs \dividend, \dividend, \divisor, lsr #3 + cmp \dividend, #1 + mov \divisor, \divisor, lsr #4 + subsge \order, \order, #4 + bge 1b + + tst \order, #3 + teqne \dividend, #0 + beq 5f + + @ Either 1, 2 or 3 comparison/subtractions are left. +2: cmn \order, #2 + blt 4f + beq 3f + cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +3: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor + mov \divisor, \divisor, lsr #1 +4: cmp \dividend, \divisor + subhs \dividend, \dividend, \divisor +5: +.endm + + +.pushsection .text.__udivsi3, "ax" +ENTRY(__udivsi3) +ENTRY(__aeabi_uidiv) +UNWIND(.fnstart) + + subs r2, r1, #1 + reteq lr + bcc Ldiv0 + cmp r0, r1 + bls 11f + tst r1, r2 + beq 12f + + ARM_DIV_BODY r0, r1, r2, r3 + + mov r0, r2 + ret lr + +11: moveq r0, #1 + movne r0, #0 + ret lr + +12: ARM_DIV2_ORDER r1, r2 + + mov r0, r0, lsr r2 + ret lr + +UNWIND(.fnend) +ENDPROC(__udivsi3) +ENDPROC(__aeabi_uidiv) +.popsection + +.pushsection .text.__umodsi3, "ax" +ENTRY(__umodsi3) +UNWIND(.fnstart) + + subs r2, r1, #1 @ compare divisor with 1 + bcc Ldiv0 + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + retls lr + + ARM_MOD_BODY r0, r1, r2, r3 + + ret lr + +UNWIND(.fnend) +ENDPROC(__umodsi3) +.popsection + +.pushsection .text.__divsi3, "ax" +ENTRY(__divsi3) +ENTRY(__aeabi_idiv) +UNWIND(.fnstart) + + cmp r1, #0 + eor ip, r0, r1 @ save the sign of the result. + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + subs r2, r1, #1 @ division by 1 or -1 ? + beq 10f + movs r3, r0 + rsbmi r3, r0, #0 @ positive dividend value + cmp r3, r1 + bls 11f + tst r1, r2 @ divisor is power of 2 ? + beq 12f + + ARM_DIV_BODY r3, r1, r0, r2 + + cmp ip, #0 + rsbmi r0, r0, #0 + ret lr + +10: teq ip, r0 @ same sign ? + rsbmi r0, r0, #0 + ret lr + +11: movlo r0, #0 + moveq r0, ip, asr #31 + orreq r0, r0, #1 + ret lr + +12: ARM_DIV2_ORDER r1, r2 + + cmp ip, #0 + mov r0, r3, lsr r2 + rsbmi r0, r0, #0 + ret lr + +UNWIND(.fnend) +ENDPROC(__divsi3) +ENDPROC(__aeabi_idiv) +.popsection + +.pushsection .text.__modsi3, "ax" +ENTRY(__modsi3) +UNWIND(.fnstart) + + cmp r1, #0 + beq Ldiv0 + rsbmi r1, r1, #0 @ loops below use unsigned. + movs ip, r0 @ preserve sign of dividend + rsbmi r0, r0, #0 @ if negative make positive + subs r2, r1, #1 @ compare divisor with 1 + cmpne r0, r1 @ compare dividend with divisor + moveq r0, #0 + tsthi r1, r2 @ see if divisor is power of 2 + andeq r0, r0, r2 + bls 10f + + ARM_MOD_BODY r0, r1, r2, r3 + +10: cmp ip, #0 + rsbmi r0, r0, #0 + ret lr + +UNWIND(.fnend) +ENDPROC(__modsi3) +.popsection + +#ifdef CONFIG_AEABI + +.pushsection .text.__aeabi_uidivmod, "ax" +ENTRY(__aeabi_uidivmod) +UNWIND(.fnstart) +UNWIND(.save {r0, r1, ip, lr} ) + + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_uidiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + ret lr + +UNWIND(.fnend) +ENDPROC(__aeabi_uidivmod) +.popsection + +.pushsection .text.__aeabi_uidivmod, "ax" +ENTRY(__aeabi_idivmod) +UNWIND(.fnstart) +UNWIND(.save {r0, r1, ip, lr} ) + + stmfd sp!, {r0, r1, ip, lr} + bl __aeabi_idiv + ldmfd sp!, {r1, r2, ip, lr} + mul r3, r0, r2 + sub r1, r1, r3 + ret lr + +UNWIND(.fnend) +ENDPROC(__aeabi_idivmod) +.popsection + +#endif + +.pushsection .text.Ldiv0, "ax" +Ldiv0: +UNWIND(.fnstart) +UNWIND(.pad #4) +UNWIND(.save {lr}) + + str lr, [sp, #-8]! + bl __div0 + mov r0, #0 @ About as wrong as it could be. + ldr pc, [sp], #8 + +UNWIND(.fnend) +ENDPROC(Ldiv0) +.popsection + +/* Thumb-1 specialities */ +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(CONFIG_HAS_THUMB2) +.pushsection .text.__gnu_thumb1_case_sqi, "ax" +ENTRY(__gnu_thumb1_case_sqi) + push {r1} + mov r1, lr + lsrs r1, r1, #1 + lsls r1, r1, #1 + ldrsb r1, [r1, r0] + lsls r1, r1, #1 + add lr, lr, r1 + pop {r1} + bx lr +ENDPROC(__gnu_thumb1_case_sqi) +.popsection + +.pushsection .text.__gnu_thumb1_case_uqi, "ax" +ENTRY(__gnu_thumb1_case_uqi) + push {r1} + mov r1, lr + lsrs r1, r1, #1 + lsls r1, r1, #1 + ldrb r1, [r1, r0] + lsls r1, r1, #1 + add lr, lr, r1 + pop {r1} + bx lr +ENDPROC(__gnu_thumb1_case_uqi) +.popsection + +.pushsection .text.__gnu_thumb1_case_shi, "ax" +ENTRY(__gnu_thumb1_case_shi) + push {r0, r1} + mov r1, lr + lsrs r1, r1, #1 + lsls r0, r0, #1 + lsls r1, r1, #1 + ldrsh r1, [r1, r0] + lsls r1, r1, #1 + add lr, lr, r1 + pop {r0, r1} + bx lr +ENDPROC(__gnu_thumb1_case_shi) +.popsection + +.pushsection .text.__gnu_thumb1_case_uhi, "ax" +ENTRY(__gnu_thumb1_case_uhi) + push {r0, r1} + mov r1, lr + lsrs r1, r1, #1 + lsls r0, r0, #1 + lsls r1, r1, #1 + ldrh r1, [r1, r0] + lsls r1, r1, #1 + add lr, lr, r1 + pop {r0, r1} + bx lr +ENDPROC(__gnu_thumb1_case_uhi) +.popsection +#endif diff --git a/roms/u-boot/arch/arm/lib/lshrdi3.S b/roms/u-boot/arch/arm/lib/lshrdi3.S new file mode 100644 index 000000000..cfa5607c5 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/lshrdi3.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005 + Free Software Foundation, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +#ifdef __ARMEB__ +#define al r1 +#define ah r0 +#else +#define al r0 +#define ah r1 +#endif + +.pushsection .text.__lshldi3, "ax" +ENTRY(__lshrdi3) +ENTRY(__aeabi_llsr) + + subs r3, r2, #32 + rsb ip, r2, #32 + movmi al, al, lsr r2 + movpl al, ah, lsr r3 + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) + mov ah, ah, lsr r2 + ret lr + +ENDPROC(__lshrdi3) +ENDPROC(__aeabi_llsr) +.popsection diff --git a/roms/u-boot/arch/arm/lib/memcpy.S b/roms/u-boot/arch/arm/lib/memcpy.S new file mode 100644 index 000000000..f7fb77235 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/memcpy.S @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * linux/arch/arm/lib/memcpy.S + * + * Author: Nicolas Pitre + * Created: Sep 28, 2005 + * Copyright: MontaVista Software, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +#define LDR1W_SHIFT 0 +#define STR1W_SHIFT 0 + + .macro ldr1w ptr reg abort + W(ldr) \reg, [\ptr], #4 + .endm + + .macro ldr4w ptr reg1 reg2 reg3 reg4 abort + ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4} + .endm + + .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort + ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} + .endm + + .macro ldr1b ptr reg cond=al abort + ldrb\cond\() \reg, [\ptr], #1 + .endm + + .macro str1w ptr reg abort + W(str) \reg, [\ptr], #4 + .endm + + .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort + stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8} + .endm + + .macro str1b ptr reg cond=al abort + strb\cond\() \reg, [\ptr], #1 + .endm + + .macro enter reg1 reg2 + stmdb sp!, {r0, \reg1, \reg2} + .endm + + .macro exit reg1 reg2 + ldmfd sp!, {r0, \reg1, \reg2} + .endm + + .text + +/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ + .syntax unified +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(MEMCPY_NO_THUMB_BUILD) + .thumb + .thumb_func +#endif +ENTRY(memcpy) + cmp r0, r1 + bxeq lr + + enter r4, lr + + subs r2, r2, #4 + blt 8f + ands ip, r0, #3 + PLD( pld [r1, #0] ) + bne 9f + ands ip, r1, #3 + bne 10f + +1: subs r2, r2, #(28) + stmfd sp!, {r5 - r8} + blt 5f + + CALGN( ands ip, r0, #31 ) + CALGN( rsb r3, ip, #32 ) + CALGN( sbcsne r4, r3, r2 ) @ C is always set here + CALGN( bcs 2f ) + CALGN( adr r4, 6f ) + CALGN( subs r2, r2, r3 ) @ C gets set + CALGN( add pc, r4, ip ) + + PLD( pld [r1, #0] ) +2: PLD( subs r2, r2, #96 ) + PLD( pld [r1, #28] ) + PLD( blt 4f ) + PLD( pld [r1, #60] ) + PLD( pld [r1, #92] ) + +3: PLD( pld [r1, #124] ) +4: ldr8w r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f + subs r2, r2, #32 + str8w r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f + bge 3b + PLD( cmn r2, #96 ) + PLD( bge 4b ) + +5: ands ip, r2, #28 + rsb ip, ip, #32 +#if LDR1W_SHIFT > 0 + lsl ip, ip, #LDR1W_SHIFT +#endif + addne pc, pc, ip @ C is always clear here + b 7f +6: + .rept (1 << LDR1W_SHIFT) + W(nop) + .endr + ldr1w r1, r3, abort=20f + ldr1w r1, r4, abort=20f + ldr1w r1, r5, abort=20f + ldr1w r1, r6, abort=20f + ldr1w r1, r7, abort=20f + ldr1w r1, r8, abort=20f + ldr1w r1, lr, abort=20f + +#if LDR1W_SHIFT < STR1W_SHIFT + lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT +#elif LDR1W_SHIFT > STR1W_SHIFT + lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT +#endif + add pc, pc, ip + nop + .rept (1 << STR1W_SHIFT) + W(nop) + .endr + str1w r0, r3, abort=20f + str1w r0, r4, abort=20f + str1w r0, r5, abort=20f + str1w r0, r6, abort=20f + str1w r0, r7, abort=20f + str1w r0, r8, abort=20f + str1w r0, lr, abort=20f + + CALGN( bcs 2b ) + +7: ldmfd sp!, {r5 - r8} + +8: movs r2, r2, lsl #31 + ldr1b r1, r3, ne, abort=21f + ldr1b r1, r4, cs, abort=21f + ldr1b r1, ip, cs, abort=21f + str1b r0, r3, ne, abort=21f + str1b r0, r4, cs, abort=21f + str1b r0, ip, cs, abort=21f + + exit r4, lr + bx lr + +9: rsb ip, ip, #4 + cmp ip, #2 + ldr1b r1, r3, gt, abort=21f + ldr1b r1, r4, ge, abort=21f + ldr1b r1, lr, abort=21f + str1b r0, r3, gt, abort=21f + str1b r0, r4, ge, abort=21f + subs r2, r2, ip + str1b r0, lr, abort=21f + blt 8b + ands ip, r1, #3 + beq 1b + +10: bic r1, r1, #3 + cmp ip, #2 + ldr1w r1, lr, abort=21f + beq 17f + bgt 18f + + + .macro forward_copy_shift pull push + + subs r2, r2, #28 + blt 14f + + CALGN( ands ip, r0, #31 ) + CALGN( rsb ip, ip, #32 ) + CALGN( sbcsne r4, ip, r2 ) @ C is always set here + CALGN( subcc r2, r2, ip ) + CALGN( bcc 15f ) + +11: stmfd sp!, {r5 - r9} + + PLD( pld [r1, #0] ) + PLD( subs r2, r2, #96 ) + PLD( pld [r1, #28] ) + PLD( blt 13f ) + PLD( pld [r1, #60] ) + PLD( pld [r1, #92] ) + +12: PLD( pld [r1, #124] ) +13: ldr4w r1, r4, r5, r6, r7, abort=19f + mov r3, lr, lspull #\pull + subs r2, r2, #32 + ldr4w r1, r8, r9, ip, lr, abort=19f + orr r3, r3, r4, lspush #\push + mov r4, r4, lspull #\pull + orr r4, r4, r5, lspush #\push + mov r5, r5, lspull #\pull + orr r5, r5, r6, lspush #\push + mov r6, r6, lspull #\pull + orr r6, r6, r7, lspush #\push + mov r7, r7, lspull #\pull + orr r7, r7, r8, lspush #\push + mov r8, r8, lspull #\pull + orr r8, r8, r9, lspush #\push + mov r9, r9, lspull #\pull + orr r9, r9, ip, lspush #\push + mov ip, ip, lspull #\pull + orr ip, ip, lr, lspush #\push + str8w r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f + bge 12b + PLD( cmn r2, #96 ) + PLD( bge 13b ) + + ldmfd sp!, {r5 - r9} + +14: ands ip, r2, #28 + beq 16f + +15: mov r3, lr, lspull #\pull + ldr1w r1, lr, abort=21f + subs ip, ip, #4 + orr r3, r3, lr, lspush #\push + str1w r0, r3, abort=21f + bgt 15b + CALGN( cmp r2, #0 ) + CALGN( bge 11b ) + +16: sub r1, r1, #(\push / 8) + b 8b + + .endm + + + forward_copy_shift pull=8 push=24 + +17: forward_copy_shift pull=16 push=16 + +18: forward_copy_shift pull=24 push=8 + + +/* + * Abort preamble and completion macros. + * If a fixup handler is required then those macros must surround it. + * It is assumed that the fixup code will handle the private part of + * the exit macro. + */ + + .macro copy_abort_preamble +19: ldmfd sp!, {r5 - r9} + b 21f +20: ldmfd sp!, {r5 - r8} +21: + .endm + + .macro copy_abort_end + ldmfd sp!, {r4, lr} + bx lr + .endm + +ENDPROC(memcpy) diff --git a/roms/u-boot/arch/arm/lib/memset.S b/roms/u-boot/arch/arm/lib/memset.S new file mode 100644 index 000000000..2277d1202 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/memset.S @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * linux/arch/arm/lib/memset.S + * + * Copyright (C) 1995-2000 Russell King + * + * ASM optimised string functions + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + + .text + .align 5 + + .syntax unified +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(MEMSET_NO_THUMB_BUILD) + .thumb + .thumb_func +#endif +ENTRY(memset) + ands r3, r0, #3 @ 1 unaligned? + mov ip, r0 @ preserve r0 as return value + bne 6f @ 1 +/* + * we know that the pointer in ip is aligned to a word boundary. + */ +1: orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + mov r3, r1 + cmp r2, #16 + blt 4f + +#if ! CALGN(1)+0 + +/* + * We need 2 extra registers for this loop - use r8 and the LR + */ + stmfd sp!, {r8, lr} + mov r8, r1 + mov lr, r1 + +2: subs r2, r2, #64 + stmiage ip!, {r1, r3, r8, lr} @ 64 bytes at a time. + stmiage ip!, {r1, r3, r8, lr} + stmiage ip!, {r1, r3, r8, lr} + stmiage ip!, {r1, r3, r8, lr} + bgt 2b + ldmfdeq sp!, {r8, pc} @ Now <64 bytes to go. +/* + * No need to correct the count; we're only testing bits from now on + */ + tst r2, #32 + stmiane ip!, {r1, r3, r8, lr} + stmiane ip!, {r1, r3, r8, lr} + tst r2, #16 + stmiane ip!, {r1, r3, r8, lr} + ldmfd sp!, {r8, lr} + +#else + +/* + * This version aligns the destination pointer in order to write + * whole cache lines at once. + */ + + stmfd sp!, {r4-r8, lr} + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov r8, r1 + mov lr, r1 + + cmp r2, #96 + tstgt ip, #31 + ble 3f + + and r8, ip, #31 + rsb r8, r8, #32 + sub r2, r2, r8 + movs r8, r8, lsl #(32 - 4) + stmiacs ip!, {r4, r5, r6, r7} + stmiami ip!, {r4, r5} + tst r8, #(1 << 30) + mov r8, r1 + strne r1, [ip], #4 + +3: subs r2, r2, #64 + stmiage ip!, {r1, r3-r8, lr} + stmiage ip!, {r1, r3-r8, lr} + bgt 3b + ldmfdeq sp!, {r4-r8, pc} + + tst r2, #32 + stmiane ip!, {r1, r3-r8, lr} + tst r2, #16 + stmiane ip!, {r4-r7} + ldmfd sp!, {r4-r8, lr} + +#endif + +4: tst r2, #8 + stmiane ip!, {r1, r3} + tst r2, #4 + strne r1, [ip], #4 +/* + * When we get here, we've got less than 4 bytes to zero. We + * may have an unaligned pointer as well. + */ +5: tst r2, #2 + strbne r1, [ip], #1 + strbne r1, [ip], #1 + tst r2, #1 + strbne r1, [ip], #1 + ret lr + +6: subs r2, r2, #4 @ 1 do we have enough + blt 5b @ 1 bytes to align with? + cmp r3, #2 @ 1 + strblt r1, [ip], #1 @ 1 + strble r1, [ip], #1 @ 1 + strb r1, [ip], #1 @ 1 + add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) + b 1b +ENDPROC(memset) diff --git a/roms/u-boot/arch/arm/lib/muldi3.S b/roms/u-boot/arch/arm/lib/muldi3.S new file mode 100644 index 000000000..e6c918119 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/muldi3.S @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * linux/arch/arm/lib/muldi3.S + * + * Author: Nicolas Pitre + * Created: Oct 19, 2005 + * Copyright: Monta Vista Software, Inc. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +#ifdef __ARMEB__ +#define xh r0 +#define xl r1 +#define yh r2 +#define yl r3 +#else +#define xl r0 +#define xh r1 +#define yl r2 +#define yh r3 +#endif + +.pushsection .text.__muldi3, "ax" +ENTRY(__muldi3) +ENTRY(__aeabi_lmul) + + mul xh, yl, xh + mla xh, xl, yh, xh + mov ip, xl, lsr #16 + mov yh, yl, lsr #16 + bic xl, xl, ip, lsl #16 + bic yl, yl, yh, lsl #16 + mla xh, yh, ip, xh + mul yh, xl, yh + mul xl, yl, xl + mul ip, yl, ip + adds xl, xl, yh, lsl #16 + adc xh, xh, yh, lsr #16 + adds xl, xl, ip, lsl #16 + adc xh, xh, ip, lsr #16 + ret lr + +ENDPROC(__muldi3) +ENDPROC(__aeabi_lmul) +.popsection diff --git a/roms/u-boot/arch/arm/lib/psci-dt.c b/roms/u-boot/arch/arm/lib/psci-dt.c new file mode 100644 index 000000000..903b33570 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/psci-dt.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 NXP Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/cache.h> +#include <linux/libfdt.h> +#include <fdt_support.h> +#include <linux/sizes.h> +#include <linux/kernel.h> +#include <asm/psci.h> +#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT) +#include <asm/armv8/sec_firmware.h> +#endif + +int fdt_psci(void *fdt) +{ +#if defined(CONFIG_ARMV7_PSCI) || defined(CONFIG_ARMV8_PSCI) || \ + defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI) + int nodeoff; + unsigned int psci_ver = 0; + int tmp; + + nodeoff = fdt_path_offset(fdt, "/cpus"); + if (nodeoff < 0) { + printf("couldn't find /cpus\n"); + return nodeoff; + } + + /* add 'enable-method = "psci"' to each cpu node */ + for (tmp = fdt_first_subnode(fdt, nodeoff); + tmp >= 0; + tmp = fdt_next_subnode(fdt, tmp)) { + const struct fdt_property *prop; + int len; + + prop = fdt_get_property(fdt, tmp, "device_type", &len); + if (!prop) + continue; + if (len < 4) + continue; + if (strcmp(prop->data, "cpu")) + continue; + + /* + * Not checking rv here, our approach is to skip over errors in + * individual cpu nodes, hopefully some of the nodes are + * processed correctly and those will boot + */ + fdt_setprop_string(fdt, tmp, "enable-method", "psci"); + } + + nodeoff = fdt_path_offset(fdt, "/psci"); + if (nodeoff >= 0) + goto init_psci_node; + + nodeoff = fdt_path_offset(fdt, "/"); + if (nodeoff < 0) + return nodeoff; + + nodeoff = fdt_add_subnode(fdt, nodeoff, "psci"); + if (nodeoff < 0) + return nodeoff; + +init_psci_node: +#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT) + psci_ver = sec_firmware_support_psci_version(); +#elif defined(CONFIG_ARMV7_PSCI_1_0) || defined(CONFIG_ARMV8_PSCI) + psci_ver = ARM_PSCI_VER_1_0; +#elif defined(CONFIG_ARMV7_PSCI_0_2) + psci_ver = ARM_PSCI_VER_0_2; +#endif + if (psci_ver >= ARM_PSCI_VER_1_0) { + tmp = fdt_setprop_string(fdt, nodeoff, + "compatible", "arm,psci-1.0"); + if (tmp) + return tmp; + } + + if (psci_ver >= ARM_PSCI_VER_0_2) { + tmp = fdt_appendprop_string(fdt, nodeoff, + "compatible", "arm,psci-0.2"); + if (tmp) + return tmp; + } + +#if !CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT) + /* + * The Secure firmware framework isn't able to support PSCI version 0.1. + */ + if (psci_ver < ARM_PSCI_VER_0_2) { + tmp = fdt_appendprop_string(fdt, nodeoff, + "compatible", "arm,psci"); + if (tmp) + return tmp; + tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend", + ARM_PSCI_FN_CPU_SUSPEND); + if (tmp) + return tmp; + tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off", + ARM_PSCI_FN_CPU_OFF); + if (tmp) + return tmp; + tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on", + ARM_PSCI_FN_CPU_ON); + if (tmp) + return tmp; + tmp = fdt_setprop_u32(fdt, nodeoff, "migrate", + ARM_PSCI_FN_MIGRATE); + if (tmp) + return tmp; + } +#endif + + tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc"); + if (tmp) + return tmp; + + tmp = fdt_setprop_string(fdt, nodeoff, "status", "okay"); + if (tmp) + return tmp; + +#endif + return 0; +} diff --git a/roms/u-boot/arch/arm/lib/reloc_aarch64_efi.c b/roms/u-boot/arch/arm/lib/reloc_aarch64_efi.c new file mode 100644 index 000000000..1aa57dbc8 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/reloc_aarch64_efi.c @@ -0,0 +1,86 @@ +/* reloc_aarch64.c - position independent x86 ELF shared object relocator + Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger <davidm@hpl.hp.com>. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include <efi.h> + +#include <elf.h> + +efi_status_t EFIAPI _relocate(long ldbase, Elf64_Dyn *dyn) +{ + long relsz = 0, relent = 0; + Elf64_Rela *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rela *)((ulong)dyn[i].d_un.d_ptr + ldbase); + break; + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE(rel->r_info)) { + case R_AARCH64_NONE: + break; + case R_AARCH64_RELATIVE: + addr = (ulong *)(ldbase + rel->r_offset); + *addr = ldbase + rel->r_addend; + break; + default: + break; + } + rel = (Elf64_Rela *)((char *)rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/roms/u-boot/arch/arm/lib/reloc_arm_efi.c b/roms/u-boot/arch/arm/lib/reloc_arm_efi.c new file mode 100644 index 000000000..9103c035c --- /dev/null +++ b/roms/u-boot/arch/arm/lib/reloc_arm_efi.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * reloc_arm.c - position-independent ARM ELF shared object relocator + * + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger <davidm@hpl.hp.com>. + * + * All rights reserved. + * + * This file is taken and modified from the gnu-efi project. + */ + +#include <efi.h> +#include <elf.h> + +efi_status_t EFIAPI _relocate(long ldbase, Elf32_Dyn *dyn) +{ + long relsz = 0, relent = 0; + Elf32_Rel *rel = 0; + ulong *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf32_Rel *)((ulong)dyn[i].d_un.d_ptr + + ldbase); + break; + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_NONE: + break; + case R_ARM_RELATIVE: + addr = (ulong *)(ldbase + rel->r_offset); + *addr += ldbase; + break; + default: + break; + } + rel = (Elf32_Rel *)((char *)rel + relent); + relsz -= relent; + } + + return EFI_SUCCESS; +} diff --git a/roms/u-boot/arch/arm/lib/relocate.S b/roms/u-boot/arch/arm/lib/relocate.S new file mode 100644 index 000000000..e5f7267be --- /dev/null +++ b/roms/u-boot/arch/arm/lib/relocate.S @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - common relocation function for ARM U-Boot + * + * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <asm-offsets.h> +#include <asm/assembler.h> +#include <config.h> +#include <elf.h> +#include <linux/linkage.h> +#ifdef CONFIG_CPU_V7M +#include <asm/armv7m.h> +#endif + +/* + * Default/weak exception vectors relocation routine + * + * This routine covers the standard ARM cases: normal (0x00000000), + * high (0xffff0000) and VBAR. SoCs which do not comply with any of + * the standard cases must provide their own, strong, version. + */ + + .section .text.relocate_vectors,"ax",%progbits + .weak relocate_vectors + +ENTRY(relocate_vectors) + +#ifdef CONFIG_CPU_V7M + /* + * On ARMv7-M we only have to write the new vector address + * to VTOR register. + */ + ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ + ldr r1, =V7M_SCB_BASE + str r0, [r1, V7M_SCB_VTOR] +#else +#ifdef CONFIG_HAS_VBAR + /* + * If the ARM processor has the security extensions, + * use VBAR to relocate the exception vectors. + */ + ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ + mcr p15, 0, r0, c12, c0, 0 /* Set VBAR */ +#else + /* + * Copy the relocated exception vectors to the + * correct address + * CP15 c1 V bit gives us the location of the vectors: + * 0x00000000 or 0xFFFF0000. + */ + ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ + mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */ + ands r2, r2, #(1 << 13) + ldreq r1, =0x00000000 /* If V=0 */ + ldrne r1, =0xFFFF0000 /* If V=1 */ + ldmia r0!, {r2-r8,r10} + stmia r1!, {r2-r8,r10} + ldmia r0!, {r2-r8,r10} + stmia r1!, {r2-r8,r10} +#endif +#endif + bx lr + +ENDPROC(relocate_vectors) + +/* + * void relocate_code(addr_moni) + * + * This function relocates the monitor code. + * + * NOTE: + * To prevent the code below from containing references with an R_ARM_ABS32 + * relocation record type, we never refer to linker-defined symbols directly. + * Instead, we declare literals which contain their relative location with + * respect to relocate_code, and at run time, add relocate_code back to them. + */ + +ENTRY(relocate_code) + ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ + subs r4, r0, r1 /* r4 <- relocation offset */ + beq relocate_done /* skip relocation */ + ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ + +copy_loop: + ldmia r1!, {r10-r11} /* copy from source address [r1] */ + stmia r0!, {r10-r11} /* copy to target address [r0] */ + cmp r1, r2 /* until source end address [r2] */ + blo copy_loop + + /* + * fix .rel.dyn relocations + */ + ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ + ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ +fixloop: + ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ + and r1, r1, #0xff + cmp r1, #R_ARM_RELATIVE + bne fixnext + + /* relative fix: increase location by offset */ + add r0, r0, r4 + ldr r1, [r0] + add r1, r1, r4 + str r1, [r0] +fixnext: + cmp r2, r3 + blo fixloop + +relocate_done: + +#ifdef __XSCALE__ + /* + * On xscale, icache must be invalidated and write buffers drained, + * even with cache disabled - 4.2.7 of xscale core developer's manual + */ + mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */ + mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ +#endif + + /* ARMv4- don't know bx lr but the assembler fails to see that */ + +#ifdef __ARM_ARCH_4__ + mov pc, lr +#else + bx lr +#endif + +ENDPROC(relocate_code) diff --git a/roms/u-boot/arch/arm/lib/relocate_64.S b/roms/u-boot/arch/arm/lib/relocate_64.S new file mode 100644 index 000000000..72e91f270 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/relocate_64.S @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - common relocation function for AArch64 U-Boot + * + * (C) Copyright 2013 + * Albert ARIBAUD <albert.u.boot@aribaud.net> + * David Feng <fenghua@phytium.com.cn> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <elf.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +/* + * void relocate_code(addr_moni) + * + * This function relocates the monitor code. + * x0 holds the destination address. + */ +ENTRY(relocate_code) + stp x29, x30, [sp, #-32]! /* create a stack frame */ + mov x29, sp + str x0, [sp, #16] + /* + * Copy u-boot from flash to RAM + */ + adrp x1, __image_copy_start /* x1 <- address bits [31:12] */ + add x1, x1, :lo12:__image_copy_start/* x1 <- address bits [11:00] */ + subs x9, x0, x1 /* x9 <- Run to copy offset */ + b.eq relocate_done /* skip relocation */ + /* + * Don't ldr x1, __image_copy_start here, since if the code is already + * running at an address other than it was linked to, that instruction + * will load the relocated value of __image_copy_start. To + * correctly apply relocations, we need to know the linked value. + * + * Linked &__image_copy_start, which we know was at + * CONFIG_SYS_TEXT_BASE, which is stored in _TEXT_BASE, as a non- + * relocated value, since it isn't a symbol reference. + */ + ldr x1, _TEXT_BASE /* x1 <- Linked &__image_copy_start */ + subs x9, x0, x1 /* x9 <- Link to copy offset */ + + adrp x1, __image_copy_start /* x1 <- address bits [31:12] */ + add x1, x1, :lo12:__image_copy_start/* x1 <- address bits [11:00] */ + adrp x2, __image_copy_end /* x2 <- address bits [31:12] */ + add x2, x2, :lo12:__image_copy_end /* x2 <- address bits [11:00] */ +copy_loop: + ldp x10, x11, [x1], #16 /* copy from source address [x1] */ + stp x10, x11, [x0], #16 /* copy to target address [x0] */ + cmp x1, x2 /* until source end address [x2] */ + b.lo copy_loop + str x0, [sp, #24] + + /* + * Fix .rela.dyn relocations + */ + adrp x2, __rel_dyn_start /* x2 <- address bits [31:12] */ + add x2, x2, :lo12:__rel_dyn_start /* x2 <- address bits [11:00] */ + adrp x3, __rel_dyn_end /* x3 <- address bits [31:12] */ + add x3, x3, :lo12:__rel_dyn_end /* x3 <- address bits [11:00] */ +fixloop: + ldp x0, x1, [x2], #16 /* (x0,x1) <- (SRC location, fixup) */ + ldr x4, [x2], #8 /* x4 <- addend */ + and x1, x1, #0xffffffff + cmp x1, #R_AARCH64_RELATIVE + bne fixnext + + /* relative fix: store addend plus offset at dest location */ + add x0, x0, x9 + add x4, x4, x9 + str x4, [x0] +fixnext: + cmp x2, x3 + b.lo fixloop + +relocate_done: + switch_el x1, 3f, 2f, 1f + bl hang +3: mrs x0, sctlr_el3 + b 0f +2: mrs x0, sctlr_el2 + b 0f +1: mrs x0, sctlr_el1 +0: tbz w0, #2, 5f /* skip flushing cache if disabled */ + tbz w0, #12, 4f /* skip invalidating i-cache if disabled */ + ic iallu /* i-cache invalidate all */ + isb sy +4: ldp x0, x1, [sp, #16] + bl __asm_flush_dcache_range + bl __asm_flush_l3_dcache +5: ldp x29, x30, [sp],#32 + ret +ENDPROC(relocate_code) diff --git a/roms/u-boot/arch/arm/lib/reset.c b/roms/u-boot/arch/arm/lib/reset.c new file mode 100644 index 000000000..95169bae1 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/reset.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2004 + * DAVE Srl + * http://www.dave-tech.it + * http://www.wawnet.biz + * mailto:info@wawnet.biz + * + * (C) Copyright 2004 Texas Insturments + */ + +#include <common.h> +#include <command.h> +#include <cpu_func.h> +#include <irq_func.h> +#include <linux/delay.h> + +__weak void reset_misc(void) +{ +} + +int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + puts ("resetting ...\n"); + + mdelay(50); /* wait 50 ms */ + + disable_interrupts(); + + reset_misc(); + reset_cpu(); + + /*NOTREACHED*/ + return 0; +} diff --git a/roms/u-boot/arch/arm/lib/sections.c b/roms/u-boot/arch/arm/lib/sections.c new file mode 100644 index 000000000..857879711 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/sections.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ +#include <linux/compiler.h> + +/** + * These two symbols are declared in a C file so that the linker + * uses R_ARM_RELATIVE relocation, rather than the R_ARM_ABS32 one + * it would use if the symbols were defined in the linker file. + * Using only R_ARM_RELATIVE relocation ensures that references to + * the symbols are correct after as well as before relocation. + * + * We need a 0-byte-size type for these symbols, and the compiler + * does not allow defining objects of C type 'void'. Using an empty + * struct is allowed by the compiler, but causes gcc versions 4.4 and + * below to complain about aliasing. Therefore we use the next best + * thing: zero-sized arrays, which are both 0-byte-size and exempt from + * aliasing warnings. + */ + +char __bss_start[0] __section(".__bss_start"); +char __bss_end[0] __section(".__bss_end"); +char __image_copy_start[0] __section(".__image_copy_start"); +char __image_copy_end[0] __section(".__image_copy_end"); +char __rel_dyn_start[0] __section(".__rel_dyn_start"); +char __rel_dyn_end[0] __section(".__rel_dyn_end"); +char __secure_start[0] __section(".__secure_start"); +char __secure_end[0] __section(".__secure_end"); +char __secure_stack_start[0] __section(".__secure_stack_start"); +char __secure_stack_end[0] __section(".__secure_stack_end"); +char __efi_runtime_start[0] __section(".__efi_runtime_start"); +char __efi_runtime_stop[0] __section(".__efi_runtime_stop"); +char __efi_runtime_rel_start[0] __section(".__efi_runtime_rel_start"); +char __efi_runtime_rel_stop[0] __section(".__efi_runtime_rel_stop"); +char _end[0] __section(".__end"); diff --git a/roms/u-boot/arch/arm/lib/semihosting.c b/roms/u-boot/arch/arm/lib/semihosting.c new file mode 100644 index 000000000..904fddd6c --- /dev/null +++ b/roms/u-boot/arch/arm/lib/semihosting.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation + */ + +/* + * Minimal semihosting implementation for reading files into memory. If more + * features like writing files or console output are required they can be + * added later. This code has been tested on arm64/aarch64 fastmodel only. + * An untested placeholder exists for armv7 architectures, but since they + * are commonly available in silicon now, fastmodel usage makes less sense + * for them. + */ +#include <common.h> +#include <command.h> +#include <env.h> +#include <log.h> + +#define SYSOPEN 0x01 +#define SYSCLOSE 0x02 +#define SYSREAD 0x06 +#define SYSFLEN 0x0C + +#define MODE_READ 0x0 +#define MODE_READBIN 0x1 + +/* + * Call the handler + */ +static noinline long smh_trap(unsigned int sysnum, void *addr) +{ + register long result asm("r0"); +#if defined(CONFIG_ARM64) + asm volatile ("hlt #0xf000" : "=r" (result) : "0"(sysnum), "r"(addr)); +#elif defined(CONFIG_CPU_V7M) + asm volatile ("bkpt #0xAB" : "=r" (result) : "0"(sysnum), "r"(addr)); +#else + /* Note - untested placeholder */ + asm volatile ("svc #0x123456" : "=r" (result) : "0"(sysnum), "r"(addr)); +#endif + return result; +} + +/* + * Open a file on the host. Mode is "r" or "rb" currently. Returns a file + * descriptor or -1 on error. + */ +static long smh_open(const char *fname, char *modestr) +{ + long fd; + unsigned long mode; + struct smh_open_s { + const char *fname; + unsigned long mode; + size_t len; + } open; + + debug("%s: file \'%s\', mode \'%s\'\n", __func__, fname, modestr); + + /* Check the file mode */ + if (!(strcmp(modestr, "r"))) { + mode = MODE_READ; + } else if (!(strcmp(modestr, "rb"))) { + mode = MODE_READBIN; + } else { + printf("%s: ERROR mode \'%s\' not supported\n", __func__, + modestr); + return -1; + } + + open.fname = fname; + open.len = strlen(fname); + open.mode = mode; + + /* Open the file on the host */ + fd = smh_trap(SYSOPEN, &open); + if (fd == -1) + printf("%s: ERROR fd %ld for file \'%s\'\n", __func__, fd, + fname); + + return fd; +} + +/* + * Read 'len' bytes of file into 'memp'. Returns 0 on success, else failure + */ +static long smh_read(long fd, void *memp, size_t len) +{ + long ret; + struct smh_read_s { + long fd; + void *memp; + size_t len; + } read; + + debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len); + + read.fd = fd; + read.memp = memp; + read.len = len; + + ret = smh_trap(SYSREAD, &read); + if (ret < 0) { + /* + * The ARM handler allows for returning partial lengths, + * but in practice this never happens so rather than create + * hard to maintain partial read loops and such, just fail + * with an error message. + */ + printf("%s: ERROR ret %ld, fd %ld, len %zu memp %p\n", + __func__, ret, fd, len, memp); + return -1; + } + + return 0; +} + +/* + * Close the file using the file descriptor + */ +static long smh_close(long fd) +{ + long ret; + + debug("%s: fd %ld\n", __func__, fd); + + ret = smh_trap(SYSCLOSE, &fd); + if (ret == -1) + printf("%s: ERROR fd %ld\n", __func__, fd); + + return ret; +} + +/* + * Get the file length from the file descriptor + */ +static long smh_len_fd(long fd) +{ + long ret; + + debug("%s: fd %ld\n", __func__, fd); + + ret = smh_trap(SYSFLEN, &fd); + if (ret == -1) + printf("%s: ERROR ret %ld, fd %ld\n", __func__, ret, fd); + + return ret; +} + +static int smh_load_file(const char * const name, ulong load_addr, + ulong *end_addr) +{ + long fd; + long len; + long ret; + + fd = smh_open(name, "rb"); + if (fd == -1) + return -1; + + len = smh_len_fd(fd); + if (len < 0) { + smh_close(fd); + return -1; + } + + ret = smh_read(fd, (void *)load_addr, len); + smh_close(fd); + + if (ret == 0) { + *end_addr = load_addr + len - 1; + printf("loaded file %s from %08lX to %08lX, %08lX bytes\n", + name, + load_addr, + *end_addr, + len); + } else { + printf("read failed\n"); + return 0; + } + + return 0; +} + +static int do_smhload(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (argc == 3 || argc == 4) { + ulong load_addr; + ulong end_addr = 0; + int ret; + char end_str[64]; + + load_addr = simple_strtoul(argv[2], NULL, 16); + if (!load_addr) + return -1; + + ret = smh_load_file(argv[1], load_addr, &end_addr); + if (ret < 0) + return CMD_RET_FAILURE; + + /* Optionally save returned end to the environment */ + if (argc == 4) { + sprintf(end_str, "0x%08lx", end_addr); + env_set(argv[3], end_str); + } + } else { + return CMD_RET_USAGE; + } + return 0; +} + +U_BOOT_CMD(smhload, 4, 0, do_smhload, "load a file using semihosting", + "<file> 0x<address> [end var]\n" + " - load a semihosted file to the address specified\n" + " if the optional [end var] is specified, the end\n" + " address of the file will be stored in this environment\n" + " variable.\n"); diff --git a/roms/u-boot/arch/arm/lib/setjmp.S b/roms/u-boot/arch/arm/lib/setjmp.S new file mode 100644 index 000000000..176a1d531 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/setjmp.S @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + */ + +#include <config.h> +#include <asm/assembler.h> +#include <linux/linkage.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + /* + * A subroutine must preserve the contents of the registers + * r4-r8, r10, r11 (v1-v5, v7 and v8) and SP (and r9 in PCS + * variants that designate r9 as v6). + */ + mov ip, sp + stm a1, {v1-v8, ip, lr} + mov a1, #0 + bx lr +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ldm a1, {v1-v8, ip, lr} + mov sp, ip + mov a1, a2 + /* If we were passed a return value of zero, return one instead */ + cmp a1, #0 + bne 1f + mov a1, #1 +1: + bx lr +ENDPROC(longjmp) +.popsection diff --git a/roms/u-boot/arch/arm/lib/setjmp_aarch64.S b/roms/u-boot/arch/arm/lib/setjmp_aarch64.S new file mode 100644 index 000000000..1b8d000eb --- /dev/null +++ b/roms/u-boot/arch/arm/lib/setjmp_aarch64.S @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + */ + +#include <config.h> +#include <asm/macro.h> +#include <linux/linkage.h> + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + /* Preserve all callee-saved registers and the SP */ + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0, #96] + mov x0, #0 + ret +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#96] + mov sp, x2 + /* Move the return value in place, but return 1 if passed 0. */ + adds x0, xzr, x1 + csinc x0, x0, xzr, ne + ret +ENDPROC(longjmp) +.popsection diff --git a/roms/u-boot/arch/arm/lib/spl.c b/roms/u-boot/arch/arm/lib/spl.c new file mode 100644 index 000000000..8e2bdf353 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/spl.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010-2012 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * Tom Rini <trini@ti.com> + */ + +#include <common.h> +#include <config.h> +#include <init.h> +#include <log.h> +#include <spl.h> +#include <image.h> +#include <asm/cache.h> +#include <asm/global_data.h> +#include <linux/compiler.h> +#include <asm/mach-types.h> + +#ifndef CONFIG_SPL_DM +/* Pointer to as well as the global data structure for SPL */ +DECLARE_GLOBAL_DATA_PTR; + +/* + * WARNING: This is going away very soon. Don't use it and don't submit + * pafches that rely on it. The global_data area is set up in crt0.S. + */ +gd_t gdata __section(".data"); +#endif + +/* + * In the context of SPL, board_init_f() prepares the hardware for execution + * from system RAM (DRAM, DDR...). As system RAM may not be available yet, + * board_init_f() must use the current GD to store any data which must be + * passed on to later stages. These data include the relocation destination, + * the future stack, and the future GD location. BSS is cleared after this + * function (and therefore must be accessible). + * + * We provide this version by default but mark it as __weak to allow for + * platforms to do this in their own way if needed. Please see the top + * level U-Boot README "Board Initialization Flow" section for info on what + * to put in this function. + */ +void __weak board_init_f(ulong dummy) +{ +} + +/* + * This function jumps to an image with argument. Normally an FDT or ATAGS + * image. + */ +#ifdef CONFIG_SPL_OS_BOOT +#ifdef CONFIG_ARM64 +void __noreturn jump_to_image_linux(struct spl_image_info *spl_image) +{ + debug("Entering kernel arg pointer: 0x%p\n", spl_image->arg); + cleanup_before_linux(); + armv8_switch_to_el2((u64)spl_image->arg, 0, 0, 0, + spl_image->entry_point, ES_TO_AARCH64); +} +#else +void __noreturn jump_to_image_linux(struct spl_image_info *spl_image) +{ + unsigned long machid = 0xffffffff; +#ifdef CONFIG_MACH_TYPE + machid = CONFIG_MACH_TYPE; +#endif + + debug("Entering kernel arg pointer: 0x%p\n", spl_image->arg); + typedef void (*image_entry_arg_t)(int, int, void *) + __attribute__ ((noreturn)); + image_entry_arg_t image_entry = + (image_entry_arg_t)(uintptr_t) spl_image->entry_point; + cleanup_before_linux(); + image_entry(0, machid, spl_image->arg); +} +#endif /* CONFIG_ARM64 */ +#endif diff --git a/roms/u-boot/arch/arm/lib/stack.c b/roms/u-boot/arch/arm/lib/stack.c new file mode 100644 index 000000000..b03e1cfc8 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/stack.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2015 Andreas Bießmann <andreas@biessmann.org> + * + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2002-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + */ +#include <common.h> +#include <init.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +int arch_reserve_stacks(void) +{ +#ifdef CONFIG_SPL_BUILD + gd->start_addr_sp -= 128; /* leave 32 words for abort-stack */ + gd->irq_sp = gd->start_addr_sp; +#else + /* setup stack pointer for exceptions */ + gd->irq_sp = gd->start_addr_sp; + +# if !defined(CONFIG_ARM64) + /* leave 3 words for abort-stack, plus 1 for alignment */ + gd->start_addr_sp -= 16; +# endif +#endif + + return 0; +} diff --git a/roms/u-boot/arch/arm/lib/uldivmod.S b/roms/u-boot/arch/arm/lib/uldivmod.S new file mode 100644 index 000000000..5e9e136cc --- /dev/null +++ b/roms/u-boot/arch/arm/lib/uldivmod.S @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2010, Google Inc. + * + * Brought in from coreboot uldivmod.S + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +/* + * A, Q = r0 + (r1 << 32) + * B, R = r2 + (r3 << 32) + * A / B = Q ... R + */ + +A_0 .req r0 +A_1 .req r1 +B_0 .req r2 +B_1 .req r3 +C_0 .req r4 +C_1 .req r5 +D_0 .req r6 +D_1 .req r7 + +Q_0 .req r0 +Q_1 .req r1 +R_0 .req r2 +R_1 .req r3 + +THUMB( +TMP .req r8 +) + +.pushsection .text.__aeabi_uldivmod, "ax" +ENTRY(__aeabi_uldivmod) + + stmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) lr} + @ Test if B == 0 + orrs ip, B_0, B_1 @ Z set -> B == 0 + beq L_div_by_0 + @ Test if B is power of 2: (B & (B - 1)) == 0 + subs C_0, B_0, #1 + sbc C_1, B_1, #0 + tst C_0, B_0 + tsteq B_1, C_1 + beq L_pow2 + @ Test if A_1 == B_1 == 0 + orrs ip, A_1, B_1 + beq L_div_32_32 + +L_div_64_64: +/* CLZ only exists in ARM architecture version 5 and above. */ +#ifdef HAVE_CLZ + mov C_0, #1 + mov C_1, #0 + @ D_0 = clz A + teq A_1, #0 + clz D_0, A_1 + clzeq ip, A_0 + addeq D_0, D_0, ip + @ D_1 = clz B + teq B_1, #0 + clz D_1, B_1 + clzeq ip, B_0 + addeq D_1, D_1, ip + @ if clz B - clz A > 0 + subs D_0, D_1, D_0 + bls L_done_shift + @ B <<= (clz B - clz A) + subs D_1, D_0, #32 + rsb ip, D_0, #32 + movmi B_1, B_1, lsl D_0 +ARM( orrmi B_1, B_1, B_0, lsr ip ) +THUMB( lsrmi TMP, B_0, ip ) +THUMB( orrmi B_1, B_1, TMP ) + movpl B_1, B_0, lsl D_1 + mov B_0, B_0, lsl D_0 + @ C = 1 << (clz B - clz A) + movmi C_1, C_1, lsl D_0 +ARM( orrmi C_1, C_1, C_0, lsr ip ) +THUMB( lsrmi TMP, C_0, ip ) +THUMB( orrmi C_1, C_1, TMP ) + movpl C_1, C_0, lsl D_1 + mov C_0, C_0, lsl D_0 +L_done_shift: + mov D_0, #0 + mov D_1, #0 + @ C: current bit; D: result +#else + @ C: current bit; D: result + mov C_0, #1 + mov C_1, #0 + mov D_0, #0 + mov D_1, #0 +L_lsl_4: + cmp B_1, #0x10000000 + cmpcc B_1, A_1 + cmpeq B_0, A_0 + bcs L_lsl_1 + @ B <<= 4 + mov B_1, B_1, lsl #4 + orr B_1, B_1, B_0, lsr #28 + mov B_0, B_0, lsl #4 + @ C <<= 4 + mov C_1, C_1, lsl #4 + orr C_1, C_1, C_0, lsr #28 + mov C_0, C_0, lsl #4 + b L_lsl_4 +L_lsl_1: + cmp B_1, #0x80000000 + cmpcc B_1, A_1 + cmpeq B_0, A_0 + bcs L_subtract + @ B <<= 1 + mov B_1, B_1, lsl #1 + orr B_1, B_1, B_0, lsr #31 + mov B_0, B_0, lsl #1 + @ C <<= 1 + mov C_1, C_1, lsl #1 + orr C_1, C_1, C_0, lsr #31 + mov C_0, C_0, lsl #1 + b L_lsl_1 +#endif +L_subtract: + @ if A >= B + cmp A_1, B_1 + cmpeq A_0, B_0 + bcc L_update + @ A -= B + subs A_0, A_0, B_0 + sbc A_1, A_1, B_1 + @ D |= C + orr D_0, D_0, C_0 + orr D_1, D_1, C_1 +L_update: + @ if A == 0: break + orrs ip, A_1, A_0 + beq L_exit + @ C >>= 1 + movs C_1, C_1, lsr #1 + movs C_0, C_0, rrx + @ if C == 0: break + orrs ip, C_1, C_0 + beq L_exit + @ B >>= 1 + movs B_1, B_1, lsr #1 + mov B_0, B_0, rrx + b L_subtract +L_exit: + @ Note: A, B & Q, R are aliases + mov R_0, A_0 + mov R_1, A_1 + mov Q_0, D_0 + mov Q_1, D_1 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} + +L_div_32_32: + @ Note: A_0 & r0 are aliases + @ Q_1 r1 + mov r1, B_0 + bl __aeabi_uidivmod + mov R_0, r1 + mov R_1, #0 + mov Q_1, #0 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} + +L_pow2: +#ifdef HAVE_CLZ + @ Note: A, B and Q, R are aliases + @ R = A & (B - 1) + and C_0, A_0, C_0 + and C_1, A_1, C_1 + @ Q = A >> log2(B) + @ Note: B must not be 0 here! + clz D_0, B_0 + add D_1, D_0, #1 + rsbs D_0, D_0, #31 + bpl L_1 + clz D_0, B_1 + rsb D_0, D_0, #31 + mov A_0, A_1, lsr D_0 + add D_0, D_0, #32 +L_1: + movpl A_0, A_0, lsr D_0 +ARM( orrpl A_0, A_0, A_1, lsl D_1 ) +THUMB( lslpl TMP, A_1, D_1 ) +THUMB( orrpl A_0, A_0, TMP ) + mov A_1, A_1, lsr D_0 + @ Mov back C to R + mov R_0, C_0 + mov R_1, C_1 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} +#else + @ Note: A, B and Q, R are aliases + @ R = A & (B - 1) + and C_0, A_0, C_0 + and C_1, A_1, C_1 + @ Q = A >> log2(B) + @ Note: B must not be 0 here! + @ Count the leading zeroes in B. + mov D_0, #0 + orrs B_0, B_0, B_0 + @ If B is greater than 1 << 31, divide A and B by 1 << 32. + moveq A_0, A_1 + moveq A_1, #0 + moveq B_0, B_1 + @ Count the remaining leading zeroes in B. + movs B_1, B_0, lsl #16 + addeq D_0, #16 + moveq B_0, B_0, lsr #16 + tst B_0, #0xff + addeq D_0, #8 + moveq B_0, B_0, lsr #8 + tst B_0, #0xf + addeq D_0, #4 + moveq B_0, B_0, lsr #4 + tst B_0, #0x3 + addeq D_0, #2 + moveq B_0, B_0, lsr #2 + tst B_0, #0x1 + addeq D_0, #1 + @ Shift A to the right by the appropriate amount. + rsb D_1, D_0, #32 + mov Q_0, A_0, lsr D_0 + ARM( orr Q_0, Q_0, A_1, lsl D_1 ) + THUMB( lsl A_1, D_1 ) + THUMB( orr Q_0, A_1 ) + mov Q_1, A_1, lsr D_0 + @ Move C to R + mov R_0, C_0 + mov R_1, C_1 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} +#endif + +L_div_by_0: + bl __div0 + @ As wrong as it could be + mov Q_0, #0 + mov Q_1, #0 + mov R_0, #0 + mov R_1, #0 + ldmfd sp!, {r4, r5, r6, r7, THUMB(TMP,) pc} +ENDPROC(__aeabi_uldivmod) +.popsection diff --git a/roms/u-boot/arch/arm/lib/vectors.S b/roms/u-boot/arch/arm/lib/vectors.S new file mode 100644 index 000000000..56f368155 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/vectors.S @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * vectors - Generic ARM exception table code + * + * Copyright (c) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (c) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (c) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net> + */ + +#include <config.h> + +/* + * A macro to allow insertion of an ARM exception vector either + * for the non-boot0 case or by a boot0-header. + */ + .macro ARM_VECTORS +#ifdef CONFIG_ARCH_K3 + ldr pc, _reset +#else + b reset +#endif + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + .endm + + +/* + ************************************************************************* + * + * Symbol _start is referenced elsewhere, so make it global + * + ************************************************************************* + */ + +.globl _start + +/* + ************************************************************************* + * + * Vectors have their own section so linker script can map them easily + * + ************************************************************************* + */ + + .section ".vectors", "ax" + +#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) +/* + * Various SoCs need something special and SoC-specific up front in + * order to boot, allow them to set that in their boot0.h file and then + * use it here. + * + * To allow a boot0 hook to insert a 'special' sequence after the vector + * table (e.g. for the socfpga), the presence of a boot0 hook supresses + * the below vector table and assumes that the vector table is filled in + * by the boot0 hook. The requirements for a boot0 hook thus are: + * (1) defines '_start:' as appropriate + * (2) inserts the vector table using ARM_VECTORS as appropriate + */ +#include <asm/arch/boot0.h> +#else + +/* + ************************************************************************* + * + * Exception vectors as described in ARM reference manuals + * + * Uses indirect branch to allow reaching handlers anywhere in memory. + * + ************************************************************************* + */ + +_start: +#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG + .word CONFIG_SYS_DV_NOR_BOOT_CFG +#endif + ARM_VECTORS +#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */ + +/* + ************************************************************************* + * + * Indirect vectors table + * + * Symbols referenced here must be defined somewhere else + * + ************************************************************************* + */ + + .globl _reset + .globl _undefined_instruction + .globl _software_interrupt + .globl _prefetch_abort + .globl _data_abort + .globl _not_used + .globl _irq + .globl _fiq + +#ifdef CONFIG_ARCH_K3 +_reset: .word reset +#endif +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +/* SPL interrupt handling: just hang */ + +#ifdef CONFIG_SPL_BUILD + + .align 5 +undefined_instruction: +software_interrupt: +prefetch_abort: +data_abort: +not_used: +irq: +fiq: +1: + b 1b /* hang and never return */ + +#else /* !CONFIG_SPL_BUILD */ + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: +#ifdef IRAM_BASE_ADDR + .word IRAM_BASE_ADDR + 0x20 +#else + .word 0x0badc0de +#endif + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + @ carve out a frame on current user stack + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + ldr r2, IRQ_STACK_START_IN + @ get values for "aborted" pc and cpsr (into parm regs) + ldmia r2, {r2 - r3} + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif /* CONFIG_SPL_BUILD */ diff --git a/roms/u-boot/arch/arm/lib/vectors_m.S b/roms/u-boot/arch/arm/lib/vectors_m.S new file mode 100644 index 000000000..7d2d55c7f --- /dev/null +++ b/roms/u-boot/arch/arm/lib/vectors_m.S @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + */ + +#include <config.h> +#include <asm/assembler.h> +#include <linux/linkage.h> + +.type __hard_fault_entry, %function +__hard_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_hard_fault + +.type __mm_fault_entry, %function +__mm_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_mm_fault + +.type __bus_fault_entry, %function +__bus_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_bus_fault + +.type __usage_fault_entry, %function +__usage_fault_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_usage_fault + +.type __invalid_entry, %function +__invalid_entry: + mov r0, sp @ pass auto-saved registers as argument + b do_invalid_entry + + .section .vectors +ENTRY(_start) + .long CONFIG_SYS_INIT_SP_ADDR @ 0 - Reset stack pointer + .long reset @ 1 - Reset + .long __invalid_entry @ 2 - NMI + .long __hard_fault_entry @ 3 - HardFault + .long __mm_fault_entry @ 4 - MemManage + .long __bus_fault_entry @ 5 - BusFault + .long __usage_fault_entry @ 6 - UsageFault + .long __invalid_entry @ 7 - Reserved + .long __invalid_entry @ 8 - Reserved + .long __invalid_entry @ 9 - Reserved + .long __invalid_entry @ 10 - Reserved + .long __invalid_entry @ 11 - SVCall + .long __invalid_entry @ 12 - Debug Monitor + .long __invalid_entry @ 13 - Reserved + .long __invalid_entry @ 14 - PendSV + .long __invalid_entry @ 15 - SysTick + .rept 255 - 16 + .long __invalid_entry @ 16..255 - External Interrupts + .endr diff --git a/roms/u-boot/arch/arm/lib/zimage.c b/roms/u-boot/arch/arm/lib/zimage.c new file mode 100644 index 000000000..45e9c4506 --- /dev/null +++ b/roms/u-boot/arch/arm/lib/zimage.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 + * Ladislav Michl <ladis@linux-mips.org> + * + * bootz code: + * Copyright (C) 2012 Marek Vasut <marek.vasut@gmail.com> + */ +#include <common.h> +#include <image.h> + +#define LINUX_ARM_ZIMAGE_MAGIC 0x016f2818 +#define BAREBOX_IMAGE_MAGIC 0x00786f62 + +struct arm_z_header { + uint32_t code[9]; + uint32_t zi_magic; + uint32_t zi_start; + uint32_t zi_end; +} __attribute__ ((__packed__)); + +int bootz_setup(ulong image, ulong *start, ulong *end) +{ + struct arm_z_header *zi = (struct arm_z_header *)image; + + if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC && + zi->zi_magic != BAREBOX_IMAGE_MAGIC) { + if (!IS_ENABLED(CONFIG_SPL_BUILD)) + puts("zimage: Bad magic!\n"); + return 1; + } + + *start = zi->zi_start; + *end = zi->zi_end; + if (!IS_ENABLED(CONFIG_SPL_BUILD)) + printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n", + image, *start, *end); + + return 0; +} |