Browse Source

Merge git://git.denx.de/u-boot-rockchip

Tom Rini 7 năm trước cách đây
mục cha
commit
0931b6f20e

+ 6 - 1
arch/arm/include/asm/arch-rockchip/grf_rk3399.h

@@ -589,7 +589,12 @@ enum {
 	PMUGRF_GPIO1C3_SEL_SHIFT        = 6,
 	PMUGRF_GPIO1C3_SEL_MASK = 3 << PMUGRF_GPIO1C3_SEL_SHIFT,
 	PMUGRF_PWM_2            = 1,
-
+	PMUGRF_GPIO1C4_SEL_SHIFT = 8,
+	PMUGRF_GPIO1C4_SEL_MASK = 3 << PMUGRF_GPIO1C4_SEL_SHIFT,
+	PMUGRF_I2C8PMU_SDA = 1,
+	PMUGRF_GPIO1C5_SEL_SHIFT = 10,
+	PMUGRF_GPIO1C5_SEL_MASK = 3 << PMUGRF_GPIO1C5_SEL_SHIFT,
+	PMUGRF_I2C8PMU_SCL = 1,
 };
 
 /* GRF_SOC_CON5 */

+ 3 - 0
arch/arm/include/asm/arch-rockchip/periph.h

@@ -24,6 +24,9 @@ enum periph_id {
 	PERIPH_ID_I2C3,
 	PERIPH_ID_I2C4,
 	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
+	PERIPH_ID_I2C8,
 	PERIPH_ID_SPI0,
 	PERIPH_ID_SPI1,
 	PERIPH_ID_SPI2,

+ 4 - 2
arch/arm/mach-rockchip/Makefile

@@ -23,9 +23,11 @@ obj-spl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o spl-boot-order.o
 
 ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
 
-ifneq ($(CONFIG_ROCKCHIP_BOOT_MODE_REG),0)
+# Always include boot_mode.o, as we bypass it (i.e. turn it off)
+# inside of boot_mode.c when CONFIG_BOOT_MODE_REG is 0.  This way,
+# we can have the preprocessor correctly recognise both 0x0 and 0
+# meaning "turn it off".
 obj-y += boot_mode.o
-endif
 
 obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o
 obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o

+ 11 - 0
arch/arm/mach-rockchip/boot_mode.c

@@ -9,6 +9,15 @@
 #include <asm/io.h>
 #include <asm/arch/boot_mode.h>
 
+#if (CONFIG_ROCKCHIP_BOOT_MODE_REG == 0)
+
+int setup_boot_mode(void)
+{
+	return 0;
+}
+
+#else
+
 void set_back_to_bootrom_dnl_flag(void)
 {
 	writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
@@ -74,3 +83,5 @@ int setup_boot_mode(void)
 
 	return 0;
 }
+
+#endif

+ 4 - 2
board/theobroma-systems/lion_rk3368/fit_spl_atf.its

@@ -17,6 +17,7 @@
 			description = "U-Boot (64-bit)";
 			data = /incbin/("../../../u-boot-nodtb.bin");
 			type = "standalone";
+			os = "U-Boot";
 			arch = "arm64";
 			compression = "none";
 			load = <0x00200000>;
@@ -25,6 +26,7 @@
 			description = "ARM Trusted Firmware";
 			data = /incbin/("../../../bl31-rk3368.bin");
 			type = "firmware";
+			os = "arm-trusted-firmware";
 			arch = "arm64";
 			compression = "none";
 			load = <0x00100000>;
@@ -43,8 +45,8 @@
 		default = "conf";
 		conf {
 			description = "Theobroma Systems RK3368-uQ7 (Puma) SoM";
-			firmware = "uboot";
-			loadables = "atf";
+			firmware = "atf";
+			loadables = "uboot";
 			fdt = "fdt";
 		};
 	};

+ 7 - 5
board/theobroma-systems/puma_rk3399/fit_spl_atf.its

