ATF can also support arm32 socs with being a bl32 payload either including optee or the minimal sp_min payload included in ATF itself.
So add the necessary infrasturcture to jump into ATF as bl32 from spl which then will jump into the real u-boot. We keep using the arm64 datastructures because, while they are named bl31_*, the only difference is not populating the bl31-related fields and making the bl32 ones mandatory, so there really is no need to redefine all of them simply to drop the empty bl31 parts. Signed-off-by: Heiko Stuebner <[email protected]> --- common/spl/Kconfig | 2 +- common/spl/spl_atf.c | 86 ++++++++++++++++++++++++++++++++++++++++++-- include/atf_common.h | 52 +++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 206c24076d..ba39c17cf2 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -886,7 +886,7 @@ config SPL_YMODEM_SUPPORT config SPL_ATF bool "Support ARM Trusted Firmware" - depends on ARM64 + depends on ARM || ARM64 help ATF(ARM Trusted Firmware) is a component for ARM AArch64 which is loaded by SPL (which is considered as BL2 in ATF terminology). diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c index cddab6a735..2fbec29b73 100644 --- a/common/spl/spl_atf.c +++ b/common/spl/spl_atf.c @@ -17,6 +17,9 @@ static struct bl2_to_bl31_params_mem bl31_params_mem; static struct bl31_params *bl2_to_bl31_params; +typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params); + +#ifdef CONFIG_ARM64 /** * bl2_plat_get_bl31_params() - prepare params for bl31. * @@ -83,8 +86,6 @@ static inline void raw_write_daif(unsigned int daif) __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); } -typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params); - static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl33_entry, uintptr_t fdt_addr) { @@ -98,6 +99,83 @@ static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl33_entry, atf_entry((void *)bl31_params, (void *)fdt_addr); } +#else /* CONFIG_ARM64 */ +static struct bl31_params *bl2_plat_get_bl32_params(uintptr_t bl33_entry) +{ + struct entry_point_info *bl33_ep_info; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL31 + */ + memset(&bl31_params_mem, 0, sizeof(struct bl2_to_bl31_params_mem)); + + /* Assign memory for TF related information */ + bl2_to_bl31_params = &bl31_params_mem.bl31_params; + SET_PARAM_HEAD(bl2_to_bl31_params, ATF_PARAM_BL31, ATF_VERSION_1, 0); + + /* Fill BL31 related information */ + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, + ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); + + /* Fill BL32 related information */ + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, ATF_PARAM_EP, + ATF_VERSION_1, 0); + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, + ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); + + /* Fill BL33 related information */ + bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; + bl33_ep_info = &bl31_params_mem.bl33_ep_info; + SET_PARAM_HEAD(bl33_ep_info, ATF_PARAM_EP, ATF_VERSION_1, + ATF_EP_NON_SECURE); + + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); + bl33_ep_info->pc = bl33_entry; + bl33_ep_info->spsr = SPSR_MODE32(MODE32_hyp, + SPSR_T_ARM, +#ifdef __ARMEB__ + SPSR_E_BIG, +#else + SPSR_E_LITTLE, +#endif + DISABLE_ALL_EXECPTIONS); + + bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, + ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); + + return bl2_to_bl31_params; +} + +static inline void raw_write_aif(unsigned int aif) +{ + unsigned int val; + + val = get_cpsr(); + val &= ~SPSR_EXCEPTION_MASK; + val |= aif; + + __asm__ __volatile__("msr cpsr_c, %0\n\t" : : "r" (val) ); +} + +static void bl32_entry(uintptr_t bl32_entry, uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + struct bl31_params *bl31_params; + atf_entry_t atf_entry = (atf_entry_t)bl32_entry; + + bl31_params = bl2_plat_get_bl32_params(bl33_entry); + + raw_write_aif(SPSR_EXCEPTION_MASK); + dcache_disable(); + + atf_entry((void *)bl31_params, (void *)fdt_addr); +} +#endif /* CONFIG_ARM64 */ static int spl_fit_images_find_uboot(void *blob) { @@ -171,5 +249,9 @@ void spl_invoke_atf(struct spl_image_info *spl_image) * We don't provide a BL3-2 entry yet, but this will be possible * using similar logic. */ +#ifdef CONFIG_ARM64 bl31_entry(spl_image->entry_point, bl33_entry, platform_param); +#else + bl32_entry(spl_image->entry_point, bl33_entry, platform_param); +#endif } diff --git a/include/atf_common.h b/include/atf_common.h index 3a7d40e5f0..9fdb190375 100644 --- a/include/atf_common.h +++ b/include/atf_common.h @@ -32,6 +32,8 @@ #define MODE_RW_64 0x0 #define MODE_RW_32 0x1 +#ifdef CONFIG_ARM64 + #define MODE_EL_SHIFT 0x2 #define MODE_EL_MASK 0x3 #define MODE_EL3 0x3 @@ -66,6 +68,53 @@ #define DISABLE_ALL_EXECPTIONS \ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) +#else /* CONFIG_ARM64 */ + +#define SPSR_E_SHIFT 9 +#define SPSR_E_MASK 0x1 +#define SPSR_E_LITTLE 0 +#define SPSR_E_BIG 1 + +#define SPSR_T_SHIFT 5 +#define SPSR_T_MASK 0x1 +#define SPSR_T_ARM 0 +#define SPSR_T_THUMB 1 + +#define MODE32_SHIFT 0 +#define MODE32_MASK 0xf +#define MODE32_usr 0x0 +#define MODE32_fiq 0x1 +#define MODE32_irq 0x2 +#define MODE32_svc 0x3 +#define MODE32_mon 0x6 +#define MODE32_abt 0x7 +#define MODE32_hyp 0xa +#define MODE32_und 0xb +#define MODE32_sys 0xf + +#define SPSR_AIF_SHIFT 6 +#define SPSR_AIF_MASK 0x07 + +#define SPSR_MODE32(mode, isa, endian, aif) \ + (MODE_RW_32 << MODE_RW_SHIFT | \ + ((mode) & MODE32_MASK) << MODE32_SHIFT | \ + ((isa) & SPSR_T_MASK) << SPSR_T_SHIFT | \ + ((endian) & SPSR_E_MASK) << SPSR_E_SHIFT | \ + ((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT) + +#define SPSR_FIQ (1 << 6) +#define SPSR_IRQ (1 << 7) +#define SPSR_SERROR (1 << 8) +#define SPSR_EXCEPTION_MASK (SPSR_FIQ | SPSR_IRQ | SPSR_SERROR) + +#define AIF_FIQ_BIT (1 << 0) +#define AIF_IRQ_BIT (1 << 1) +#define AIF_ABT_BIT (1 << 2) +#define DISABLE_ALL_EXECPTIONS \ + (AIF_FIQ_BIT | AIF_IRQ_BIT | AIF_ABT_BIT) + +#endif /* CONFIG_ARM64 */ + #ifndef __ASSEMBLY__ /******************************************************************************* @@ -152,6 +201,9 @@ struct image_desc { * BL31 image information is mandatory if this structure is used. If either of * the optional BL32 and BL33 image information is not provided, this is * indicated by the respective image_info pointers being zero. + * + * In ARM32 mode BL31 image information is to be left empty and BL32 + * information becomes mandatory. ******************************************************************************/ struct bl31_params { struct param_header h; -- 2.20.1 _______________________________________________ U-Boot mailing list [email protected] https://lists.denx.de/listinfo/u-boot

