From e9ebc17e59217eed457ae83b3c1eec0f7a86daa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 4 Nov 2020 15:33:44 +0100 Subject: [PATCH 01/24] Makefile: Do not call useless command 'true' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Macro 'cmd_objcopy_uboot' currently does not work with passed empty command expanded from 'cmd_static_rela' and therefore dummy command 'true' is set in 'cmd_static_rela' to workaround this issue. Eliminate it now by fixing 'cmd_objcopy_uboot' macro to work also with empty 'cmd_static_rela' macro and remove useless invocation of command 'true'. Signed-off-by: Pali Rohár Reviewed-by: Simon Glass --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cef149dec9..72be573ebc 100644 --- a/Makefile +++ b/Makefile @@ -885,7 +885,7 @@ cmd_static_rela = \ tools/relocate-rela $(3) $(4) $$start $$end else quiet_cmd_static_rela = -cmd_static_rela = true +cmd_static_rela = endif # Always append INPUTS so that arch config.mk's can add custom ones @@ -1312,7 +1312,11 @@ endif shell_cmd = { $(call echo-cmd,$(1)) $(cmd_$(1)); } quiet_cmd_objcopy_uboot = OBJCOPY $@ +ifdef cmd_static_rela cmd_objcopy_uboot = $(cmd_objcopy) && $(call shell_cmd,static_rela,$<,$@,$(CONFIG_SYS_TEXT_BASE)) || { rm -f $@; false; } +else +cmd_objcopy_uboot = $(cmd_objcopy) +endif u-boot-nodtb.bin: u-boot FORCE $(call if_changed,objcopy_uboot) From 4d145f26dd06d9de0c2da3ff2c1f8be1ac9dbd2b Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Fri, 11 Dec 2020 19:56:47 +0100 Subject: [PATCH 02/24] bootcount: allow to use this feature on TPL This commit add an option TPL_BOOTCOUNT_LIMIT to use bootcount on TPL. Signed-off-by: Philippe Reynes Reviewed-by: Simon Glass --- common/spl/Kconfig | 9 ++++++++- common/spl/spl.c | 4 +++- drivers/Makefile | 1 + include/bootcount.h | 6 +++--- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index bdc229f930..774541c02b 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -186,7 +186,7 @@ config SPL_BOOTROM_SUPPORT config SPL_BOOTCOUNT_LIMIT bool "Support bootcount in SPL" - depends on SPL_ENV_SUPPORT + depends on SPL_ENV_SUPPORT && !TPL_BOOTCOUNT_LIMIT help On some boards, which use 'falcon' mode, it is necessary to check and increment the number of boot attempts. Such boards do not @@ -1382,6 +1382,13 @@ config TPL_BOARD_INIT spl_board_init() from board_init_r(). This function should be provided by the board. +config TPL_BOOTCOUNT_LIMIT + bool "Support bootcount in TPL" + depends on TPL_ENV_SUPPORT + help + If this option is enabled, the TPL will support bootcount. + For example, it may be useful to choose the device to boot. + config TPL_LDSCRIPT string "Linker script for the TPL stage" depends on TPL diff --git a/common/spl/spl.c b/common/spl/spl.c index 835c53deaa..8b7374487d 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -837,7 +837,9 @@ ulong spl_relocate_stack_gd(void) #endif } -#if defined(CONFIG_BOOTCOUNT_LIMIT) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT) +#if defined(CONFIG_BOOTCOUNT_LIMIT) && \ + ((!defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT)) || \ + (defined(CONFIG_TPL_BUILD) && !defined(CONFIG_TPL_BOOTCOUNT_LIMIT))) void bootcount_store(ulong a) { } diff --git a/drivers/Makefile b/drivers/Makefile index e371bc32bb..c562a719f7 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -69,6 +69,7 @@ endif ifdef CONFIG_TPL_BUILD +obj-$(CONFIG_TPL_BOOTCOUNT_LIMIT) += bootcount/ obj-$(CONFIG_TPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/ endif diff --git a/include/bootcount.h b/include/bootcount.h index cd30403984..b1d1fe53d1 100644 --- a/include/bootcount.h +++ b/include/bootcount.h @@ -69,7 +69,7 @@ void bootcount_store(ulong); */ ulong bootcount_load(void); -#if defined(CONFIG_SPL_BOOTCOUNT_LIMIT) || defined(CONFIG_BOOTCOUNT_LIMIT) +#if defined(CONFIG_SPL_BOOTCOUNT_LIMIT) || defined(CONFIG_TPL_BOOTCOUNT_LIMIT) || defined(CONFIG_BOOTCOUNT_LIMIT) #if !defined(CONFIG_SYS_BOOTCOUNT_LE) && !defined(CONFIG_SYS_BOOTCOUNT_BE) # if __BYTE_ORDER == __LITTLE_ENDIAN @@ -130,7 +130,7 @@ static inline void bootcount_inc(void) #ifndef CONFIG_SPL_BUILD /* Only increment bootcount when no bootcount support in SPL */ -#ifndef CONFIG_SPL_BOOTCOUNT_LIMIT +#if !defined(CONFIG_SPL_BOOTCOUNT_LIMIT) && !defined(CONFIG_TPL_BOOTCOUNT_LIMIT) bootcount_store(++bootcount); #endif env_set_ulong("bootcount", bootcount); @@ -140,5 +140,5 @@ static inline void bootcount_inc(void) #else static inline int bootcount_error(void) { return 0; } static inline void bootcount_inc(void) {} -#endif /* CONFIG_SPL_BOOTCOUNT_LIMIT || CONFIG_BOOTCOUNT_LIMIT */ +#endif /* CONFIG_SPL_BOOTCOUNT_LIMIT || CONFIG_TPL_BOOTCOUNT_LIMIT || CONFIG_BOOTCOUNT_LIMIT */ #endif /* _BOOTCOUNT_H__ */ From b7cfe32e186d453001a12ee0ee2c85d08a0ecd53 Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Tue, 5 Jan 2021 20:03:11 +0000 Subject: [PATCH 03/24] smccc: fix sign bit expansion Signed ARM_SMCCC_FAST_CALL value is shifted to 31'st bit. Then, it is expanded to 64 bit value, which results in 1s in higher 32 bits. This causes corrupted values in 64-bit SMC IDs and issues in buggy handlers of 32-bit calls. We need to make ARM_SMCCC_FAST_CALL unsigned long, so it would work properly on 32 bit architectures. Signed-off-by: Volodymyr Babchuk Reviewed-by: Jens Wiklander --- include/linux/arm-smccc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 2d1e6cc156..7f2be23394 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -11,8 +11,8 @@ * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html */ -#define ARM_SMCCC_STD_CALL 0 -#define ARM_SMCCC_FAST_CALL 1 +#define ARM_SMCCC_STD_CALL 0UL +#define ARM_SMCCC_FAST_CALL 1UL #define ARM_SMCCC_TYPE_SHIFT 31 #define ARM_SMCCC_SMC_32 0 From 76c78a548144b69ecc3ed9cc2d670297983da6b1 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Mon, 11 Jan 2021 08:46:58 -0600 Subject: [PATCH 04/24] common: fit-sig: Fix error message in fit_config_verify_sig() In fit_config_verify_sig(), when no 'signature*' subnode exists in the configuration node, the fdt_for_each_subnode() loop is a no-op. Therefore, no error flags are set, and 'err_,sg' is not populated with an error string. This is incorrect behavior. Populate err_msg to indicate that no 'signature' is found, before entering the loop. The first call to fit_image_verify_sig() will override clear err_msg, or set it to a more specific message. Signed-off-by: Alexandru Gagniuc Reviewed-by: Simon Glass --- common/image-fit-sig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c index d39741e905..31cc580941 100644 --- a/common/image-fit-sig.c +++ b/common/image-fit-sig.c @@ -360,7 +360,7 @@ static int fit_config_verify_sig(const void *fit, int conf_noffset, const void *sig_blob, int sig_offset) { int noffset; - char *err_msg = ""; + char *err_msg = "No 'signature' subnode found"; int verified = 0; int ret; From a7a029d14de44bdcd050181ec5544b1ae3728c8a Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 12 Jan 2021 12:03:43 +0100 Subject: [PATCH 05/24] pci: Remove CONFIG_PCI_ENUM_ONLY as it's not used (any more) This patch completely removes CONFIG_PCI_ENUM_ONLY from the PCI code as it is not configured for any board (any more). With this removal, some PCI related files get cleaned up a bit. Additional, dm_pciauto_setup_device() is now static, as it's not referenced from any code outside of this C file. Signed-off-by: Stefan Roese Cc: Simon Glass Cc: Bin Meng Reviewed-by: Simon Glass --- README | 7 --- drivers/pci/pci_auto.c | 104 ++++++++++++++--------------------- drivers/pci/pci_auto_old.c | 18 ------ scripts/config_whitelist.txt | 1 - 4 files changed, 41 insertions(+), 89 deletions(-) diff --git a/README b/README index 89606c8add..f7f9aa5619 100644 --- a/README +++ b/README @@ -2770,13 +2770,6 @@ Low Level (hardware related) configuration options: CONFIG_SYS_OR3_PRELIM, CONFIG_SYS_BR3_PRELIM: Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM) -- CONFIG_PCI_ENUM_ONLY - Only scan through and get the devices on the buses. - Don't do any setup work, presumably because someone or - something has already done it, and we don't need to do it - a second time. Useful for platforms that are pre-booted - by coreboot or similar. - - CONFIG_PCI_INDIRECT_BRIDGE: Enable support for indirect PCI bridges. diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index b37dd994e5..da76148c58 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -18,10 +18,10 @@ #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8 #endif -void dm_pciauto_setup_device(struct udevice *dev, int bars_num, - struct pci_region *mem, - struct pci_region *prefetch, struct pci_region *io, - bool enum_only) +static void dm_pciauto_setup_device(struct udevice *dev, int bars_num, + struct pci_region *mem, + struct pci_region *prefetch, + struct pci_region *io) { u32 bar_response; pci_size_t bar_size; @@ -43,8 +43,7 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, int ret = 0; /* Tickle the BAR and get the response */ - if (!enum_only) - dm_pci_write_config32(dev, bar, 0xffffffff); + dm_pci_write_config32(dev, bar, 0xffffffff); dm_pci_read_config32(dev, bar, &bar_response); /* If BAR is not implemented (or invalid) go to the next BAR */ @@ -58,8 +57,7 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, bar_size = bar_response & PCI_BASE_ADDRESS_IO_MASK; bar_size &= ~(bar_size - 1); - if (!enum_only) - bar_res = io; + bar_res = io; debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (unsigned long long)bar_size); @@ -69,10 +67,7 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, u32 bar_response_upper; u64 bar64; - if (!enum_only) { - dm_pci_write_config32(dev, bar + 4, - 0xffffffff); - } + dm_pci_write_config32(dev, bar + 4, 0xffffffff); dm_pci_read_config32(dev, bar + 4, &bar_response_upper); @@ -81,33 +76,29 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; - if (!enum_only) - found_mem64 = 1; + found_mem64 = 1; } else { bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); } - if (!enum_only) { - if (prefetch && (bar_response & - PCI_BASE_ADDRESS_MEM_PREFETCH)) { - bar_res = prefetch; - } else { - bar_res = mem; - } - } + + if (prefetch && + (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) + bar_res = prefetch; + else + bar_res = mem; debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", bar_nr, bar_res == prefetch ? "Prf" : "Mem", (unsigned long long)bar_size); } - if (!enum_only) { - ret = pciauto_region_allocate(bar_res, bar_size, - &bar_value, found_mem64); - if (ret) - printf("PCI: Failed autoconfig bar %x\n", bar); - } - if (!enum_only && !ret) { + ret = pciauto_region_allocate(bar_res, bar_size, + &bar_value, found_mem64); + if (ret) + printf("PCI: Failed autoconfig bar %x\n", bar); + + if (!ret) { /* Write it out and update our limit */ dm_pci_write_config32(dev, bar, (u32)bar_value); @@ -135,28 +126,24 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num, bar_nr++; } - if (!enum_only) { - /* Configure the expansion ROM address */ - dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); - header_type &= 0x7f; - if (header_type != PCI_HEADER_TYPE_CARDBUS) { - rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ? - PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1; - dm_pci_write_config32(dev, rom_addr, 0xfffffffe); - dm_pci_read_config32(dev, rom_addr, &bar_response); - if (bar_response) { - bar_size = -(bar_response & ~1); - debug("PCI Autoconfig: ROM, size=%#x, ", - (unsigned int)bar_size); - if (pciauto_region_allocate(mem, bar_size, - &bar_value, - false) == 0) { - dm_pci_write_config32(dev, rom_addr, - bar_value); - } - cmdstat |= PCI_COMMAND_MEMORY; - debug("\n"); + /* Configure the expansion ROM address */ + dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); + header_type &= 0x7f; + if (header_type != PCI_HEADER_TYPE_CARDBUS) { + rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ? + PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1; + dm_pci_write_config32(dev, rom_addr, 0xfffffffe); + dm_pci_read_config32(dev, rom_addr, &bar_response); + if (bar_response) { + bar_size = -(bar_response & ~1); + debug("PCI Autoconfig: ROM, size=%#x, ", + (unsigned int)bar_size); + if (pciauto_region_allocate(mem, bar_size, &bar_value, + false) == 0) { + dm_pci_write_config32(dev, rom_addr, bar_value); } + cmdstat |= PCI_COMMAND_MEMORY; + debug("\n"); } } @@ -319,15 +306,10 @@ int dm_pciauto_config_device(struct udevice *dev) struct pci_region *pci_io; unsigned int sub_bus = PCI_BUS(dm_pci_get_bdf(dev)); unsigned short class; - bool enum_only = false; struct udevice *ctlr = pci_get_controller(dev); struct pci_controller *ctlr_hose = dev_get_uclass_priv(ctlr); int ret; -#ifdef CONFIG_PCI_ENUM_ONLY - enum_only = true; -#endif - pci_mem = ctlr_hose->pci_mem; pci_prefetch = ctlr_hose->pci_prefetch; pci_io = ctlr_hose->pci_io; @@ -339,8 +321,7 @@ int dm_pciauto_config_device(struct udevice *dev) debug("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dm_pci_get_bdf(dev))); - dm_pciauto_setup_device(dev, 2, pci_mem, pci_prefetch, pci_io, - enum_only); + dm_pciauto_setup_device(dev, 2, pci_mem, pci_prefetch, pci_io); ret = dm_pci_hose_probe_bus(dev); if (ret < 0) @@ -353,8 +334,7 @@ int dm_pciauto_config_device(struct udevice *dev) * just do a minimal setup of the bridge, * let the OS take care of the rest */ - dm_pciauto_setup_device(dev, 0, pci_mem, pci_prefetch, pci_io, - enum_only); + dm_pciauto_setup_device(dev, 0, pci_mem, pci_prefetch, pci_io); debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n", PCI_DEV(dm_pci_get_bdf(dev))); @@ -378,8 +358,7 @@ int dm_pciauto_config_device(struct udevice *dev) */ debug("PCI Autoconfig: Broken bridge found, only minimal config\n"); dm_pciauto_setup_device(dev, 0, hose->pci_mem, - hose->pci_prefetch, hose->pci_io, - enum_only); + hose->pci_prefetch, hose->pci_io); break; #endif @@ -388,8 +367,7 @@ int dm_pciauto_config_device(struct udevice *dev) /* fall through */ default: - dm_pciauto_setup_device(dev, 6, pci_mem, pci_prefetch, pci_io, - enum_only); + dm_pciauto_setup_device(dev, 6, pci_mem, pci_prefetch, pci_io); break; } diff --git a/drivers/pci/pci_auto_old.c b/drivers/pci/pci_auto_old.c index 8b67cfa92b..c56ff53c4f 100644 --- a/drivers/pci/pci_auto_old.c +++ b/drivers/pci/pci_auto_old.c @@ -36,13 +36,11 @@ void pciauto_setup_device(struct pci_controller *hose, pci_size_t bar_size; u16 cmdstat = 0; int bar, bar_nr = 0; -#ifndef CONFIG_PCI_ENUM_ONLY u8 header_type; int rom_addr; pci_addr_t bar_value; struct pci_region *bar_res; int found_mem64 = 0; -#endif u16 class; pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); @@ -51,26 +49,20 @@ void pciauto_setup_device(struct pci_controller *hose, for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) { /* Tickle the BAR and get the response */ -#ifndef CONFIG_PCI_ENUM_ONLY pci_hose_write_config_dword(hose, dev, bar, 0xffffffff); -#endif pci_hose_read_config_dword(hose, dev, bar, &bar_response); /* If BAR is not implemented go to the next BAR */ if (!bar_response) continue; -#ifndef CONFIG_PCI_ENUM_ONLY found_mem64 = 0; -#endif /* Check the BAR type and set our address mask */ if (bar_response & PCI_BASE_ADDRESS_SPACE) { bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK)) & 0xffff) + 1; -#ifndef CONFIG_PCI_ENUM_ONLY bar_res = io; -#endif debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (unsigned long long)bar_size); @@ -80,23 +72,18 @@ void pciauto_setup_device(struct pci_controller *hose, u32 bar_response_upper; u64 bar64; -#ifndef CONFIG_PCI_ENUM_ONLY pci_hose_write_config_dword(hose, dev, bar + 4, 0xffffffff); -#endif pci_hose_read_config_dword(hose, dev, bar + 4, &bar_response_upper); bar64 = ((u64)bar_response_upper << 32) | bar_response; bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; -#ifndef CONFIG_PCI_ENUM_ONLY found_mem64 = 1; -#endif } else { bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); } -#ifndef CONFIG_PCI_ENUM_ONLY if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) bar_res = prefetch; else @@ -105,10 +92,8 @@ void pciauto_setup_device(struct pci_controller *hose, debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", bar_nr, bar_res == prefetch ? "Prf" : "Mem", (unsigned long long)bar_size); -#endif } -#ifndef CONFIG_PCI_ENUM_ONLY if (pciauto_region_allocate(bar_res, bar_size, &bar_value, found_mem64) == 0) { /* Write it out and update our limit */ @@ -129,7 +114,6 @@ void pciauto_setup_device(struct pci_controller *hose, } } -#endif cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY; @@ -138,7 +122,6 @@ void pciauto_setup_device(struct pci_controller *hose, bar_nr++; } -#ifndef CONFIG_PCI_ENUM_ONLY /* Configure the expansion ROM address */ pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type); header_type &= 0x7f; @@ -160,7 +143,6 @@ void pciauto_setup_device(struct pci_controller *hose, debug("\n"); } } -#endif /* PCI_COMMAND_IO must be set for VGA device */ pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index e2cf205451..86e011c06d 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1222,7 +1222,6 @@ CONFIG_PCI_CLK_FREQ CONFIG_PCI_CONFIG_HOST_BRIDGE CONFIG_PCI_EHCI_DEVICE CONFIG_PCI_EHCI_DEVNO -CONFIG_PCI_ENUM_ONLY CONFIG_PCI_FIXUP_DEV CONFIG_PCI_GT64120 CONFIG_PCI_INDIRECT_BRIDGE From 040fad3791fe05b985516a68c9437847173da56a Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 12 Jan 2021 19:18:54 +0100 Subject: [PATCH 06/24] lib: rsa: rsa-verify: don't look for keys in the FIT image In the function rsa_verify_hash, if the "main" key doesn't work, u-boot try others keys. But it searches those keys in the FIT image instead of the u-boot device tree. Signed-off-by: Philippe Reynes Reviewed-by: Simon Glass --- lib/rsa/rsa-verify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 0ab0f629d0..e34d3293d1 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -522,10 +522,10 @@ int rsa_verify_hash(struct image_sign_info *info, return ret; /* No luck, so try each of the keys in turn */ - for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, + for (ndepth = 0, noffset = fdt_next_node(blob, sig_node, &ndepth); (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(info->fit, noffset, &ndepth)) { + noffset = fdt_next_node(blob, noffset, &ndepth)) { if (ndepth == 1 && noffset != node) { ret = rsa_verify_with_keynode(info, hash, sig, sig_len, From 09d9ba9097ceb374f2802506c9e755fd8d5dd861 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:42 -0700 Subject: [PATCH 07/24] spl: Add functions for next and previous phase It is useful to be able to figure out which phase we are loading next and which phase we came from. Add some functions to handle this as well as returning the name of a phase. This allows messages like "Booting to x" where x is the next phase. At present, TPL says 'Jumping to U-Boot' at the end, when in fact it is jumping to SPL. This is confusing, so use the new functions to correct this. Tests for this will come with an upcoming minor SPL test refactor. Signed-off-by: Simon Glass --- common/spl/spl.c | 2 +- include/spl.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index 8b7374487d..8cb6f3d531 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -734,7 +734,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("Failed to stash bootstage: err=%d\n", ret); #endif - debug("loaded - jumping to U-Boot...\n"); + debug("loaded - jumping to %s...\n", spl_phase_name(spl_next_phase())); spl_board_prepare_for_boot(); jump_to_image_no_args(&spl_image); } diff --git a/include/spl.h b/include/spl.h index a7648787b7..faffeb519a 100644 --- a/include/spl.h +++ b/include/spl.h @@ -58,6 +58,7 @@ static inline bool u_boot_first_phase(void) } enum u_boot_phase { + PHASE_NONE, /* Invalid phase, signifying before U-Boot */ PHASE_TPL, /* Running in TPL */ PHASE_SPL, /* Running in SPL */ PHASE_BOARD_F, /* Running in U-Boot before relocation */ @@ -123,6 +124,58 @@ static inline enum u_boot_phase spl_phase(void) #endif } +/** + * spl_prev_phase() - Figure out the previous U-Boot phase + * + * @return the previous phase from this one, e.g. if called in SPL this returns + * PHASE_TPL, if TPL is enabled + */ +static inline enum u_boot_phase spl_prev_phase(void) +{ +#ifdef CONFIG_TPL_BUILD + return PHASE_NONE; +#elif defined(CONFIG_SPL_BUILD) + return IS_ENABLED(CONFIG_TPL) ? PHASE_TPL : PHASE_NONE; +#else + return IS_ENABLED(CONFIG_SPL) ? PHASE_SPL : PHASE_NONE; +#endif +} + +/** + * spl_next_phase() - Figure out the next U-Boot phase + * + * @return the next phase from this one, e.g. if called in TPL this returns + * PHASE_SPL + */ +static inline enum u_boot_phase spl_next_phase(void) +{ +#ifdef CONFIG_TPL_BUILD + return PHASE_SPL; +#else + return PHASE_BOARD_F; +#endif +} + +/** + * spl_phase_name() - Get the name of the current phase + * + * @return phase name + */ +static inline const char *spl_phase_name(enum u_boot_phase phase) +{ + switch (phase) { + case PHASE_TPL: + return "TPL"; + case PHASE_SPL: + return "SPL"; + case PHASE_BOARD_F: + case PHASE_BOARD_R: + return "U-Boot"; + default: + return "phase?"; + } +} + /* A string name for SPL or TPL */ #ifdef CONFIG_SPL_BUILD # ifdef CONFIG_TPL_BUILD From 9fe064646d2c9f3914cd5ceae51c34020aa77599 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:43 -0700 Subject: [PATCH 08/24] bloblist: Support relocating to a larger space Typically in TPL/SPL the bloblist is quite small. But U-Boot proper may want to add a lot more to it, such as ACPI tables. Add a way to expand the bloblist by relocating it in U-Boot proper, along with the other relocation activities. Signed-off-by: Simon Glass --- common/Kconfig | 10 ++++++++++ common/bloblist.c | 11 +++++++++++ common/board_f.c | 10 ++++++---- include/bloblist.h | 10 ++++++++++ test/bloblist.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/common/Kconfig b/common/Kconfig index d8982ba377..45535e3501 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -697,6 +697,16 @@ config BLOBLIST_ADDR Sets the address of the bloblist, set up by the first part of U-Boot which runs. Subsequent U-Boot stages typically use the same address. +config BLOBLIST_SIZE_RELOC + hex "Size of bloblist after relocation" + depends on BLOBLIST + default BLOBLIST_SIZE + help + Sets the size of the bloblist in bytes after relocation. Since U-Boot + has a lot more memory available then, it is possible to use a larger + size than the one set up by SPL. This bloblist is set up during the + relocation process. + endmenu source "common/spl/Kconfig" diff --git a/common/bloblist.c b/common/bloblist.c index 33b5862380..e32f551e27 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -317,6 +317,15 @@ void bloblist_show_list(void) } } +void bloblist_reloc(void *to, uint to_size, void *from, uint from_size) +{ + struct bloblist_hdr *hdr; + + memcpy(to, from, from_size); + hdr = to; + hdr->size = to_size; +} + int bloblist_init(void) { bool expected; @@ -327,6 +336,8 @@ int bloblist_init(void) * that runs */ expected = !u_boot_first_phase(); + if (spl_prev_phase() == PHASE_TPL && !IS_ENABLED(CONFIG_TPL_BLOBLIST)) + expected = false; if (expected) ret = bloblist_check(CONFIG_BLOBLIST_ADDR, CONFIG_BLOBLIST_SIZE); diff --git a/common/board_f.c b/common/board_f.c index ae3001bed1..4327a43a33 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -568,9 +568,10 @@ static int reserve_bloblist(void) { #ifdef CONFIG_BLOBLIST /* Align to a 4KB boundary for easier reading of addresses */ - gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - CONFIG_BLOBLIST_SIZE, - 0x1000); - gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE); + gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - + CONFIG_BLOBLIST_SIZE_RELOC, 0x1000); + gd->new_bloblist = map_sysmem(gd->start_addr_sp, + CONFIG_BLOBLIST_SIZE_RELOC); #endif return 0; @@ -658,7 +659,8 @@ static int reloc_bloblist(void) debug("Copying bloblist from %p to %p, size %x\n", gd->bloblist, gd->new_bloblist, size); - memcpy(gd->new_bloblist, gd->bloblist, size); + bloblist_reloc(gd->new_bloblist, CONFIG_BLOBLIST_SIZE_RELOC, + gd->bloblist, size); gd->bloblist = gd->new_bloblist; } #endif diff --git a/include/bloblist.h b/include/bloblist.h index 8cdce61187..964b974fda 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -242,6 +242,16 @@ void bloblist_show_list(void); */ const char *bloblist_tag_name(enum bloblist_tag_t tag); +/** + * bloblist_reloc() - Relocate the bloblist and optionally resize it + * + * @to: Pointer to new bloblist location (must not overlap old location) + * @to:size: New size for bloblist (must be larger than from_size) + * @from: Pointer to bloblist to relocate + * @from_size: Size of bloblist to relocate + */ +void bloblist_reloc(void *to, uint to_size, void *from, uint from_size); + /** * bloblist_init() - Init the bloblist system with a single bloblist * diff --git a/test/bloblist.c b/test/bloblist.c index 900299dd68..85a6c39680 100644 --- a/test/bloblist.c +++ b/test/bloblist.c @@ -347,6 +347,42 @@ static int bloblist_test_align(struct unit_test_state *uts) } BLOBLIST_TEST(bloblist_test_align, 0); +/* Test relocation of a bloblist */ +static int bloblist_test_reloc(struct unit_test_state *uts) +{ + const uint large_size = TEST_BLOBLIST_SIZE; + const uint small_size = 0x20; + void *old_ptr, *new_ptr; + void *blob1, *blob2; + ulong new_addr; + ulong new_size; + + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); + old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); + + /* Add one blob and then one that won't fit */ + blob1 = bloblist_add(TEST_TAG, small_size, 0); + ut_assertnonnull(blob1); + blob2 = bloblist_add(TEST_TAG2, large_size, 0); + ut_assertnull(blob2); + + /* Relocate the bloblist somewhere else, a bit larger */ + new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE; + new_size = TEST_BLOBLIST_SIZE + 0x100; + new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE); + bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE); + gd->bloblist = new_ptr; + + /* Check the old blob is there and that we can now add the bigger one */ + ut_assertnonnull(bloblist_find(TEST_TAG, small_size)); + ut_assertnull(bloblist_find(TEST_TAG2, small_size)); + blob2 = bloblist_add(TEST_TAG2, large_size, 0); + ut_assertnonnull(blob2); + + return 0; +} +BLOBLIST_TEST(bloblist_test_reloc, 0); + int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { From 02d7a53ce6e31dc8f9f45949209468c16a025638 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:44 -0700 Subject: [PATCH 09/24] bloblist: Add missing tag names Add tag names for recently added types. Fixes: d2cb7a22da0 (x86: Allow putting some tables in the bloblist) Signed-off-by: Simon Glass --- common/bloblist.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/bloblist.c b/common/bloblist.c index e32f551e27..0e6448becb 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -33,6 +33,12 @@ static const char *const tag_name[] = { [BLOBLISTT_SPL_HANDOFF] = "SPL hand-off", [BLOBLISTT_VBOOT_CTX] = "Chrome OS vboot context", [BLOBLISTT_VBOOT_HANDOFF] = "Chrome OS vboot hand-off", + [BLOBLISTT_ACPI_GNVS] = "ACPI GNVS", + [BLOBLISTT_INTEL_VBT] = "Intel Video-BIOS table", + [BLOBLISTT_TPM2_TCG_LOG] = "TPM v2 log space", + [BLOBLISTT_TCPA_LOG] = "TPM log space", + [BLOBLISTT_ACPI_TABLES] = "ACPI tables for x86", + [BLOBLISTT_SMBIOS_TABLES] = "SMBIOS tables for x86", }; const char *bloblist_tag_name(enum bloblist_tag_t tag) From 7d70116fc752a2b97a67ee839be16239074614ce Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:46 -0700 Subject: [PATCH 10/24] video: Allow syncing the entire framebuffer to the copy In some cases so much of the framebuffer is updated that it is not worth copying the changes piece by piece to the copy framebuffer. Add a function to copy the whole thing. Signed-off-by: Simon Glass --- drivers/video/video-uclass.c | 10 ++++++++++ include/video.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index a1d527529f..91d078a9d5 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -290,6 +290,16 @@ int video_sync_copy(struct udevice *dev, void *from, void *to) return 0; } + +int video_sync_copy_all(struct udevice *dev) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + + video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size); + + return 0; +} + #endif /* Set up the colour map */ diff --git a/include/video.h b/include/video.h index 74d822fadb..827733305e 100644 --- a/include/video.h +++ b/include/video.h @@ -246,11 +246,25 @@ void video_set_default_colors(struct udevice *dev, bool invert); * frame buffer start */ int video_sync_copy(struct udevice *dev, void *from, void *to); + +/** + * video_sync_copy_all() - Sync the entire framebuffer to the copy + * + * @dev: Vidconsole device being updated + * @return 0 (always) + */ +int video_sync_copy_all(struct udevice *dev); #else static inline int video_sync_copy(struct udevice *dev, void *from, void *to) { return 0; } + +static inline int video_sync_copy_all(struct udevice *dev) +{ + return 0; +} + #endif #ifndef CONFIG_DM_VIDEO From 177e7f9ce71fa659c17c2e1b8f97a1425389577f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:47 -0700 Subject: [PATCH 11/24] net: Use CONFIG_IS_ENABLED() in eth_dev_get_mac_address() This function may be used in SPL where devicetree is not available. Use the correct macro so that the function does not try to read it. Signed-off-by: Simon Glass --- net/eth-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 7c2454f5ae..35842f577d 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -487,7 +487,7 @@ static int eth_pre_unbind(struct udevice *dev) static bool eth_dev_get_mac_address(struct udevice *dev, u8 mac[ARP_HLEN]) { -#if IS_ENABLED(CONFIG_OF_CONTROL) +#if CONFIG_IS_ENABLED(OF_CONTROL) const uint8_t *p; p = dev_read_u8_array_ptr(dev, "mac-address", ARP_HLEN); From e1d23f569bb3d07611cc5e5ee41b32f553cabb9f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:48 -0700 Subject: [PATCH 12/24] fdtdec: Update the missing-devicetree message This includes information about sandbox which is not relevant for most boards. Drop it. Also add the address to help figure out the problem. Signed-off-by: Simon Glass --- lib/fdtdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 0ab7105fef..54f7a1fe47 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -600,7 +600,8 @@ int fdtdec_prepare_fdt(void) #ifdef CONFIG_SPL_BUILD puts("Missing DTB\n"); #else - puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d \n"); + printf("No valid device tree binary found at %p\n", + gd->fdt_blob); # ifdef DEBUG if (gd->fdt_blob) { printf("fdt_blob=%p\n", gd->fdt_blob); From 0a2aaab0b678fd1778ff2fc59d0770fc82995532 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:49 -0700 Subject: [PATCH 13/24] fdtdec: Use CONFIG_IS_ENABLED in board_fdt_blob_setup() This setting may be different in SPL and TPL. Update the code to check the correct setting. Signed-off-by: Simon Glass --- lib/fdtdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 54f7a1fe47..a2d2fb4e1f 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1253,7 +1253,7 @@ __weak void *board_fdt_blob_setup(void) void *fdt_blob = NULL; #ifdef CONFIG_SPL_BUILD /* FDT is at end of BSS unless it is in a different memory region */ - if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS)) + if (CONFIG_IS_ENABLED(SEPARATE_BSS)) fdt_blob = (ulong *)&_image_binary_end; else fdt_blob = (ulong *)&__bss_end; From ac42fe539ca991543c888e261e62b4187ec9bbee Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:50 -0700 Subject: [PATCH 14/24] display_options: Use USE_TINY_PRINTF for SPL check At present this code uses a simple printf() format if running in SPL. But SPL can use the full printf. Use USE_TINY_PRINTF instead. Signed-off-by: Simon Glass --- lib/display_options.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/display_options.c b/lib/display_options.c index b2025eeb5c..cd48998b6d 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -169,11 +169,10 @@ int print_buffer(ulong addr, const void *data, uint width, uint count, x = lb.us[i] = *(volatile uint16_t *)data; else x = lb.uc[i] = *(volatile uint8_t *)data; -#if defined(CONFIG_SPL_BUILD) - printf(" %x", (uint)x); -#else - printf(" %0*lx", width * 2, x); -#endif + if (CONFIG_IS_ENABLED(USE_TINY_PRINTF)) + printf(" %x", (uint)x); + else + printf(" %0*lx", width * 2, x); data += width; } From f8a2d191cf3a200c080fbf6f8e095589d3afd57f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:51 -0700 Subject: [PATCH 15/24] uuid: Add a comment for UUID_STR_LEN This macro is the length of the string but excludes the terminator. Users must add 1 when declaring a large-enough string. Add a comment to make this clear. Signed-off-by: Simon Glass --- include/uuid.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uuid.h b/include/uuid.h index 0c653cb087..4a4883d3b5 100644 --- a/include/uuid.h +++ b/include/uuid.h @@ -23,6 +23,7 @@ struct uuid { #define UUID_STR_FORMAT_GUID BIT(0) #define UUID_STR_UPPER_CASE BIT(1) +/* Use UUID_STR_LEN + 1 for string space */ #define UUID_STR_LEN 36 #define UUID_BIN_LEN sizeof(struct uuid) From 60868632f6d89f71aca547df01a075149ad96357 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:52 -0700 Subject: [PATCH 16/24] mmc: pci_mmc: Only generate ACPI code for the SD card At present if an eMMC part is in the system, the ACPI table generated will include information about that, as well as the SD card. We only need to include the SD card, since it has a card-detect GPIO. Use a different compatible string for each option, and add code only for the SD card. Signed-off-by: Simon Glass Reviewed-by: Jaehoon Chung --- drivers/mmc/pci_mmc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index b26eb034d0..9316ac12cc 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -17,6 +17,12 @@ #include #include +/* Type of MMC device */ +enum { + TYPE_SD, + TYPE_EMMC, +}; + struct pci_mmc_plat { struct mmc_config cfg; struct mmc mmc; @@ -79,6 +85,8 @@ static int pci_mmc_acpi_fill_ssdt(const struct udevice *dev, if (!dev_has_ofnode(dev)) return 0; + if (dev_get_driver_data(dev) == TYPE_EMMC) + return 0; ret = gpio_get_acpi(&priv->cd_gpio, &gpio); if (ret) @@ -122,7 +130,8 @@ struct acpi_ops pci_mmc_acpi_ops = { }; static const struct udevice_id pci_mmc_match[] = { - { .compatible = "intel,apl-sd" }, + { .compatible = "intel,apl-sd", .data = TYPE_SD }, + { .compatible = "intel,apl-emmc", .data = TYPE_EMMC }, { } }; From 8a8a8314ce669a5faaad4ddfdbef14551ec452b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:54 -0700 Subject: [PATCH 17/24] mmc: pci_mmc: Set the removable flag Set this flag so that it is available to those looking at the device. For non-removable devices there is no need to check for insertion/removable since the media can never change. Signed-off-by: Simon Glass Reviewed-by: Jaehoon Chung --- drivers/mmc/pci_mmc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 9316ac12cc..fd5dd229b5 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -40,8 +41,15 @@ static int pci_mmc_probe(struct udevice *dev) struct pci_mmc_plat *plat = dev_get_plat(dev); struct pci_mmc_priv *priv = dev_get_priv(dev); struct sdhci_host *host = &priv->host; + struct blk_desc *desc; int ret; + ret = mmc_of_parse(dev, &plat->cfg); + if (ret) + return ret; + desc = mmc_get_blk_desc(&plat->mmc); + desc->removable = !(plat->cfg.host_caps & MMC_CAP_NONREMOVABLE); + host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); host->name = dev->name; From ec5f101a3794396fed93e480ebcf8d389041b30e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:55 -0700 Subject: [PATCH 18/24] crc32: Exclude crc32 from TPL Unfortunately the toolchain often brings in the crc32 table even if the function is not actually used. For now, exclude it from the TPL build, which is very sensitive to size. Signed-off-by: Simon Glass --- lib/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Makefile b/lib/Makefile index 851a80ef3b..edc1c3dd4f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -92,7 +92,9 @@ obj-y += display_options.o CFLAGS_display_options.o := $(if $(BUILD_TAG),-DBUILD_TAG='"$(BUILD_TAG)"') obj-$(CONFIG_BCH) += bch.o obj-$(CONFIG_MMC_SPI) += crc7.o +#ifndef CONFIG_TPL_BUILD obj-y += crc32.o +#endif obj-$(CONFIG_CRC32C) += crc32c.o obj-y += ctype.o obj-y += div64.o From 76b54d8ca159b217be976eef986b76e26409ea4a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:56 -0700 Subject: [PATCH 19/24] binman: Move selection of the binman node into a function Move this logic out of the main init function so it is available for other purpose. Use a different error when multiple-images is in use but no subnode is available. This makes it easier to determine what is wrong. Signed-off-by: Simon Glass --- lib/binman.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/binman.c b/lib/binman.c index f027d1b304..b6d9dff5b7 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -30,6 +30,34 @@ struct binman_info { static struct binman_info *binman; +/** + * find_image_node() - Find the top-level binman node + * + * Finds the binman node which can be used to load entries. The correct node + * depends on whether multiple-images is in use. + * + * @nodep: Returns the node found, on success + * @return 0 if OK, , -EINVAL if there is no /binman node, -ECHILD if multiple + * images are being used but the first image is not available + */ +static int find_image_node(ofnode *nodep) +{ + ofnode node; + + node = ofnode_path("/binman"); + if (!ofnode_valid(node)) + return log_msg_ret("binman node", -EINVAL); + if (ofnode_read_bool(node, "multiple-images")) { + node = ofnode_first_subnode(node); + + if (!ofnode_valid(node)) + return log_msg_ret("first image", -ECHILD); + } + *nodep = node; + + return 0; +} + static int binman_entry_find_internal(ofnode node, const char *name, struct binman_entry *entry) { @@ -90,19 +118,14 @@ int binman_get_rom_offset(void) int binman_init(void) { + int ret; + binman = malloc(sizeof(struct binman_info)); if (!binman) return log_msg_ret("space for binman", -ENOMEM); - binman->image = ofnode_path("/binman"); - if (!ofnode_valid(binman->image)) - return log_msg_ret("binman node", -EINVAL); - if (ofnode_read_bool(binman->image, "multiple-images")) { - ofnode node = ofnode_first_subnode(binman->image); - - if (!ofnode_valid(node)) - return log_msg_ret("first image", -ENOENT); - binman->image = node; - } + ret = find_image_node(&binman->image); + if (ret) + return log_msg_ret("node", -ENOENT); binman_set_rom_offset(ROM_OFFSET_NONE); return 0; From 1e35a4d2282329093ae384bfbb8df844e23798c6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:57 -0700 Subject: [PATCH 20/24] binman: Allow reading entries from a subnode Some images may have multiple copies of the same thing, e.g. two versions of the read/write U-Boots. It is necessary to read data from one or other of these under selection of the verified-boot logic. Add a function to select the subnode to use. Signed-off-by: Simon Glass --- include/binman.h | 14 ++++++++++++++ lib/binman.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/binman.h b/include/binman.h index 8b89a9666d..5958dfb448 100644 --- a/include/binman.h +++ b/include/binman.h @@ -70,6 +70,20 @@ int binman_entry_find(const char *name, struct binman_entry *entry); */ ofnode binman_section_find_node(const char *name); +/** + * binman_select_subnode() - Select a subnode to use to find entries + * + * Normally binman selects the top-level node for future entry requests, such as + * binman_entry_find(). This function allows a subnode to be chosen instead. + * + * @name: Name of subnode, typically a section. This must be in the top-level + * binman node + * @return 0 if OK, -EINVAL if there is no /binman node, -ECHILD if multiple + * images are being used but the first image is not available, -ENOENT if + * the requested subnode cannot be found + */ +int binman_select_subnode(const char *name); + /** * binman_init() - Set up the binman symbol information * diff --git a/lib/binman.c b/lib/binman.c index b6d9dff5b7..f415df3054 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -116,6 +116,24 @@ int binman_get_rom_offset(void) return binman->rom_offset; } +int binman_select_subnode(const char *name) +{ + ofnode node; + int ret; + + ret = find_image_node(&node); + if (ret) + return log_msg_ret("main", -ENOENT); + node = ofnode_find_subnode(node, name); + if (!ofnode_valid(node)) + return log_msg_ret("node", -ENOENT); + binman->image = node; + log_debug("binman: Selected image subnode '%s'\n", + ofnode_get_name(binman->image)); + + return 0; +} + int binman_init(void) { int ret; From e088f0c3d87005bd2bdf11d571e20f6232cc021f Mon Sep 17 00:00:00 2001 From: "Yuezhang.Mo@sony.com" Date: Fri, 15 Jan 2021 03:11:49 +0000 Subject: [PATCH 21/24] autoboot: fix illegal memory access when stop key and delay key are empty If both stop key and delay key are empty, the length of these keys is 0. The subtraction operation will cause the u_int type variable to overflow, will cause illegal memory access in key input loop. This commit fixes this bug by using int type instead of u_init. Acked-by: Heinrich Schuchardt --- common/autoboot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/autoboot.c b/common/autoboot.c index ddb6246be3..b025fd99a0 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -164,9 +164,9 @@ static int passwd_abort_key(uint64_t etime) }; char presskey[MAX_DELAY_STOP_STR]; - u_int presskey_len = 0; - u_int presskey_max = 0; - u_int i; + int presskey_len = 0; + int presskey_max = 0; + int i; # ifdef CONFIG_AUTOBOOT_DELAY_STR if (delaykey[0].str == NULL) From 8d612ccde992f0006b80b9e670b70e5c759a968a Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Fri, 15 Jan 2021 13:53:02 +0800 Subject: [PATCH 22/24] rtc: add rtc-abx80x, a driver for the Abracon AB x80x i2c rtc This is a basic driver for the ultra-low-power Abracon AB x80x series of RTC chips. It supports in particular, the supersets AB0805 and AB1805. It allows reading and writing the time, and enables the supercapacitor or battery charger. Signed-off-by: Ying-Chun Liu (PaulLiu) --- drivers/rtc/Kconfig | 9 + drivers/rtc/Makefile | 1 + drivers/rtc/abx80x.c | 553 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 563 insertions(+) create mode 100644 drivers/rtc/abx80x.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cad667a404..aa6d90158c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -166,4 +166,13 @@ config RTC_STM32 help Enable STM32 RTC driver. This driver supports the rtc that is present on some STM32 SoCs. + +config RTC_ABX80X + bool "Enable Abracon ABx80x RTC driver" + depends on DM_RTC + help + If you say yes here you get support for Abracon AB080X and AB180X + families of ultra-low-power battery- and capacitor-backed real-time + clock chips. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ef66dc4bf0..6a45a9c874 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_RTC_S35392A) += s35392a.o obj-$(CONFIG_RTC_STM32) += stm32_rtc.o obj-$(CONFIG_SANDBOX) += sandbox_rtc.o obj-$(CONFIG_RTC_X1205) += x1205.o +obj-$(CONFIG_RTC_ABX80X) += abx80x.o diff --git a/drivers/rtc/abx80x.c b/drivers/rtc/abx80x.c new file mode 100644 index 0000000000..528b06cbd6 --- /dev/null +++ b/drivers/rtc/abx80x.c @@ -0,0 +1,553 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * A driver for the I2C members of the Abracon AB x8xx RTC family, + * and compatible: AB 1805 and AB 0805 + * + * Copyright 2014-2015 Macq S.A. + * Copyright 2020 Linaro + * + * Author: Philippe De Muyter + * Author: Alexandre Belloni + * Author: Ying-Chun Liu (PaulLiu) + * + */ + +#include +#include +#include +#include +#include + +#define ABX8XX_REG_HTH 0x00 +#define ABX8XX_REG_SC 0x01 +#define ABX8XX_REG_MN 0x02 +#define ABX8XX_REG_HR 0x03 +#define ABX8XX_REG_DA 0x04 +#define ABX8XX_REG_MO 0x05 +#define ABX8XX_REG_YR 0x06 +#define ABX8XX_REG_WD 0x07 + +#define ABX8XX_REG_AHTH 0x08 +#define ABX8XX_REG_ASC 0x09 +#define ABX8XX_REG_AMN 0x0a +#define ABX8XX_REG_AHR 0x0b +#define ABX8XX_REG_ADA 0x0c +#define ABX8XX_REG_AMO 0x0d +#define ABX8XX_REG_AWD 0x0e + +#define ABX8XX_REG_STATUS 0x0f +#define ABX8XX_STATUS_AF BIT(2) +#define ABX8XX_STATUS_BLF BIT(4) +#define ABX8XX_STATUS_WDT BIT(6) + +#define ABX8XX_REG_CTRL1 0x10 +#define ABX8XX_CTRL_WRITE BIT(0) +#define ABX8XX_CTRL_ARST BIT(2) +#define ABX8XX_CTRL_12_24 BIT(6) + +#define ABX8XX_REG_CTRL2 0x11 +#define ABX8XX_CTRL2_RSVD BIT(5) + +#define ABX8XX_REG_IRQ 0x12 +#define ABX8XX_IRQ_AIE BIT(2) +#define ABX8XX_IRQ_IM_1_4 (0x3 << 5) + +#define ABX8XX_REG_CD_TIMER_CTL 0x18 + +#define ABX8XX_REG_OSC 0x1c +#define ABX8XX_OSC_FOS BIT(3) +#define ABX8XX_OSC_BOS BIT(4) +#define ABX8XX_OSC_ACAL_512 BIT(5) +#define ABX8XX_OSC_ACAL_1024 BIT(6) + +#define ABX8XX_OSC_OSEL BIT(7) + +#define ABX8XX_REG_OSS 0x1d +#define ABX8XX_OSS_OF BIT(1) +#define ABX8XX_OSS_OMODE BIT(4) + +#define ABX8XX_REG_WDT 0x1b +#define ABX8XX_WDT_WDS BIT(7) +#define ABX8XX_WDT_BMB_MASK 0x7c +#define ABX8XX_WDT_BMB_SHIFT 2 +#define ABX8XX_WDT_MAX_TIME (ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT) +#define ABX8XX_WDT_WRB_MASK 0x03 +#define ABX8XX_WDT_WRB_1HZ 0x02 + +#define ABX8XX_REG_CFG_KEY 0x1f +#define ABX8XX_CFG_KEY_OSC 0xa1 +#define ABX8XX_CFG_KEY_MISC 0x9d + +#define ABX8XX_REG_ID0 0x28 + +#define ABX8XX_REG_OUT_CTRL 0x30 +#define ABX8XX_OUT_CTRL_EXDS BIT(4) + +#define ABX8XX_REG_TRICKLE 0x20 +#define ABX8XX_TRICKLE_CHARGE_ENABLE 0xa0 +#define ABX8XX_TRICKLE_STANDARD_DIODE 0x8 +#define ABX8XX_TRICKLE_SCHOTTKY_DIODE 0x4 + +static u8 trickle_resistors[] = {0, 3, 6, 11}; + +enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, + AB1801, AB1803, AB1804, AB1805, RV1805, ABX80X}; + +struct abx80x_cap { + u16 pn; + bool has_tc; + bool has_wdog; +}; + +static struct abx80x_cap abx80x_caps[] = { + [AB0801] = {.pn = 0x0801}, + [AB0803] = {.pn = 0x0803}, + [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true}, + [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true}, + [AB1801] = {.pn = 0x1801}, + [AB1803] = {.pn = 0x1803}, + [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true}, + [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, + [RV1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, + [ABX80X] = {.pn = 0} +}; + +static int abx80x_rtc_read8(struct udevice *dev, unsigned int reg) +{ + int ret = 0; + u8 buf; + + if (reg > 0xff) + return -EINVAL; + + ret = dm_i2c_read(dev, reg, &buf, sizeof(buf)); + if (ret < 0) + return ret; + + return buf; +} + +static int abx80x_rtc_write8(struct udevice *dev, unsigned int reg, int val) +{ + u8 buf = (u8)val; + + if (reg > 0xff) + return -EINVAL; + + return dm_i2c_write(dev, reg, &buf, sizeof(buf)); +} + +static int abx80x_is_rc_mode(struct udevice *dev) +{ + int flags = 0; + + flags = dm_i2c_reg_read(dev, ABX8XX_REG_OSS); + if (flags < 0) { + log_err("Failed to read autocalibration attribute\n"); + return flags; + } + + return (flags & ABX8XX_OSS_OMODE) ? 1 : 0; +} + +static int abx80x_enable_trickle_charger(struct udevice *dev, u8 trickle_cfg) +{ + int err; + + /* + * Write the configuration key register to enable access to the Trickle + * register + */ + err = dm_i2c_reg_write(dev, ABX8XX_REG_CFG_KEY, ABX8XX_CFG_KEY_MISC); + if (err < 0) { + log_err("Unable to write configuration key\n"); + return -EIO; + } + + err = dm_i2c_reg_write(dev, ABX8XX_REG_TRICKLE, + ABX8XX_TRICKLE_CHARGE_ENABLE | trickle_cfg); + if (err < 0) { + log_err("Unable to write trickle register\n"); + return -EIO; + } + + return 0; +} + +static int abx80x_rtc_read_time(struct udevice *dev, struct rtc_time *tm) +{ + unsigned char buf[8]; + int err, flags, rc_mode = 0; + + /* Read the Oscillator Failure only in XT mode */ + rc_mode = abx80x_is_rc_mode(dev); + if (rc_mode < 0) + return rc_mode; + + if (!rc_mode) { + flags = dm_i2c_reg_read(dev, ABX8XX_REG_OSS); + if (flags < 0) { + log_err("Unable to read oscillator status.\n"); + return flags; + } + + if (flags & ABX8XX_OSS_OF) + log_debug("Oscillator fail, data is not accurate.\n"); + } + + err = dm_i2c_read(dev, ABX8XX_REG_HTH, + buf, sizeof(buf)); + if (err < 0) { + log_err("Unable to read date\n"); + return -EIO; + } + + tm->tm_sec = bcd2bin(buf[ABX8XX_REG_SC] & 0x7F); + tm->tm_min = bcd2bin(buf[ABX8XX_REG_MN] & 0x7F); + tm->tm_hour = bcd2bin(buf[ABX8XX_REG_HR] & 0x3F); + tm->tm_wday = buf[ABX8XX_REG_WD] & 0x7; + tm->tm_mday = bcd2bin(buf[ABX8XX_REG_DA] & 0x3F); + tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F); + tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 2000; + + return 0; +} + +static int abx80x_rtc_set_time(struct udevice *dev, const struct rtc_time *tm) +{ + unsigned char buf[8]; + int err, flags; + + if (tm->tm_year < 2000) + return -EINVAL; + + buf[ABX8XX_REG_HTH] = 0; + buf[ABX8XX_REG_SC] = bin2bcd(tm->tm_sec); + buf[ABX8XX_REG_MN] = bin2bcd(tm->tm_min); + buf[ABX8XX_REG_HR] = bin2bcd(tm->tm_hour); + buf[ABX8XX_REG_DA] = bin2bcd(tm->tm_mday); + buf[ABX8XX_REG_MO] = bin2bcd(tm->tm_mon); + buf[ABX8XX_REG_YR] = bin2bcd(tm->tm_year - 2000); + buf[ABX8XX_REG_WD] = tm->tm_wday; + + err = dm_i2c_write(dev, ABX8XX_REG_HTH, + buf, sizeof(buf)); + if (err < 0) { + log_err("Unable to write to date registers\n"); + return -EIO; + } + + /* Clear the OF bit of Oscillator Status Register */ + flags = dm_i2c_reg_read(dev, ABX8XX_REG_OSS); + if (flags < 0) { + log_err("Unable to read oscillator status.\n"); + return flags; + } + + err = dm_i2c_reg_write(dev, ABX8XX_REG_OSS, + flags & ~ABX8XX_OSS_OF); + if (err < 0) { + log_err("Unable to write oscillator status register\n"); + return err; + } + + return 0; +} + +static int abx80x_rtc_set_autocalibration(struct udevice *dev, + int autocalibration) +{ + int retval, flags = 0; + + if (autocalibration != 0 && autocalibration != 1024 && + autocalibration != 512) { + log_err("autocalibration value outside permitted range\n"); + return -EINVAL; + } + + flags = dm_i2c_reg_read(dev, ABX8XX_REG_OSC); + if (flags < 0) + return flags; + + if (autocalibration == 0) { + flags &= ~(ABX8XX_OSC_ACAL_512 | ABX8XX_OSC_ACAL_1024); + } else if (autocalibration == 1024) { + /* 1024 autocalibration is 0x10 */ + flags |= ABX8XX_OSC_ACAL_1024; + flags &= ~(ABX8XX_OSC_ACAL_512); + } else { + /* 512 autocalibration is 0x11 */ + flags |= (ABX8XX_OSC_ACAL_1024 | ABX8XX_OSC_ACAL_512); + } + + /* Unlock write access to Oscillator Control Register */ + retval = dm_i2c_reg_write(dev, ABX8XX_REG_CFG_KEY, + ABX8XX_CFG_KEY_OSC); + if (retval < 0) { + log_err("Failed to write CONFIG_KEY register\n"); + return retval; + } + + retval = dm_i2c_reg_write(dev, ABX8XX_REG_OSC, flags); + + return retval; +} + +static int abx80x_rtc_get_autocalibration(struct udevice *dev) +{ + int flags = 0, autocalibration; + + flags = dm_i2c_reg_read(dev, ABX8XX_REG_OSC); + if (flags < 0) + return flags; + + if (flags & ABX8XX_OSC_ACAL_512) + autocalibration = 512; + else if (flags & ABX8XX_OSC_ACAL_1024) + autocalibration = 1024; + else + autocalibration = 0; + + return autocalibration; +} + +static struct rtc_time default_tm = { 0, 0, 0, 1, 1, 2000, 6, 0, 0 }; + +static int abx80x_rtc_reset(struct udevice *dev) +{ + int ret = 0; + + int autocalib = abx80x_rtc_get_autocalibration(dev); + + if (autocalib != 0) + abx80x_rtc_set_autocalibration(dev, 0); + + ret = abx80x_rtc_set_time(dev, &default_tm); + if (ret != 0) { + log_err("cannot set time to default_tm. error %d\n", ret); + return ret; + } + + return ret; +} + +static const struct rtc_ops abx80x_rtc_ops = { + .get = abx80x_rtc_read_time, + .set = abx80x_rtc_set_time, + .reset = abx80x_rtc_reset, + .read8 = abx80x_rtc_read8, + .write8 = abx80x_rtc_write8 +}; + +static int abx80x_dt_trickle_cfg(struct udevice *dev) +{ + const char *diode; + int trickle_cfg = 0; + int i, ret = 0; + u32 tmp; + + diode = ofnode_read_string(dev_ofnode(dev), "abracon,tc-diode"); + if (!diode) + return ret; + + if (!strcmp(diode, "standard")) { + trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE; + } else if (!strcmp(diode, "schottky")) { + trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE; + } else { + log_err("Invalid tc-diode value: %s\n", diode); + return -EINVAL; + } + + ret = ofnode_read_u32(dev_ofnode(dev), "abracon,tc-resistor", &tmp); + if (ret) + return ret; + + for (i = 0; i < sizeof(trickle_resistors); i++) + if (trickle_resistors[i] == tmp) + break; + + if (i == sizeof(trickle_resistors)) { + log_err("Invalid tc-resistor value: %u\n", tmp); + return -EINVAL; + } + + return (trickle_cfg | i); +} + +static int abx80x_probe(struct udevice *dev) +{ + int i, data, err, trickle_cfg = -EINVAL; + unsigned char buf[7]; + unsigned int part = dev->driver_data; + unsigned int partnumber; + unsigned int majrev, minrev; + unsigned int lot; + unsigned int wafer; + unsigned int uid; + + err = dm_i2c_read(dev, ABX8XX_REG_ID0, buf, sizeof(buf)); + if (err < 0) { + log_err("Unable to read partnumber\n"); + return -EIO; + } + + partnumber = (buf[0] << 8) | buf[1]; + majrev = buf[2] >> 3; + minrev = buf[2] & 0x7; + lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3]; + uid = ((buf[4] & 0x7f) << 8) | buf[5]; + wafer = (buf[6] & 0x7c) >> 2; + log_debug("model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n", + partnumber, majrev, minrev, lot, wafer, uid); + + data = dm_i2c_reg_read(dev, ABX8XX_REG_CTRL1); + if (data < 0) { + log_err("Unable to read control register\n"); + return -EIO; + } + + err = dm_i2c_reg_write(dev, ABX8XX_REG_CTRL1, + ((data & ~(ABX8XX_CTRL_12_24 | + ABX8XX_CTRL_ARST)) | + ABX8XX_CTRL_WRITE)); + if (err < 0) { + log_err("Unable to write control register\n"); + return -EIO; + } + + /* Configure RV1805 specifics */ + if (part == RV1805) { + /* + * Avoid accidentally entering test mode. This can happen + * on the RV1805 in case the reserved bit 5 in control2 + * register is set. RV-1805-C3 datasheet indicates that + * the bit should be cleared in section 11h - Control2. + */ + data = dm_i2c_reg_read(dev, ABX8XX_REG_CTRL2); + if (data < 0) { + log_err("Unable to read control2 register\n"); + return -EIO; + } + + err = dm_i2c_reg_write(dev, ABX8XX_REG_CTRL2, + data & ~ABX8XX_CTRL2_RSVD); + if (err < 0) { + log_err("Unable to write control2 register\n"); + return -EIO; + } + + /* + * Avoid extra power leakage. The RV1805 uses smaller + * 10pin package and the EXTI input is not present. + * Disable it to avoid leakage. + */ + data = dm_i2c_reg_read(dev, ABX8XX_REG_OUT_CTRL); + if (data < 0) { + log_err("Unable to read output control register\n"); + return -EIO; + } + + /* + * Write the configuration key register to enable access to + * the config2 register + */ + err = dm_i2c_reg_write(dev, ABX8XX_REG_CFG_KEY, + ABX8XX_CFG_KEY_MISC); + if (err < 0) { + log_err("Unable to write configuration key\n"); + return -EIO; + } + + err = dm_i2c_reg_write(dev, ABX8XX_REG_OUT_CTRL, + data | ABX8XX_OUT_CTRL_EXDS); + if (err < 0) { + log_err("Unable to write output control register\n"); + return -EIO; + } + } + + /* part autodetection */ + if (part == ABX80X) { + for (i = 0; abx80x_caps[i].pn; i++) + if (partnumber == abx80x_caps[i].pn) + break; + if (abx80x_caps[i].pn == 0) { + log_err("Unknown part: %04x\n", partnumber); + return -EINVAL; + } + part = i; + } + + if (partnumber != abx80x_caps[part].pn) { + log_err("partnumber mismatch %04x != %04x\n", + partnumber, abx80x_caps[part].pn); + return -EINVAL; + } + + if (abx80x_caps[part].has_tc) + trickle_cfg = abx80x_dt_trickle_cfg(dev); + + if (trickle_cfg > 0) { + log_debug("Enabling trickle charger: %02x\n", trickle_cfg); + abx80x_enable_trickle_charger(dev, trickle_cfg); + } + + err = dm_i2c_reg_write(dev, ABX8XX_REG_CD_TIMER_CTL, BIT(2)); + if (err) + return err; + + return 0; +} + +static const struct udevice_id abx80x_of_match[] = { + { + .compatible = "abracon,abx80x", + .data = ABX80X + }, + { + .compatible = "abracon,ab0801", + .data = AB0801 + }, + { + .compatible = "abracon,ab0803", + .data = AB0803 + }, + { + .compatible = "abracon,ab0804", + .data = AB0804 + }, + { + .compatible = "abracon,ab0805", + .data = AB0805 + }, + { + .compatible = "abracon,ab1801", + .data = AB1801 + }, + { + .compatible = "abracon,ab1803", + .data = AB1803 + }, + { + .compatible = "abracon,ab1804", + .data = AB1804 + }, + { + .compatible = "abracon,ab1805", + .data = AB1805 + }, + { + .compatible = "microcrystal,rv1805", + .data = RV1805 + }, + { } +}; + +U_BOOT_DRIVER(abx80x_rtc) = { + .name = "rtc-abx80x", + .id = UCLASS_RTC, + .probe = abx80x_probe, + .of_match = abx80x_of_match, + .ops = &abx80x_rtc_ops, +}; From e89ef172f88118ce036eb46d660f857c9209b194 Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Fri, 15 Jan 2021 13:53:03 +0800 Subject: [PATCH 23/24] doc: device-tree-bindings: rtc: Abracon AB x80x i2c rtc Document the bindings for abracon,abx80x and related compatibles. Signed-off-by: Ying-Chun Liu (PaulLiu) --- .../rtc/abracon,abx80x.txt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 doc/device-tree-bindings/rtc/abracon,abx80x.txt diff --git a/doc/device-tree-bindings/rtc/abracon,abx80x.txt b/doc/device-tree-bindings/rtc/abracon,abx80x.txt new file mode 100644 index 0000000000..2405e35a1b --- /dev/null +++ b/doc/device-tree-bindings/rtc/abracon,abx80x.txt @@ -0,0 +1,31 @@ +Abracon ABX80X I2C ultra low power RTC/Alarm chip + +The Abracon ABX80X family consist of the ab0801, ab0803, ab0804, ab0805, ab1801, +ab1803, ab1804 and ab1805. The ab0805 is the superset of ab080x and the ab1805 +is the superset of ab180x. + +Required properties: + + - "compatible": should one of: + "abracon,abx80x" + "abracon,ab0801" + "abracon,ab0803" + "abracon,ab0804" + "abracon,ab0805" + "abracon,ab1801" + "abracon,ab1803" + "abracon,ab1804" + "abracon,ab1805" + "microcrystal,rv1805" + Using "abracon,abx80x" will enable chip autodetection. + - "reg": I2C bus address of the device + +Optional properties: + +The abx804 and abx805 have a trickle charger that is able to charge the +connected battery or supercap. Both the following properties have to be defined +and valid to enable charging: + + - "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V) + - "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output + resistor, the other values are in kOhm. From 54f884bb0b1ebc16946890bb8349fe0ca2455bb2 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 22 Jan 2021 12:27:31 +0100 Subject: [PATCH 24/24] cmd: misc: Fix return value for the sleep command If sleeping has been interrupted, return CMD_RET_FAILURE instead of -1 (CMD_RET_USAGE). Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass Reviewed-by: Jaehoon Chung --- cmd/sleep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/sleep.c b/cmd/sleep.c index f0c78a8efb..1fff400c79 100644 --- a/cmd/sleep.c +++ b/cmd/sleep.c @@ -40,7 +40,7 @@ static int do_sleep(struct cmd_tbl *cmdtp, int flag, int argc, while (get_timer(start) < delay) { if (ctrlc()) - return (-1); + return CMD_RET_FAILURE; udelay(100); }