@@ -17,6 +17,7 @@
 			description = "U-Boot (64-bit)";
 			data = /incbin/("../../../u-boot-nodtb.bin");
 			type = "standalone";
+			os = "U-Boot";
 			arch = "arm64";
 			compression = "none";
 			load = <0x00200000>;
@@ -26,16 +27,17 @@
 			data = /incbin/("../../../bl31-rk3399.bin");
 			type = "firmware";
 			arch = "arm64";
+			os = "arm-trusted-firmware";
 			compression = "none";
-			load = <0x00001000>;
-			entry = <0x00001000>;
+			load = <0x1000>;
+			entry = <0x1000>;
 		};
 		pmu {
 		        description = "Cortex-M0 firmware";
 			data = /incbin/("../../../rk3399m0.bin");
 			type = "pmu-firmware";
 			compression = "none";
-			load = <0xff8c0000>;
+			load = <0x180000>;
                 };
 		fdt {
 			description = "RK3399-Q7 (Puma) flat device-tree";
@@ -49,8 +51,8 @@
 		default = "conf";
 		conf {
 			description = "Theobroma Systems RK3399-Q7 (Puma) SoM";
-			firmware = "uboot";
-			loadables = "atf";
+			firmware = "atf";
+			loadables = "uboot", "pmu";
 			fdt = "fdt";
 		};
 	};

+ 39 - 0
common/fdt_support.c

@@ -410,6 +410,45 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
 	return p - (char *)buf;
 }
 
+int fdt_record_loadable(void *blob, u32 index, const char *name,
+			uintptr_t load_addr, u32 size, uintptr_t entry_point,
+			const char *type, const char *os)
+{
+	int err, node;
+
+	err = fdt_check_header(blob);
+	if (err < 0) {
+		printf("%s: %s\n", __func__, fdt_strerror(err));
+		return err;
+	}
+
+	/* find or create "/fit-images" node */
+	node = fdt_find_or_add_subnode(blob, 0, "fit-images");
+	if (node < 0)
+			return node;
+
+	/* find or create "/fit-images/<name>" node */
+	node = fdt_find_or_add_subnode(blob, node, name);
+	if (node < 0)
+		return node;
+
+	/*
+	 * We record these as 32bit entities, possibly truncating addresses.
+	 * However, spl_fit.c is not 64bit safe either: i.e. we should not
+	 * have an issue here.
+	 */
+	fdt_setprop_u32(blob, node, "load-addr", load_addr);
+	if (entry_point != -1)
+		fdt_setprop_u32(blob, node, "entry-point", entry_point);
+	fdt_setprop_u32(blob, node, "size", size);
+	if (type)
+		fdt_setprop_string(blob, node, "type", type);
+	if (os)
+		fdt_setprop_string(blob, node, "os", os);
+
+	return node;
+}
+
 #ifdef CONFIG_NR_DRAM_BANKS
 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
 #else

+ 1 - 0
common/image.c

