From 4914af1286c4a48cd0ae98cf6adea3569111413b Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:29 +0200 Subject: [PATCH 01/19] image: add IH_OS_ARM_TRUSTED_FIRMWARE for ARM Trusted Firmware To boot on ARMv8 systems with ARM Trusted Firmware, we need to assemble an ATF-specific parameter structure and also provide the address of the images started by ATF (e.g. BL3-3, which may be the full U-Boot). To allow us to identify an ARM Trusted Firmware contained in a FIT image, this adds the necessary definitions. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- common/image.c | 1 + include/image.h | 1 + 2 files changed, 2 insertions(+) diff --git a/common/image.c b/common/image.c index 06fdca129c..4ec4744589 100644 --- a/common/image.c +++ b/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", }, diff --git a/include/image.h b/include/image.h index 127cfc5148..e9c18ce403 100644 --- a/include/image.h +++ b/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, }; From 75014470aec60580978962071972f2962695938d Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:30 +0200 Subject: [PATCH 02/19] spl: add a fdt_addr field to spl_image_info When loading a full U-Boot with detached device-tree using the SPL FIT backend, we should store the address of the FDT loaded as part of the SPL image info: this allows us to fixup the FDT with additional info we may want to propagate onward. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- include/spl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/spl.h b/include/spl.h index b14a29c57c..1ac97188a3 100644 --- a/include/spl.h +++ b/include/spl.h @@ -25,6 +25,9 @@ struct spl_image_info { u8 os; ulong load_addr; ulong entry_point; +#if CONFIG_IS_ENABLED(LOAD_FIT) + void *fdt_addr; +#endif u32 size; u32 flags; void *arg; From f2efe6786eeaa2305353a01056ffef55ae520b7d Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:31 +0200 Subject: [PATCH 03/19] spl: change load_addr and entry_point to uintptr_t Mainly a stylistic change: convert the load_addr and entry_point fields of struct spl_image_info to uintptr_t (from ulong). Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- include/spl.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/spl.h b/include/spl.h index 1ac97188a3..308ce7b563 100644 --- a/include/spl.h +++ b/include/spl.h @@ -23,8 +23,8 @@ 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 @@ -271,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 From d879616e9e64cf5a9c43dedc30677aa2fa463d64 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:32 +0200 Subject: [PATCH 04/19] spl: fit: simplify logic for FDT loading for non-OS boots To better support bootin through an ATF or OPTEE, we need to streamline some of the logic for when the FDT is appended to an image: depending on the image type, we'd like to append the FDT not at all (the case for the OS boot), to the 'firmware' image (if it is a U-Boot) or to one of the loadables (if the 'firmware' is an ATF, an OPTEE, or some other image-type and U-Boot is listed in the loadabled). To achieve this goal, we drop the os_boot flag and track the type of image loaded. If it is of type IH_OS_U_BOOT, we append the FDT. Signed-off-by: Philipp Tomsich Acked-by: York Sun Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 88 ++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 32d9ee5901..c496f45b72 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -218,6 +218,30 @@ 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); + return ret; +} + int spl_load_simple_fit(struct spl_image_info *spl_image, struct spl_load_info *info, ulong sector, void *fit) { @@ -225,7 +249,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 +296,18 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, return -1; } -#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; -#endif - /* find the U-Boot image */ + /* + * 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 + if (node < 0) + node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0); +#endif if (node < 0) { debug("could not find firmware image, trying loadables...\n"); node = spl_fit_get_image_node(fit, images, "loadables", 0); @@ -305,34 +329,29 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (ret) return ret; -#ifdef CONFIG_SPL_OS_BOOT + /* + * For backward compatibility, we treat the first node that is + * as a U-Boot image, if no OS-type has been declared. + */ if (!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 +361,13 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (ret < 0) continue; + if (!fit_image_get_os(fit, node, &os_type)) + debug("Loadable is %s\n", genimg_get_os_name(os_type)); + + if (spl_image->os == IH_OS_U_BOOT) + spl_fit_append_fdt(spl_image, info, sector, + fit, images, base_offset); + /* * If the "firmware" image did not provide an entry point, * use the first valid entry point from the loadables. From 9f45aeb937275960405de0f2abca8c665dbb03d4 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:33 +0200 Subject: [PATCH 05/19] spl: fit: implement fdt_record_loadable During the loading of more complex FIT images (e.g. when the invoked next stage needs to find additional firmware for a power-management core... or if there are multiple images for different privilege levels started in parallel), it is helpful to create a record of what images are loaded where: if a FDT is loaded for one of the next stages, it can be used to convey the status and location of loadables. This adds a fdt_record_loadable() function that can be invoked to record the status of each loadable below the /fit-images path. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- common/fdt_support.c | 39 +++++++++++++++++++++++++++++++++++++++ include/fdt_support.h | 20 ++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/common/fdt_support.c b/common/fdt_support.c index f4f9543d54..6896dcb285 100644 --- a/common/fdt_support.c +++ b/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/" 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 diff --git a/include/fdt_support.h b/include/fdt_support.h index 2bca4d7889..afaf0e787d 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -133,6 +133,26 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev); static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {} #endif +#if CONFIG_IS_ENABLED(LOAD_FIT) +/** + * 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); +#endif + #ifdef CONFIG_PCI #include int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose); From a616c783f22a045e580f101141a9d62775f97365 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:34 +0200 Subject: [PATCH 06/19] spl: fit: implement recording of loadables into /fit-images If a FDT was loaded (e.g. to append it to U-Boot image), we store it's address and record information for all loadables into this FDT. This allows us to easily keep track of images for multiple privilege levels (e.g. with ATF) or of firmware images preloaded into temporary locations (e.g. PMU firmware that may overlap the SPL stage). Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- common/spl/spl_fit.c | 95 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index c496f45b72..128af1bbd6 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -2,7 +2,7 @@ * Copyright (C) 2016 Google, Inc * Written by Simon Glass * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -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. */ @@ -239,6 +269,35 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, 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; + /* Try to make space, so we can inject details on the loadables */ + ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192); + + return ret; +} + +static int spl_fit_record_loadable(const void *fit, int images, int index, + void *blob, struct spl_image_info *image) +{ + char *name; + int node, ret; + + 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)); return ret; } @@ -364,9 +423,11 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (!fit_image_get_os(fit, node, &os_type)) debug("Loadable is %s\n", genimg_get_os_name(os_type)); - if (spl_image->os == IH_OS_U_BOOT) - spl_fit_append_fdt(spl_image, info, sector, + 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, @@ -375,6 +436,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); } /* From 1d3790905d9c089b434c376f2dcc585b6a92bc99 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:35 +0200 Subject: [PATCH 07/19] spl: atf: introduce spl_invoke_atf and make bl31_entry private This adds a new interface spl_invoke_atf() that takes a spl_image_info argument and then derives the necessary parameters for the ATF entry. Based on the additional information recorded (into /fit-images) from the FIT loadables, we can now easily locate the next boot stage. We now pass a pointer to a FDT as the platform-specific parameter pointer to ATF (so we don't run into the future headache of every board/platform defining their own proprietary tag-structure), as FDT access is already available in ATF. With the necessary infrastructure in place, we can now update the support for the ARM Trusted Firmware to dispatch into the spl_invoke_atf function only if a IH_OS_ARM_TRUSTED_FIRMWARE image is loaded. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- common/spl/spl.c | 11 +++--- common/spl/spl_atf.c | 84 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index d232f67ba9..3bb20c7822 100644 --- a/common/spl/spl.c +++ b/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); diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c index 6e8f928044..63557c01e8 100644 --- a/common/spl/spl_atf.c +++ b/common/spl/spl_atf.c @@ -5,6 +5,7 @@ * reserved. * Copyright (C) 2016 Rockchip Electronic Co.,Ltd * Written by Kever Yang + * 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); } From aa122f6b3d24bd133392c7dd2a882a8cc2cbd622 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:36 +0200 Subject: [PATCH 08/19] spl: rename config item SPL_ATF_SUPPORT to SPL_ATF Having CONFIG_SPL_ATF seems more natural. Rename it, while it it is easy and there's few boards that use it (only RK3399 and RK3368 boards). Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- common/spl/Kconfig | 2 +- common/spl/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index c62b82fd68..3169bbb888 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -702,7 +702,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 diff --git a/common/spl/Makefile b/common/spl/Makefile index e229947b53..9bf8a2d81a 100644 --- a/common/spl/Makefile +++ b/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 From 506c428ec8a96befa30b48c4915704826afd7928 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:37 +0200 Subject: [PATCH 09/19] spl: atf: drop the SPL_ATF_TEXT_BASE configuration item The SPL_ATF_TEXT_BASE configuration item has become obsolete. Remove it from Kconfig. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- common/spl/Kconfig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 3169bbb888..ce7c3afa59 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -710,12 +710,6 @@ config SPL_ATF 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 From cd5eae5590fcf8529ff0b2268db0968558842218 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:39 +0200 Subject: [PATCH 10/19] rockchip: defconfig: firefly-rk3399: sync up with SPL changes for ATF This tracks the SPL changes for ATF for the Firefly: * renames ATF_SUPPORT to ATF * drops CONFIG_SPL_ATF_TEXT_BASE Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- configs/firefly-rk3399_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/firefly-rk3399_defconfig b/configs/firefly-rk3399_defconfig index dc3cda4260..731222cdd0 100644 --- a/configs/firefly-rk3399_defconfig +++ b/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 From fc76fa3cfa3fa716bf541f30977896fd6656b148 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:40 +0200 Subject: [PATCH 11/19] rockchip: board: puma-rk3399: update .its file to use new features This commit updates the .its file for the RK3399-Q7 to use the new features and demonstrates how to use those: * it marks the ATF as the 'firmware' * it tracks the OS-type for U-Boot and ATF * it loads the PMU (M0) firmware to DRAM and records the location to /fit-images (where our ATF reads it from) With the handoff of the next-stage FDT to ATF in place, we can now use this to pass information about the load addresses and names of each loadables to ATF: now we can load the M0 firmware into DRAM and avoid overwriting parts of the SPL stage. This is achieved by changing our .its-file to use an available area of DRAM as the load-address. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- board/theobroma-systems/puma_rk3399/fit_spl_atf.its | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/board/theobroma-systems/puma_rk3399/fit_spl_atf.its b/board/theobroma-systems/puma_rk3399/fit_spl_atf.its index 520f846d66..cb7d92fead 100644 --- a/board/theobroma-systems/puma_rk3399/fit_spl_atf.its +++ b/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"; }; }; From b07856fe436a6ccf20c6176cd450a4c4487973a1 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:41 +0200 Subject: [PATCH 12/19] rockchip: board: lion-rk3368: update .its file For the RK3368-uQ7, we can now update the .its file to mark the Trusted Firmware as out 'firmware' bootable and annotate both ATF and U-Boot with an OS-type. Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- board/theobroma-systems/lion_rk3368/fit_spl_atf.its | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its b/board/theobroma-systems/lion_rk3368/fit_spl_atf.its index 60daddcc44..e3bea5ea2f 100644 --- a/board/theobroma-systems/lion_rk3368/fit_spl_atf.its +++ b/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"; }; }; From cba7b949b4a2ebceabf6adde04eb9f67f71c7ee4 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:42 +0200 Subject: [PATCH 13/19] rockchip: defconfig: puma-rk3399: sync up with SPL changes for ATF This defconfig update makes use of the new features: * CONFIG_ROCKCHIP_SPL_RESERVE_IRAM is now set to 0, as there is no overlap between the M0 firmware and the ATF (we load this to DRAM and relocate it to its final location within the ATF) * tracks the ATF_SUPPORT -> ATF renaming Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- configs/puma-rk3399_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig index ebbf8a9b05..4591cc2c6b 100644 --- a/configs/puma-rk3399_defconfig +++ b/configs/puma-rk3399_defconfig @@ -5,6 +5,7 @@ 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_TARGET_PUMA_RK3399=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y @@ -23,6 +24,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 From ec4bf3d6bd5ebc01d2664560b1e79e36994f6c1d Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Sep 2017 21:29:43 +0200 Subject: [PATCH 14/19] rockchip: defconfig: lion-rk3368: sync up with SPL changes for ATF This tracks the SPL changes for ATF for the RK3368-uQ7: * renames ATF_SUPPORT to ATF * drops CONFIG_SPL_ATF_TEXT_BASE (now dynamically retrieved from the .itb file) Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- configs/lion-rk3368_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/lion-rk3368_defconfig b/configs/lion-rk3368_defconfig index 8dae75cefd..9548b961e3 100644 --- a/configs/lion-rk3368_defconfig +++ b/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 From 337bbb6297775e8e9d664e96e96004f00d1d8c02 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 24 Nov 2017 13:26:03 +0100 Subject: [PATCH 15/19] spl: fit: add SPL_FIT_IMAGE_TINY config to reduce code-size A minor code-size increase from the changes for tracking the os-type of FIT images and from infrastructure for recording the loadables into the the loaded FDT, broke the builds for sun50i and some OMAP2+ devices. This change adds a new config option (enabled by default for MACH_SUN50I, MACH_SUN50I_H5 and ARCH_OMAP2PLUS) that does skips these processing steps (bringing code size down to below the limit again). The os-type is not evaluated, but assumed to be IH_OS_UBOOT (i.e. taking the code-paths intended for backward-compatibility). Note that enabling this config option precludes any useful downstream processing, such as utilising a special calling convention for ATF or OPTEE, based on the os-type of the loadables. Signed-off-by: Philipp Tomsich --- common/spl/Kconfig | 16 ++++++++++++++++ common/spl/spl_fit.c | 20 +++++++++++++++++--- include/fdt_support.h | 2 -- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index ce7c3afa59..b1ee15c96d 100644 --- a/common/spl/Kconfig +++ b/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 diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 128af1bbd6..72ae8f4c50 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -275,8 +275,10 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, /* 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; } @@ -284,8 +286,10 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, 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; + int node; ret = spl_fit_get_image_name(fit, images, "loadables", index, &name); @@ -298,9 +302,19 @@ static int spl_fit_record_loadable(const void *fit, int images, int index, 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) { @@ -392,7 +406,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, * For backward compatibility, we treat the first node that is * as a U-Boot image, if no OS-type has been declared. */ - if (!fit_image_get_os(fit, node, &spl_image->os)) + if (!spl_fit_image_get_os(fit, node, &spl_image->os)) debug("Image OS is %s\n", genimg_get_os_name(spl_image->os)); #if !defined(CONFIG_SPL_OS_BOOT) else @@ -420,7 +434,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (ret < 0) continue; - if (!fit_image_get_os(fit, node, &os_type)) + 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) { diff --git a/include/fdt_support.h b/include/fdt_support.h index afaf0e787d..e0f908636c 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -133,7 +133,6 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev); static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {} #endif -#if CONFIG_IS_ENABLED(LOAD_FIT) /** * Record information about a processed loadable in /fit-images (creating * /fit-images if necessary). @@ -151,7 +150,6 @@ static inline void fdt_fixup_crypto_node(void *blob, int sec_rev) {} 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); -#endif #ifdef CONFIG_PCI #include From a8ee98df183ed240afb5220c3cdf2991f69fa578 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 22 Nov 2017 19:45:04 +0100 Subject: [PATCH 16/19] rockchip: clk: rk3399: change extract_bits to bitfield_extract The RK3399 clk driver still has a left-over use of extract_bits, which can be replaced by using bitfield_extract from include/bitfield.h. This rewrites the invocation to use the shared function. Signed-off-by: Philipp Tomsich --- drivers/clk/rockchip/clk_rk3399.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index e21d056efb..2e85ac7df2 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/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); } From 8c2bb589e29d5cb89e10c3ddd23b28d949fa9693 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 22 Nov 2017 19:47:37 +0100 Subject: [PATCH 17/19] rockchip: pinctrl: rk3399: add support for I2C8 The RK3399 has a total of 9 I2C controllers. To support these, the enum in periph.h is extended and the mapping from the IRQ numbers to the peripheral-ids is extended to ensure that pinctrl requests are passed through to the function configuring the I2C pins. For I2C8, the pinctrl is implemented and tested (on a RK3399-Q7) using communication with the FAN53555 connected on I2C8. Signed-off-by: Philipp Tomsich Tested-by: Klaus Goger --- .../include/asm/arch-rockchip/grf_rk3399.h | 7 ++++++- arch/arm/include/asm/arch-rockchip/periph.h | 3 +++ drivers/pinctrl/rockchip/pinctrl_rk3399.c | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h b/arch/arm/include/asm/arch-rockchip/grf_rk3399.h index 8d21eb7bee..b541e2caa1 100644 --- a/arch/arm/include/asm/arch-rockchip/grf_rk3399.h +++ b/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 */ diff --git a/arch/arm/include/asm/arch-rockchip/periph.h b/arch/arm/include/asm/arch-rockchip/periph.h index 9f4bc2e107..77cf5b9450 100644 --- a/arch/arm/include/asm/arch-rockchip/periph.h +++ b/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, diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3399.c b/drivers/pinctrl/rockchip/pinctrl_rk3399.c index cab268c7d6..19a7415522 100644 --- a/drivers/pinctrl/rockchip/pinctrl_rk3399.c +++ b/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) From f07d76c00d1fe05baad1599d01d07a9226498923 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 24 Nov 2017 14:44:58 +0100 Subject: [PATCH 18/19] rockchip: fix turning off boot-mode via Kconfig The ROCKCHIP_BOOT_MODE_REG option defaults to a hex value, so 0 will show as 0x0 if a default is provided and changed via Kconfig. However, it still will show as 0, if no default is given. Consequently, the "is set to something other than 0" test in a Makefile is cumbersome. Instead this check can easily be performed in the C-code. This removes the ifeq-check from mach-rockchip/Makefile, adds a matching #if-check to boot_mode.c and fixes resulting link issues (if boot_mode.o was not included due to the Makefile check) by defining a stub function (in case the functionality is not built in) for setup_boot_mode in boot_mode.c. Fixes: e306779 (rockchip: make boot_mode related codes reused across all platforms) Signed-off-by: Philipp Tomsich --- arch/arm/mach-rockchip/Makefile | 6 ++++-- arch/arm/mach-rockchip/boot_mode.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 2127f2bbe8..7e1f864383 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/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 diff --git a/arch/arm/mach-rockchip/boot_mode.c b/arch/arm/mach-rockchip/boot_mode.c index 942849f2f8..d7dd425aae 100644 --- a/arch/arm/mach-rockchip/boot_mode.c +++ b/arch/arm/mach-rockchip/boot_mode.c @@ -9,6 +9,15 @@ #include #include +#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 From e5ee24dda20af5dc87971b497268f9fb1c83027e Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 24 Nov 2017 14:44:59 +0100 Subject: [PATCH 19/19] rockchip: defconfig: puma-rk3399: bypass ADC-based boot_mode check The boot (and fallback/emergency boot) concept for the RK3399-Q7 differs from Rockchip's reference platforms. On the RK3399-Q7, some of this functionality is present in the bootloader itself (and configurable); some is backed in hardware by the Qseven BIOS_DISABLE signal to invoke the final stages of fallbacks (i.e. either an external boot bypassing on-module memories or falling back to the BROM for USB recovery). In summary: the ADC-based boot_mode check does not apply for the RK3399-Q7 and we therefore disable it (in this commit) by setting CONFIG_BOOT_MODE_REG to 0. Signed-off-by: Philipp Tomsich --- configs/puma-rk3399_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig index 4591cc2c6b..18705ed534 100644 --- a/configs/puma-rk3399_defconfig +++ b/configs/puma-rk3399_defconfig @@ -6,6 +6,7 @@ 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