[U-Boot,2/8] spl: atf: add arm32 variant
diff mbox series

Message ID 20190405083013.5473-3-heiko@sntech.de
State Changes Requested
Delegated to: Kever Yang
Headers show
Series
  • arm-trusted-firmware support for rk3288
Related show

Commit Message

Heiko Stuebner April 5, 2019, 8:30 a.m. UTC
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 <heiko@sntech.de>
---
 common/spl/Kconfig   |  2 +-
 common/spl/spl_atf.c | 86 ++++++++++++++++++++++++++++++++++++++++++--
 include/atf_common.h | 52 +++++++++++++++++++++++++++
 3 files changed, 137 insertions(+), 3 deletions(-)

Patch
diff mbox series

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;