@@ -95,6 +95,7 @@ static const table_entry_t uimage_arch[] = {
 
 static const table_entry_t uimage_os[] = {
 	{	IH_OS_INVALID,	"invalid",	"Invalid OS",		},
+	{       IH_OS_ARM_TRUSTED_FIRMWARE, "arm-trusted-firmware", "ARM Trusted Firmware"  },
 	{	IH_OS_LINUX,	"linux",	"Linux",		},
 #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
 	{	IH_OS_LYNXOS,	"lynxos",	"LynxOS",		},

+ 17 - 7
common/spl/Kconfig

@@ -228,6 +228,22 @@ config SPL_SHA256_SUPPORT
 	  SHA256 variant is supported: SHA512 and others are not currently
 	  supported in U-Boot.
 
+config SPL_FIT_IMAGE_TINY
+	bool "Remove functionality from SPL FIT loading to reduce size"
+	depends on SPL_FIT
+	default y if MACH_SUN50I || MACH_SUN50I_H5
+	default y if ARCH_OMAP2PLUS
+	help
+	  Enable this to reduce the size of the FIT image loading code
+	  in SPL, if space for the SPL binary is very tight.
+
+	  This removes the detection of image types (which forces the
+	  first image to be treated as having a U-Boot style calling
+	  convention) and skips the recording of each loaded payload
+	  (i.e. loadable) into the FDT (modifying the loaded FDT to
+	  ensure this information is available to the next image
+	  invoked).
+
 config SPL_CPU_SUPPORT
 	bool "Support CPU drivers"
 	help
@@ -702,7 +718,7 @@ config SPL_YMODEM_SUPPORT
 	  means of transmitting U-Boot over a serial line for using in SPL,
 	  with a checksum to ensure correctness.
 
-config SPL_ATF_SUPPORT
+config SPL_ATF
 	bool "Support ARM Trusted Firmware"
 	depends on ARM64
 	help
@@ -710,12 +726,6 @@ config SPL_ATF_SUPPORT
 	  is loaded by SPL(which is considered as BL2 in ATF terminology).
 	  More detail at: https://github.com/ARM-software/arm-trusted-firmware
 
-config SPL_ATF_TEXT_BASE
-	depends on SPL_ATF_SUPPORT
-	hex "ATF BL31 base address"
-	help
-	  This is the base address in memory for ATF BL31 text and entry point.
-
 config TPL
 	bool
 	depends on SUPPORT_TPL

+ 1 - 1
common/spl/Makefile

@@ -22,7 +22,7 @@ endif
 obj-$(CONFIG_$(SPL_TPL_)UBI) += spl_ubi.o
 obj-$(CONFIG_$(SPL_TPL_)NET_SUPPORT) += spl_net.o
 obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += spl_mmc.o
-obj-$(CONFIG_$(SPL_TPL_)ATF_SUPPORT) += spl_atf.o
+obj-$(CONFIG_$(SPL_TPL_)ATF) += spl_atf.o
 obj-$(CONFIG_$(SPL_TPL_)USB_SUPPORT) += spl_usb.o
 obj-$(CONFIG_$(SPL_TPL_)FAT_SUPPORT) += spl_fat.o
 obj-$(CONFIG_$(SPL_TPL_)EXT_SUPPORT) += spl_ext.o

+ 6 - 5
common/spl/spl.c

@@ -418,6 +418,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 	case IH_OS_U_BOOT:
 		debug("Jumping to U-Boot\n");
 		break;
+#if CONFIG_IS_ENABLED(ATF)
+	case IH_OS_ARM_TRUSTED_FIRMWARE:
+		debug("Jumping to U-Boot via ARM Trusted Firmware\n");
+		spl_invoke_atf(&spl_image);
+		break;
+#endif
 #ifdef CONFIG_SPL_OS_BOOT
 	case IH_OS_LINUX:
 		debug("Jumping to Linux\n");
@@ -442,11 +448,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 		debug("Failed to stash bootstage: err=%d\n", ret);
 #endif
 
-	if (CONFIG_IS_ENABLED(ATF_SUPPORT)) {
-		debug("loaded - jumping to U-Boot via ATF BL31.\n");
-		bl31_entry();
-	}
-
 	debug("loaded - jumping to U-Boot...\n");
 	spl_board_prepare_for_boot();
 	jump_to_image_no_args(&spl_image);

+ 76 - 8
common/spl/spl_atf.c

@@ -5,6 +5,7 @@
  * reserved.
  * Copyright (C) 2016 Rockchip Electronic Co.,Ltd
  * Written by Kever Yang <kever.yang@rock-chips.com>
+ * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:     BSD-3-Clause
  */
@@ -30,7 +31,7 @@ static struct bl31_params *bl2_to_bl31_params;
  *
  * @return bl31 params structure pointer
  */
-struct bl31_params *bl2_plat_get_bl31_params(void)
+static struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl33_entry)
 {
 	struct entry_point_info *bl33_ep_info;
 
@@ -66,7 +67,7 @@ struct bl31_params *bl2_plat_get_bl31_params(void)
 
 	/* BL33 expects to receive the primary CPU MPID (through x0) */
 	bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
-	bl33_ep_info->pc = CONFIG_SYS_TEXT_BASE;
+	bl33_ep_info->pc = bl33_entry;
 	bl33_ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
 				     DISABLE_ALL_EXECPTIONS);
 
@@ -77,21 +78,88 @@ struct bl31_params *bl2_plat_get_bl31_params(void)
 	return bl2_to_bl31_params;
 }
 
-void raw_write_daif(unsigned int daif)
+static inline void raw_write_daif(unsigned int daif)
 {
 	__asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory");
 }
 
-void bl31_entry(void)
+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)
 {
 	struct bl31_params *bl31_params;
-	void (*entry)(struct bl31_params *params, void *plat_params) = NULL;
+	atf_entry_t  atf_entry = (atf_entry_t)bl31_entry;
 
-	bl31_params = bl2_plat_get_bl31_params();
-	entry = (void *)CONFIG_SPL_ATF_TEXT_BASE;
+	bl31_params = bl2_plat_get_bl31_params(bl33_entry);
 
 	raw_write_daif(SPSR_EXCEPTION_MASK);
 	dcache_disable();
 
-	entry(bl31_params, NULL);
+	atf_entry((void *)bl31_params, (void *)fdt_addr);
+}
+
+static int spl_fit_images_find_uboot(void *blob)
+{
+	int parent, node, ndepth;
+	const void *data;
+
+	if (!blob)
+		return -FDT_ERR_BADMAGIC;
+
+	parent = fdt_path_offset(blob, "/fit-images");
+	if (parent < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	for (node = fdt_next_node(blob, parent, &ndepth);
+	     (node >= 0) && (ndepth > 0);
+	     node = fdt_next_node(blob, node, &ndepth)) {
+		if (ndepth != 1)
+			continue;
+
+		data = fdt_getprop(blob, node, FIT_OS_PROP, NULL);
+		if (!data)
+			continue;
+
+		if (genimg_get_os_id(data) == IH_OS_U_BOOT)
+			return node;
+	};
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+uintptr_t spl_fit_images_get_entry(void *blob, int node)
+{
+	ulong  val;
+
+	val = fdt_getprop_u32(blob, node, "entry-point");
+	if (val == FDT_ERROR)
+		val = fdt_getprop_u32(blob, node, "load-addr");
+
+	debug("%s: entry point 0x%lx\n", __func__, val);
+	return val;
+}
+
+void spl_invoke_atf(struct spl_image_info *spl_image)
+{
+	uintptr_t  bl33_entry = CONFIG_SYS_TEXT_BASE;
+	void *blob = spl_image->fdt_addr;
+	int node;
+
+	/*
+	 * Find the U-Boot binary (in /fit-images) load addreess or
+	 * entry point (if different) and pass it as the BL3-3 entry
+	 * point.
+	 * This will need to be extended to support Falcon mode.
+	 */
+
+	node = spl_fit_images_find_uboot(blob);
+	if (node >= 0)
+		bl33_entry = spl_fit_images_get_entry(blob, node);
+
+	/*
+	 * We don't provide a BL3-2 entry yet, but this will be possible
+	 * using similar logic.
+	 */
+	bl31_entry(spl_image->entry_point, bl33_entry, (uintptr_t)blob);
 }

+ 150 - 43
common/spl/spl_fit.c

@@ -2,7 +2,7 @@
  * Copyright (C) 2016 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
  *
- * SPDX-License-Identifier:     GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
@@ -16,22 +16,24 @@
 #endif
 
 /**
- * spl_fit_get_image_node(): By using the matching configuration subnode,
+ * spl_fit_get_image_name(): By using the matching configuration subnode,
  * retrieve the name of an image, specified by a property name and an index
  * into that.
  * @fit:	Pointer to the FDT blob.
  * @images:	Offset of the /images subnode.
  * @type:	Name of the property within the configuration subnode.
  * @index:	Index into the list of strings in this property.
+ * @outname:	Name of the image
  *
- * Return:	the node offset of the respective image node or a negative
- * 		error number.
+ * Return:	0 on success, or a negative error number
  */
-static int spl_fit_get_image_node(const void *fit, int images,
-				  const char *type, int index)
+static int spl_fit_get_image_name(const void *fit, int images,
+				  const char *type, int index,
+				  char **outname)
 {
 	const char *name, *str;
-	int node, conf_node;
+	__maybe_unused int node;
+	int conf_node;
 	int len, i;
 
 	conf_node = fit_find_config_node(fit);
@@ -63,7 +65,35 @@ static int spl_fit_get_image_node(const void *fit, int images,
 		}
 	}
 
+	*outname = (char *)str;
+	return 0;
+}
+
+/**
+ * spl_fit_get_image_node(): By using the matching configuration subnode,
+ * retrieve the name of an image, specified by a property name and an index
+ * into that.
+ * @fit:	Pointer to the FDT blob.
+ * @images:	Offset of the /images subnode.
+ * @type:	Name of the property within the configuration subnode.
+ * @index:	Index into the list of strings in this property.
+ *
+ * Return:	the node offset of the respective image node or a negative
+ *		error number.
+ */
+static int spl_fit_get_image_node(const void *fit, int images,
+				  const char *type, int index)
+{
+	char *str;
+	int err;
+	int node;
+
+	err = spl_fit_get_image_name(fit, images, type, index, &str);
+	if (err)
+		return err;
+
 	debug("%s: '%s'\n", type, str);
+
 	node = fdt_subnode_offset(fit, images, str);
 	if (node < 0) {
 		debug("cannot find image node '%s': %d\n", str, node);
@@ -116,15 +146,15 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size,
  * @info:	points to information about the device to load data from
  * @sector:	the start sector of the FIT image on the device
  * @fit:	points to the flattened device tree blob describing the FIT
- * 		image
+ *		image
  * @base_offset: the beginning of the data area containing the actual
  *		image data, relative to the beginning of the FIT
  * @node:	offset of the DT node describing the image to load (relative
- * 		to @fit)
+ *		to @fit)
  * @image_info:	will be filled with information about the loaded image
- * 		If the FIT node does not contain a "load" (address) property,
- * 		the image gets loaded to the address pointed to by the
- * 		load_addr member in this struct.
+ *		If the FIT node does not contain a "load" (address) property,
+ *		the image gets loaded to the address pointed to by the
+ *		load_addr member in this struct.
  *
  * Return:	0 on success or a negative error number.
  */
@@ -218,6 +248,73 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
 	return 0;
 }
 
+static int spl_fit_append_fdt(struct spl_image_info *spl_image,
+			      struct spl_load_info *info, ulong sector,
+			      void *fit, int images, ulong base_offset)
+{
+	struct spl_image_info image_info;
+	int node, ret;
+
+	/* Figure out which device tree the board wants to use */
+	node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
+	if (node < 0) {
+		debug("%s: cannot find FDT node\n", __func__);
+		return node;
+	}
+
+	/*
+	 * Read the device tree and place it after the image.
+	 * Align the destination address to ARCH_DMA_MINALIGN.
+	 */
+	image_info.load_addr = spl_image->load_addr + spl_image->size;
+	ret = spl_load_fit_image(info, sector, fit, base_offset, node,
+				 &image_info);
+
+	if (ret < 0)
+		return ret;
+
+	/* Make the load-address of the FDT available for the SPL framework */
+	spl_image->fdt_addr = (void *)image_info.load_addr;
+#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
+	/* Try to make space, so we can inject details on the loadables */
+	ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
+#endif
+
+	return ret;
+}
+
+static int spl_fit_record_loadable(const void *fit, int images, int index,
+				   void *blob, struct spl_image_info *image)
+{
+	int ret = 0;
+#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
+	char *name;
+	int node;
+
+	ret = spl_fit_get_image_name(fit, images, "loadables",
+				     index, &name);
+	if (ret < 0)
+		return ret;
+
+	node = spl_fit_get_image_node(fit, images, "loadables", index);
+
+	ret = fdt_record_loadable(blob, index, name, image->load_addr,
+				  image->size, image->entry_point,
+				  fdt_getprop(fit, node, "type", NULL),
+				  fdt_getprop(fit, node, "os", NULL));
+#endif
+	return ret;
+}
+
+static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
+{
+#if CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
+	return -ENOTSUPP;
+#else
+	return fit_image_get_os(fit, noffset, os);
+#endif
+}
+
 int spl_load_simple_fit(struct spl_image_info *spl_image,
 			struct spl_load_info *info, ulong sector, void *fit)
 {
@@ -225,7 +322,6 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 	ulong size;
 	unsigned long count;
 	struct spl_image_info image_info;
-	bool boot_os = false;
 	int node = -1;
 	int images, ret;
 	int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
@@ -273,17 +369,18 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 		return -1;
 	}
 
+	/*
+	 * Find the U-Boot image using the following search order:
+	 *   - start at 'firmware' (e.g. an ARM Trusted Firmware)
+	 *   - fall back 'kernel' (e.g. a Falcon-mode OS boot
+	 *   - fall back to using the first 'loadables' entry
+	 */
+	if (node < 0)
+		node = spl_fit_get_image_node(fit, images, "firmware", 0);
 #ifdef CONFIG_SPL_OS_BOOT
-	/* Find OS image first */
-	node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0);
 	if (node < 0)
-		debug("No kernel image.\n");
-	else
-		boot_os = true;
+		node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0);
 #endif
-	/* find the U-Boot image */
-	if (node < 0)
-		node = spl_fit_get_image_node(fit, images, "firmware", 0);
 	if (node < 0) {
 		debug("could not find firmware image, trying loadables...\n");
 		node = spl_fit_get_image_node(fit, images, "loadables", 0);
@@ -305,34 +402,29 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_SPL_OS_BOOT
-	if (!fit_image_get_os(fit, node, &spl_image->os))
+	/*
+	 * For backward compatibility, we treat the first node that is
+	 * as a U-Boot image, if no OS-type has been declared.
+	 */
+	if (!spl_fit_image_get_os(fit, node, &spl_image->os))
 		debug("Image OS is %s\n", genimg_get_os_name(spl_image->os));
-#else
-	spl_image->os = IH_OS_U_BOOT;
+#if !defined(CONFIG_SPL_OS_BOOT)
+	else
+		spl_image->os = IH_OS_U_BOOT;
 #endif
 
-	if (!boot_os) {
-		/* Figure out which device tree the board wants to use */
-		node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
-		if (node < 0) {
-			debug("%s: cannot find FDT node\n", __func__);
-			return node;
-		}
-
-		/*
-		 * Read the device tree and place it after the image.
-		 * Align the destination address to ARCH_DMA_MINALIGN.
-		 */
-		image_info.load_addr = spl_image->load_addr + spl_image->size;
-		ret = spl_load_fit_image(info, sector, fit, base_offset, node,
-					 &image_info);
-		if (ret < 0)
-			return ret;
-	}
+	/*
+	 * Booting a next-stage U-Boot may require us to append the FDT.
+	 * We allow this to fail, as the U-Boot image might embed its FDT.
+	 */
+	if (spl_image->os == IH_OS_U_BOOT)
+		spl_fit_append_fdt(spl_image, info, sector, fit,
+				   images, base_offset);
 
 	/* Now check if there are more images for us to load */
 	for (; ; index++) {
+		uint8_t os_type = IH_OS_INVALID;
+
 		node = spl_fit_get_image_node(fit, images, "loadables", index);
 		if (node < 0)
 			break;
@@ -342,6 +434,15 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 		if (ret < 0)
 			continue;
 
+		if (!spl_fit_image_get_os(fit, node, &os_type))
+			debug("Loadable is %s\n", genimg_get_os_name(os_type));
+
+		if (os_type == IH_OS_U_BOOT) {
+			spl_fit_append_fdt(&image_info, info, sector,
+					   fit, images, base_offset);
+			spl_image->fdt_addr = image_info.fdt_addr;
+		}
+
 		/*
 		 * If the "firmware" image did not provide an entry point,
 		 * use the first valid entry point from the loadables.
@@ -349,6 +450,12 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 		if (spl_image->entry_point == FDT_ERROR &&
 		    image_info.entry_point != FDT_ERROR)
 			spl_image->entry_point = image_info.entry_point;
+
+		/* Record our loadables into the FDT */
+		if (spl_image->fdt_addr)
+			spl_fit_record_loadable(fit, images, index,
+						spl_image->fdt_addr,
+						&image_info);
 	}
 
 	/*

+ 1 - 2
configs/firefly-rk3399_defconfig

@@ -12,8 +12,7 @@ CONFIG_SPL_LOAD_FIT=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
-CONFIG_SPL_ATF_SUPPORT=y
-CONFIG_SPL_ATF_TEXT_BASE=0x00010000
+CONFIG_SPL_ATF=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y

+ 1 - 2
configs/lion-rk3368_defconfig

@@ -32,8 +32,7 @@ CONFIG_SPL_BOOTROM_SUPPORT=y
 CONFIG_TPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
-CONFIG_SPL_ATF_SUPPORT=y
-CONFIG_SPL_ATF_TEXT_BASE=0x10000
+CONFIG_SPL_ATF=y
 CONFIG_TPL=y
 CONFIG_TPL_BOOTROM_SUPPORT=y
 CONFIG_TPL_DRIVERS_MISC_SUPPORT=y

+ 3 - 0
configs/puma-rk3399_defconfig

@@ -5,6 +5,8 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_SYS_MALLOC_F_LEN=0x4000
 CONFIG_ROCKCHIP_RK3399=y
+CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0
+CONFIG_ROCKCHIP_BOOT_MODE_REG=0x0
 CONFIG_TARGET_PUMA_RK3399=y
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
@@ -23,6 +25,7 @@ CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x4000
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_POWER_SUPPORT=y
+CONFIG_SPL_ATF=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y

+ 2 - 6
drivers/clk/rockchip/clk_rk3399.c

@@ -569,11 +569,6 @@ static const struct spi_clkreg spi_clkregs[] = {
 		.sel_shift = CLK_SPI5_PLL_SEL_SHIFT, },
 };
 
-static inline u32 extract_bits(u32 val, unsigned width, unsigned shift)
-{
-	return (val >> shift) & ((1 << width) - 1);
-}
-
 static ulong rk3399_spi_get_clk(struct rk3399_cru *cru, ulong clk_id)
 {
 	const struct spi_clkreg *spiclk = NULL;
@@ -590,7 +585,8 @@ static ulong rk3399_spi_get_clk(struct rk3399_cru *cru, ulong clk_id)
 	}
 
 	val = readl(&cru->clksel_con[spiclk->reg]);
-	div = extract_bits(val, CLK_SPI_PLL_DIV_CON_WIDTH, spiclk->div_shift);
+	div = bitfield_extract(val, spiclk->div_shift,
+			       CLK_SPI_PLL_DIV_CON_WIDTH);
 
 	return DIV_TO_RATE(GPLL_HZ, div);
 }

+ 19 - 0
drivers/pinctrl/rockchip/pinctrl_rk3399.c

@@ -70,11 +70,21 @@ static void pinctrl_rk3399_i2c_config(struct rk3399_grf_regs *grf,
 			     PMUGRF_GPIO1C0_SEL_MASK,
 			     PMUGRF_I2C0PMU_SCL << PMUGRF_GPIO1C0_SEL_SHIFT);
 		break;
+	case PERIPH_ID_I2C8:
+		rk_clrsetreg(&pmugrf->gpio1c_iomux,
+			     PMUGRF_GPIO1C4_SEL_MASK,
+			     PMUGRF_I2C8PMU_SDA << PMUGRF_GPIO1C4_SEL_SHIFT);
+		rk_clrsetreg(&pmugrf->gpio1c_iomux,
+			     PMUGRF_GPIO1C5_SEL_MASK,
+			     PMUGRF_I2C8PMU_SCL << PMUGRF_GPIO1C5_SEL_SHIFT);
+		break;
 	case PERIPH_ID_I2C1:
 	case PERIPH_ID_I2C2:
 	case PERIPH_ID_I2C3:
 	case PERIPH_ID_I2C4:
 	case PERIPH_ID_I2C5:
+	case PERIPH_ID_I2C6:
+	case PERIPH_ID_I2C7:
 	default:
 		debug("i2c id = %d iomux error!\n", i2c_id);
 		break;
@@ -301,6 +311,9 @@ static int rk3399_pinctrl_request(struct udevice *dev, int func, int flags)
 	case PERIPH_ID_I2C3:
 	case PERIPH_ID_I2C4:
 	case PERIPH_ID_I2C5:
+	case PERIPH_ID_I2C6:
+	case PERIPH_ID_I2C7:
+	case PERIPH_ID_I2C8:
 		pinctrl_rk3399_i2c_config(priv->grf, priv->pmugrf, func);
 		break;
 	case PERIPH_ID_SPI0:
@@ -375,6 +388,12 @@ static int rk3399_pinctrl_get_periph_id(struct udevice *dev,
 		return PERIPH_ID_I2C4;
 	case 38:
 		return PERIPH_ID_I2C5;
+	case 37:
+		return PERIPH_ID_I2C6;
+	case 36:
+		return PERIPH_ID_I2C7;
+	case 58:
+		return PERIPH_ID_I2C8;
 	case 65:
 		return PERIPH_ID_SDMMC1;
 #if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)

+ 18 - 0
include/fdt_support.h

@@ -133,6 +133,24 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev);
 static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {}
 #endif
 
+/**
+ * Record information about a processed loadable in /fit-images (creating
+ * /fit-images if necessary).
+ *
+ * @param blob		FDT blob to update
+ * @param index	        index of this loadable
+ * @param name          name of the loadable
+ * @param load_addr     address the loadable was loaded to
+ * @param size          number of bytes loaded
+ * @param entry_point   entry point (if specified, otherwise pass -1)
+ * @param type          type (if specified, otherwise pass NULL)
+ * @param os            os-type (if specified, otherwise pass NULL)
+ * @return 0 if ok, or -1 or -FDT_ERR_... on error
+ */
+int fdt_record_loadable(void *blob, u32 index, const char *name,
+			uintptr_t load_addr, u32 size, uintptr_t entry_point,
+			const char *type, const char *os);
+
 #ifdef CONFIG_PCI
 #include <pci.h>
 int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose);

+ 1 - 0
include/image.h

@@ -152,6 +152,7 @@ enum {
 	IH_OS_OSE,			/* OSE		*/
 	IH_OS_PLAN9,			/* Plan 9	*/
 	IH_OS_OPENRTOS,		/* OpenRTOS	*/
+	IH_OS_ARM_TRUSTED_FIRMWARE,     /* ARM Trusted Firmware */
 
 	IH_OS_COUNT,
 };

+ 9 - 3
include/spl.h

@@ -23,8 +23,11 @@
 struct spl_image_info {
 	const char *name;
 	u8 os;
-	ulong load_addr;
-	ulong entry_point;
+	uintptr_t load_addr;
+	uintptr_t entry_point;
+#if CONFIG_IS_ENABLED(LOAD_FIT)
+	void *fdt_addr;
+#endif
 	u32 size;
 	u32 flags;
 	void *arg;
@@ -268,7 +271,10 @@ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr);
 int spl_mmc_load_image(struct spl_image_info *spl_image,
 		       struct spl_boot_device *bootdev);
 
-void bl31_entry(void);
+/**
+ * spl_invoke_atf - boot using an ARM trusted firmware image
+ */
+void spl_invoke_atf(struct spl_image_info *spl_image);
 
 /**
  * board_return_to_bootrom - allow for boards to continue with the boot ROM