From f7d367c2e66ec550976818b8297416f2e4e299ce Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Sun, 25 Sep 2022 15:28:47 +0200 Subject: [PATCH 01/22] dm: doc: Fix serial howto u-boot,dm-pre-reloc typo In a couple of places the document says u-boot,pre-reloc but all examples show u-boot,dm-pre-reloc, use the latter consistently. Signed-off-by: Michal Suchanek Reviewed-by: Fabio Estevam Reviewed-by: Simon Glass --- doc/develop/driver-model/serial-howto.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/develop/driver-model/serial-howto.rst b/doc/develop/driver-model/serial-howto.rst index 9da0e57eab6..5b1d57d83a8 100644 --- a/doc/develop/driver-model/serial-howto.rst +++ b/doc/develop/driver-model/serial-howto.rst @@ -62,7 +62,7 @@ what you need. U-Boot automatically includes these files: see :ref:`dttweaks`. Here are some things you might need to consider: 1. The serial driver itself needs to be present before relocation, so that the - U-Boot banner appears. Make sure it has a u-boot,pre-reloc tag in the device + U-Boot banner appears. Make sure it has a u-boot,dm-pre-reloc tag in the device tree, so that the serial driver is bound when U-Boot starts. For example, on iMX8:: @@ -79,7 +79,7 @@ Here are some things you might need to consider: }; 2. If your serial port requires a particular pinmux configuration, you may need - a pinctrl driver. This needs to have a u-boot,pre-reloc tag also. Take care + a pinctrl driver. This needs to have a u-boot,dm-pre-reloc tag also. Take care that any subnodes have the same tag, if they are needed to make the correct pinctrl available. From d7e9de7ec1bb79261c08e7689a1856a464ee2443 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Tue, 27 Sep 2022 10:18:05 +0200 Subject: [PATCH 02/22] fdt_support: cosmetic: remove fdt_fixup_nor_flash_size prototype Remove prototype for the removed function fdt_fixup_nor_flash_size. This patch has no impact as the function is never used. Fixes: 98f705c9cefd ("powerpc: remove 4xx support") Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- include/fdt_support.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/fdt_support.h b/include/fdt_support.h index b8380716f39..5638bd4f165 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -243,8 +243,6 @@ int fdt_increase_size(void *fdt, int add_len); int fdt_delete_disabled_nodes(void *blob); -int fdt_fixup_nor_flash_size(void *blob); - struct node_info; #if defined(CONFIG_FDT_FIXUP_PARTITIONS) void fdt_fixup_mtdparts(void *fdt, const struct node_info *node_info, From 1fcfadcb82a21af058baa5dea2b20883b8c388b8 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Tue, 27 Sep 2022 23:25:24 +0200 Subject: [PATCH 03/22] dm: pci: Fix doc typo first -> next pci_find_first_device description says it can be used for iteration with itself but it should really be with pci_find_next_device Signed-off-by: Michal Suchanek --- include/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pci.h b/include/pci.h index d7ed35dd523..c55d6107a49 100644 --- a/include/pci.h +++ b/include/pci.h @@ -957,7 +957,7 @@ int pci_bus_find_devfn(const struct udevice *bus, pci_dev_t find_devfn, /** * pci_find_first_device() - return the first available PCI device * - * This function and pci_find_first_device() allow iteration through all + * This function and pci_find_next_device() allow iteration through all * available PCI devices on all buses. Assuming there are any, this will * return the first one. * From fc872ee84cd5dd3a74bf51ce6519377b0de4940f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 1 Oct 2022 15:00:21 +0200 Subject: [PATCH 04/22] x86: fix longjmp() implementation If longjmp(jmp_buf env, int val) is called with val = 0, the setjmp() macro must return 1. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- arch/x86/cpu/i386/setjmp.S | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/cpu/i386/setjmp.S b/arch/x86/cpu/i386/setjmp.S index 40b10dc8df1..eceeafa7c8b 100644 --- a/arch/x86/cpu/i386/setjmp.S +++ b/arch/x86/cpu/i386/setjmp.S @@ -49,12 +49,17 @@ longjmp: xchgl %eax, %edx #else movl 4(%esp), %edx /* jmp_ptr address */ + movl 8(%esp), %eax /* Return value */ #endif movl (%edx), %ebx movl 4(%edx), %esp movl 8(%edx), %ebp movl 12(%edx), %esi movl 16(%edx), %edi + test %eax, %eax + jnz nz + inc %eax +nz: jmp *20(%edx) .size longjmp, .-longjmp From 95e7cafa8171397b5ef5d15ec4eac29ffa6fbe87 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 1 Oct 2022 15:00:22 +0200 Subject: [PATCH 05/22] x86: provide typedef jmp_buf The jmp_buf type is required by the C99 specification. Defining it for x86 fixes building the longjmp unit test. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- arch/x86/include/asm/setjmp.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h index 49c36c1cc88..15915d0dc6b 100644 --- a/arch/x86/include/asm/setjmp.h +++ b/arch/x86/include/asm/setjmp.h @@ -34,7 +34,9 @@ struct jmp_buf_data { #endif -int setjmp(struct jmp_buf_data *jmp_buf); -void longjmp(struct jmp_buf_data *jmp_buf, int val); +typedef struct jmp_buf_data jmp_buf[1]; + +int setjmp(jmp_buf env); +void longjmp(jmp_buf env, int val); #endif From 10e66449d7e8a6aaee69b9fd130a3f04ea7b6f57 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 3 Oct 2022 11:02:45 +0200 Subject: [PATCH 06/22] gpio-uclass: fix gpio lookup by label Matching anything that just happens to have the sought-for label as a prefix is wrong. For example, if the board designer has designated 10 lines for debug purposes, named "debug1" through "debug10", and we are looking up "debug1", if debug10 happens to be met first during the iteration we'd wrongly return that. In theory, this can break existing users that could rely on this quirk, but OTOH keeping the current broken semantics can cause a lot of grief for people hitting this in the future and not understanding why they don't find the line they expect. Considering how few in-tree defconfigs currently set DM_GPIO_LOOKUP_LABEL (ignoring sandbox, only four "real" boards), let's fix it before the use becomes more widespread. Signed-off-by: Rasmus Villemoes Reviewed-by: Simon Glass Reviewed-by: Heiko Schocher --- drivers/gpio/gpio-uclass.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index a00880e446c..65033258f47 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -91,15 +91,13 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) static int dm_gpio_lookup_label(const char *name, struct gpio_dev_priv *uc_priv, ulong *offset) { - int len; int i; *offset = -1; - len = strlen(name); for (i = 0; i < uc_priv->gpio_count; i++) { if (!uc_priv->name[i]) continue; - if (!strncmp(name, uc_priv->name[i], len)) { + if (!strcmp(name, uc_priv->name[i])) { *offset = i; return 0; } From d13879211285d5cc5cfb727eb36b41da0111edf0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 8 Oct 2022 21:33:20 -0600 Subject: [PATCH 07/22] dm: core: Fix lists_bind_fdt() using non-existent of_match The call to device_bind_with_driver_data() passes id->data but if the entry has no of_match then the id has not been set by the selected driver. Normally this passes unnoticed since a previous driver likely had an of_match value, so the id is set to that. Of course it is not correct to pass the id->data from a different driver. With clang-14 the driver ordering is such that the id is never actually set in the 'bind /usb@1 usb_ether' line in test_bind_unbind_with_node() thus causing a crash. Fix this by passing 0 if the of_match for a driver does not exist. Signed-off-by: Simon Glass --- drivers/core/lists.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/core/lists.c b/drivers/core/lists.c index c49695b24f0..3878957c9ef 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -222,6 +222,7 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, log_debug(" - attempt to match compatible string '%s'\n", compat); + id = NULL; for (entry = driver; entry != driver + n_ents; entry++) { if (drv) { if (drv != entry) @@ -250,7 +251,8 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, entry->name, entry->of_match->compatible, id->compatible); ret = device_bind_with_driver_data(parent, entry, name, - id->data, node, &dev); + id ? id->data : 0, node, + &dev); if (ret == -ENODEV) { log_debug("Driver '%s' refuses to bind\n", entry->name); continue; From 5fe72d968f6c388b41202c54c563815f2db977fc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 8 Oct 2022 21:33:21 -0600 Subject: [PATCH 08/22] event: Drop the path when checking event-list filenames This path does not seem to be present in clang-14 for some reason. Relax the regular expression so that the test works, at least for non-LTO. Signed-off-by: Simon Glass --- test/py/tests/test_event_dump.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py index e63c25df537..674df2ea001 100644 --- a/test/py/tests/test_event_dump.py +++ b/test/py/tests/test_event_dump.py @@ -16,7 +16,7 @@ def test_event_dump(u_boot_console): out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox]) expect = '''.*Event type Id Source location -------------------- ------------------------------ ------------------------------ -EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*boot/vbe_fixup.c:.* -EVT_FT_FIXUP bootmeth_vbe_simple_ft_fixup .*boot/vbe_simple.c:.* -EVT_MISC_INIT_F sandbox_misc_init_f .*arch/sandbox/cpu/start.c:''' +EVT_FT_FIXUP bootmeth_vbe_ft_fixup .*vbe_fixup.c:.* +EVT_FT_FIXUP bootmeth_vbe_simple_ft_fixup .*vbe_simple.c:.* +EVT_MISC_INIT_F sandbox_misc_init_f .*start.c:''' assert re.match(expect, out, re.MULTILINE) is not None From 7e8d3e1b016faa50cbd1c0ef8ff3d12014ab2e7a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 8 Oct 2022 21:33:22 -0600 Subject: [PATCH 09/22] test: Drop unwanted option in event_dump.py This option is not used. Drop it. Signed-off-by: Simon Glass --- scripts/event_dump.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/event_dump.py b/scripts/event_dump.py index 6aadddf28da..d87823f3749 100755 --- a/scripts/event_dump.py +++ b/scripts/event_dump.py @@ -108,8 +108,6 @@ def main(argv): parser.add_argument('elf', type=str, help='ELF file to decode') parser.add_argument('-e', '--endian', type=str, default='auto', help='Big-endian image') - parser.add_argument('-t', '--test', action='store_true', - help='Big-endian image') args = parser.parse_args(argv) show_event_spy_list(args.elf, args.endian) From c977b184350479b8c43a0e002eaf2b13b510ba4f Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Thu, 13 Oct 2022 22:39:51 +0200 Subject: [PATCH 10/22] libfdt: Fix invalid version warning python does not like the u-boot- prefix in the version, drop it. /usr/lib/python3.10/site-packages/setuptools/dist.py:544: UserWarning: The version specified ('u-boot-2022.10') is an invalid version, this may not work as expected with newer versions of setuptools, pip, and PyPI. Please see PEP 440 for more details. Signed-off-by: Michal Suchanek Reviewed-by: Simon Glass --- scripts/dtc/pylibfdt/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile index 493995e3038..a7579f0c5f6 100644 --- a/scripts/dtc/pylibfdt/Makefile +++ b/scripts/dtc/pylibfdt/Makefile @@ -17,7 +17,7 @@ quiet_cmd_pymod = PYMOD $@ cmd_pymod = unset CROSS_COMPILE; unset CFLAGS; \ CC="$(HOSTCC)" LDSHARED="$(HOSTCC) -shared " \ LDFLAGS="$(HOSTLDFLAGS)" \ - VERSION="u-boot-$(UBOOTVERSION)" \ + VERSION="$(UBOOTVERSION)" \ CPPFLAGS="$(HOSTCFLAGS) -I$(LIBFDT_srcdir)" OBJDIR=$(obj) \ SOURCES="$(PYLIBFDT_srcs)" \ SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \ From 7d01bb1c5a1daef0187c9ea276bde19a8d0e7fde Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Thu, 13 Oct 2022 22:43:41 +0200 Subject: [PATCH 11/22] libfdt: Fix build with python 3.10 Python 3.10 requires defining PY_SSIZE_T_CLEAN. This will be fixed in swig 4.10 but it is not clear when it will be released. There was a warning since python 3.8. Link: https://github.com/swig/swig/pull/2277 Signed-off-by: Michal Suchanek Reviewed-by: Simon Glass --- scripts/dtc/pylibfdt/libfdt.i_shipped | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/dtc/pylibfdt/libfdt.i_shipped b/scripts/dtc/pylibfdt/libfdt.i_shipped index 27c29ea2603..56cc5d48f4f 100644 --- a/scripts/dtc/pylibfdt/libfdt.i_shipped +++ b/scripts/dtc/pylibfdt/libfdt.i_shipped @@ -7,6 +7,10 @@ %module libfdt +%begin %{ +#define PY_SSIZE_T_CLEAN +%} + %include %{ From 6792bd999b03bef74fc0762510f8a98eebb8c161 Mon Sep 17 00:00:00 2001 From: William Zhang Date: Fri, 14 Oct 2022 11:04:55 -0700 Subject: [PATCH 12/22] dm: tpl: Add fdt address translation support in TPL This is needed in the platforms that use "ranges" node property for address translation in their dts for TPL. Signed-off-by: William Zhang Reviewed-by: Simon Glass --- drivers/core/Kconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 0dc442b921c..b79e99b63de 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -350,6 +350,20 @@ config SPL_OF_TRANSLATE used for the address translation. This function is faster and smaller in size than fdt_translate_address(). +config TPL_OF_TRANSLATE + bool "Translate addresses using fdt_translate_address in TPL" + depends on TPL_DM && TPL_OF_CONTROL + help + If this option is enabled, the reg property will be translated + using the fdt_translate_address() function. This is necessary + on some platforms (e.g. MVEBU) using complex "ranges" + properties in many nodes. As this translation is not handled + correctly in the default simple_bus_translate() function. + + If this option is not enabled, simple_bus_translate() will be + used for the address translation. This function is faster and + smaller in size than fdt_translate_address() + config VPL_OF_TRANSLATE bool "Translate addresses using fdt_translate_address in SPL" depends on SPL_DM && VPL_OF_CONTROL From 5bde2e06caba0f072d0d3788fafcedafd11ae28a Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Fri, 14 Oct 2022 22:52:33 +0200 Subject: [PATCH 13/22] tests: Build correct sandbox configuration on 32bit Currently sandbox configuration defautls to 64bit and there is no automation for building 32bit sandbox on 32bit hosts. Use _LP64 macro as heuristic for detecting 64bit targets. Signed-off-by: Michal Suchanek Reviewed-by: Simon Glass --- arch/sandbox/Kconfig | 18 +++--------------- scripts/Kconfig.include | 4 ++++ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 852a7c8bf2c..35508c6b292 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -13,7 +13,7 @@ config SYS_CPU config SANDBOX64 bool "Use 64-bit addresses" select PHYS_64BIT - select HOST_64BIT + depends on HOST_64BIT config SANDBOX_RAM_SIZE_MB int "RAM size in MiB" @@ -41,23 +41,11 @@ config SYS_CONFIG_NAME default "sandbox_spl" if SANDBOX_SPL default "sandbox" if !SANDBOX_SPL -choice - prompt "Run sandbox on 32/64-bit host" - default HOST_64BIT - help - Sandbox can be built on 32-bit and 64-bit hosts. - The default is to build on a 64-bit host and run - on a 64-bit host. If you want to run sandbox on - a 32-bit host, change it here. - config HOST_32BIT - bool "32-bit host" - depends on !PHYS_64BIT + def_bool ! $(cc-define,_LP64) config HOST_64BIT - bool "64-bit host" - -endchoice + def_bool $(cc-define,_LP64) config SANDBOX_CRASH_RESET bool "Reset on crash" diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index dad5583451a..b7598ca5d9f 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -22,6 +22,10 @@ success = $(if-success,$(1),y,n) # Return y if the compiler supports , n otherwise cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null) +# $(cc-define,) +# Return y if the compiler defines , n otherwise +cc-define = $(success,$(CC) -dM -E -x c /dev/null | grep -q '^#define \<$(1)\>') + # $(ld-option,) # Return y if the linker supports , n otherwise ld-option = $(success,$(LD) -v $(1)) From f29f98d1e40e6b4d9c723af503b20948aa482bf2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Oct 2022 22:17:46 +0200 Subject: [PATCH 14/22] sandbox: typo Fictionnal %s/Fictionnal/Fictional/ Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- board/sandbox/sandbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index ca9a2ca5b17..38cfa0832d7 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -129,7 +129,7 @@ int extension_board_scan(struct list_head *extension_list) snprintf(extension->name, sizeof(extension->name), "extension board %d", i); snprintf(extension->owner, sizeof(extension->owner), "sandbox"); snprintf(extension->version, sizeof(extension->version), "1.1"); - snprintf(extension->other, sizeof(extension->other), "Fictionnal extension board"); + snprintf(extension->other, sizeof(extension->other), "Fictional extension board"); list_add_tail(&extension->list, extension_list); } From 3545e8595c944c893bc3fa64c8e4727c928cf892 Mon Sep 17 00:00:00 2001 From: Neha Malcom Francis Date: Mon, 17 Oct 2022 16:36:25 +0530 Subject: [PATCH 15/22] binman: Add support for symlinking images Adding support to symlink an image packaged using binman. Signed-off-by: Neha Malcom Francis Reviewed-by: Simon Glass --- tools/binman/binman.rst | 3 +++ tools/binman/ftest.py | 9 +++++++++ tools/binman/image.py | 6 ++++++ tools/binman/test/259_symlink.dts | 16 ++++++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 tools/binman/test/259_symlink.dts diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst index 4ee6f41f35e..d8a3d776f46 100644 --- a/tools/binman/binman.rst +++ b/tools/binman/binman.rst @@ -780,6 +780,9 @@ align-default: This means that each section must specify its own default alignment, if required. +symlink: + Adds a symlink to the image with string given in the symlink property. + Examples of the above options can be found in the tests. See the tools/binman/test directory. diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 261107b3354..232ac2cf185 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -5995,6 +5995,15 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self.assertIn('Expected __bss_size symbol in vpl/u-boot-vpl', str(e.exception)) + def testSymlink(self): + """Test that image files can be named""" + retcode = self._DoTestFile('259_symlink.dts', debug=True, map=True) + self.assertEqual(0, retcode) + image = control.images['test_image'] + fname = tools.get_output_filename('test_image.bin') + sname = tools.get_output_filename('symlink_to_test.bin') + self.assertTrue(os.path.islink(sname)) + self.assertEqual(os.readlink(sname), fname) if __name__ == "__main__": unittest.main() diff --git a/tools/binman/image.py b/tools/binman/image.py index afc4b4d6430..6d4bff58436 100644 --- a/tools/binman/image.py +++ b/tools/binman/image.py @@ -38,6 +38,7 @@ class Image(section.Entry_section): repacked later test_section_timeout: Use a zero timeout for section multi-threading (for testing) + symlink: Name of symlink to image Args: copy_to_orig: Copy offset/size to orig_offset/orig_size after reading @@ -97,6 +98,7 @@ class Image(section.Entry_section): if filename: self._filename = filename self.allow_repack = fdt_util.GetBool(self._node, 'allow-repack') + self._symlink = fdt_util.GetString(self._node, 'symlink') @classmethod def FromFile(cls, fname): @@ -180,6 +182,10 @@ class Image(section.Entry_section): data = self.GetPaddedData() fd.write(data) tout.info("Wrote %#x bytes" % len(data)) + # Create symlink to file if symlink given + if self._symlink is not None: + sname = tools.get_output_filename(self._symlink) + os.symlink(fname, sname) def WriteMap(self): """Write a map of the image to a .map file diff --git a/tools/binman/test/259_symlink.dts b/tools/binman/test/259_symlink.dts new file mode 100644 index 00000000000..2ee1f7f05e2 --- /dev/null +++ b/tools/binman/test/259_symlink.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + multiple-images; + test_image { + filename = "test_image.bin"; + symlink = "symlink_to_test.bin"; + u-boot { + }; + }; + }; +}; From 529b2c2d9c757b3ed7d898c90ab7611f1b0c9d0f Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Tue, 18 Oct 2022 14:17:25 +0530 Subject: [PATCH 16/22] thermal: sandbox: Enable thermal uclass for sandbox64 variant The sandbox64 variant is currently building the sandbox thermal driver but not the corresponding uclass driver. This results in the sandbox64 variant not booting with the test device tree. Enable building the thermal uclass for the sandbox64 variant as well. Also enable the temperature command to allow the test to be run on the sandbox64 variant. Signed-off-by: Sughosh Ganu Reviewed-by: Simon Glass --- configs/sandbox64_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 04756729682..e28f1e8cf96 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -54,6 +54,7 @@ CONFIG_CMD_PCI=y CONFIG_CMD_READ=y CONFIG_CMD_REMOTEPROC=y CONFIG_CMD_SPI=y +CONFIG_CMD_TEMPERATURE=y CONFIG_CMD_USB=y CONFIG_CMD_CAT=y CONFIG_CMD_WDT=y @@ -220,6 +221,7 @@ CONFIG_SYSINFO=y CONFIG_SYSINFO_SANDBOX=y CONFIG_SYSINFO_GPIO=y CONFIG_SYSRESET=y +CONFIG_DM_THERMAL=y CONFIG_TIMER=y CONFIG_TIMER_EARLY=y CONFIG_SANDBOX_TIMER=y From 6b08fb5cc44f8d32260a17a4f04c5bfa8dd5f18f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 30 Jul 2022 20:57:11 -0600 Subject: [PATCH 17/22] fdt: Move to setuptools The distutils package is deprecated. The upstream libfdt repo uses setuptools for building the pylibfdt module, so bring in that code, suitably modified for U-Boot. Also bring in the README. The modifications include setting the version correctly, making use of the environment variables provided by the Makefile and various tweaks to the directories. Note that the version omits the minus character at the start of EXTRAVERSION, since this creates a warning. The build is really just used within U-Boot itself, so it doesn't matter too much if the version matches upstream, or exactly matches U-Boot. Signed-off-by: Simon Glass --- scripts/dtc/README | 106 ++++++++++++++++++++++++++++++++++ scripts/dtc/pylibfdt/Makefile | 5 +- scripts/dtc/pylibfdt/setup.py | 57 +++++++++++++++--- 3 files changed, 158 insertions(+), 10 deletions(-) create mode 100644 scripts/dtc/README diff --git a/scripts/dtc/README b/scripts/dtc/README new file mode 100644 index 00000000000..a48312a422c --- /dev/null +++ b/scripts/dtc/README @@ -0,0 +1,106 @@ +The source tree contains the Device Tree Compiler (dtc) toolchain for +working with device tree source and binary files and also libfdt, a +utility library for reading and manipulating the binary format. + +DTC and LIBFDT are maintained by: + +David Gibson +Jon Loeliger + + +Python library +-------------- + +A Python library is also available. To build this you will need to install +swig and Python development files. On Debian distributions: + + sudo apt-get install swig python3-dev + +The library provides an Fdt class which you can use like this: + +$ PYTHONPATH=../pylibfdt python3 +>>> import libfdt +>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read()) +>>> node = fdt.path_offset('/subnode@1') +>>> print(node) +124 +>>> prop_offset = fdt.first_property_offset(node) +>>> prop = fdt.get_property_by_offset(prop_offset) +>>> print('%s=%s' % (prop.name, prop.as_str())) +compatible=subnode1 +>>> node2 = fdt.path_offset('/') +>>> print(fdt.getprop(node2, 'compatible').as_str()) +test_tree1 + +You will find tests in tests/pylibfdt_tests.py showing how to use each +method. Help is available using the Python help command, e.g.: + + $ cd pylibfdt + $ python3 -c "import libfdt; help(libfdt)" + +If you add new features, please check code coverage: + + $ sudo apt-get install python3-coverage + $ cd tests + # It's just 'coverage' on most other distributions + $ python3-coverage run pylibfdt_tests.py + $ python3-coverage html + # Open 'htmlcov/index.html' in your browser + + +The library can be installed with pip from a local source tree: + + pip install . [--user|--prefix=/path/to/install_dir] + +Or directly from a remote git repo: + + pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main + +The install depends on libfdt shared library being installed on the host system +first. Generally, using --user or --prefix is not necessary and pip will use the +default location for the Python installation which varies if the user is root or +not. + +You can also install everything via make if you like, but pip is recommended. + +To install both libfdt and pylibfdt you can use: + + make install [PREFIX=/path/to/install_dir] + +To disable building the python library, even if swig and Python are available, +use: + + make NO_PYTHON=1 + + +More work remains to support all of libfdt, including access to numeric +values. + + +Adding a new function to libfdt.h +--------------------------------- + +The shared library uses libfdt/version.lds to list the exported functions, so +add your new function there. Check that your function works with pylibfdt. If +it cannot be supported, put the declaration in libfdt.h behind #ifndef SWIG so +that swig ignores it. + + +Tests +----- + +Test files are kept in the tests/ directory. Use 'make check' to build and run +all tests. + +If you want to adjust a test file, be aware that tree_tree1.dts is compiled +and checked against a binary tree from assembler macros in trees.S. So +if you change that file you must change tree.S also. + + +Mailing list +------------ +The following list is for discussion about dtc and libfdt implementation +mailto:devicetree-compiler@vger.kernel.org + +Core device tree bindings are discussed on the devicetree-spec list: +mailto:devicetree-spec@vger.kernel.org diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile index a7579f0c5f6..e442d5c2420 100644 --- a/scripts/dtc/pylibfdt/Makefile +++ b/scripts/dtc/pylibfdt/Makefile @@ -13,11 +13,14 @@ include $(LIBFDT_srcdir)/Makefile.libfdt PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \ $(obj)/libfdt.i +# create a version string compliant with PEP 440 +PEP_VERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(subst -,,$(EXTRAVERSION)) + quiet_cmd_pymod = PYMOD $@ cmd_pymod = unset CROSS_COMPILE; unset CFLAGS; \ CC="$(HOSTCC)" LDSHARED="$(HOSTCC) -shared " \ LDFLAGS="$(HOSTLDFLAGS)" \ - VERSION="$(UBOOTVERSION)" \ + VERSION="$(PEP_VERSION)" \ CPPFLAGS="$(HOSTCFLAGS) -I$(LIBFDT_srcdir)" OBJDIR=$(obj) \ SOURCES="$(PYLIBFDT_srcs)" \ SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \ diff --git a/scripts/dtc/pylibfdt/setup.py b/scripts/dtc/pylibfdt/setup.py index 992cdec30f5..ec1fc5002b0 100755 --- a/scripts/dtc/pylibfdt/setup.py +++ b/scripts/dtc/pylibfdt/setup.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) """ setup.py file for SWIG libfdt Copyright (C) 2017 Google, Inc. Written by Simon Glass -SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause +This script is modified from the upstream version, to fit in with the U-Boot +build system. Files to be built into the extension are provided in SOURCES C flags to use are provided in CPPFLAGS @@ -18,14 +20,29 @@ allows this script to be run stand-alone, e.g.: ./pylibfdt/setup.py install [--prefix=...] """ -from distutils.core import setup, Extension +from setuptools import setup, Extension +from setuptools.command.build_py import build_py as _build_py import os import re import sys +srcdir = os.path.dirname(__file__) + +with open(os.path.join(srcdir, "../README"), "r") as fh: + long_description = fh.read() + # Decodes a Makefile assignment line into key and value (and plus for +=) RE_KEY_VALUE = re.compile('(?P\w+) *(?P[+])?= *(?P.*)$') +def get_top_builddir(): + if '--top-builddir' in sys.argv: + index = sys.argv.index('--top-builddir') + sys.argv.pop(index) + return sys.argv.pop(index) + else: + return os.path.join(srcdir, '..') + +top_builddir = get_top_builddir() def ParseMakefile(fname): """Parse a Makefile to obtain its variables. @@ -86,7 +103,7 @@ def GetEnvFromMakefiles(): makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt')) files = makevars['LIBFDT_SRCS'].split() files = [os.path.join(basedir, 'libfdt', fname) for fname in files] - files.append('pylibfdt/libfdt.i') + files.append('libfdt.i') cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir] objdir = '' return swig_opts, version, files, cflags, objdir @@ -107,17 +124,39 @@ if not all((swig_opts, version, files, cflags, objdir)): libfdt_module = Extension( '_libfdt', - sources = files, - extra_compile_args = cflags, - swig_opts = swig_opts, + sources=files, + include_dirs=[os.path.join(srcdir, 'libfdt')], + library_dirs=[os.path.join(top_builddir, 'libfdt')], + swig_opts=swig_opts, ) +class build_py(_build_py): + def run(self): + self.run_command("build_ext") + return super().run() + setup( name='libfdt', - version= version, - author='Simon Glass ', + version=version, + cmdclass = {'build_py' : build_py}, + author='Simon Glass', + author_email='sjg@chromium.org', description='Python binding for libfdt', ext_modules=[libfdt_module], package_dir={'': objdir}, - py_modules=['pylibfdt/libfdt'], + py_modules=['libfdt'], + + long_description=long_description, + long_description_content_type="text/plain", + url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", + license="BSD", + license_files=["GPL", "BSD-2-Clause"], + + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: BSD License", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", + "Operating System :: OS Independent", + ], + ) From 58ddb937e1699de241e4aa39de90a68a0be71744 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Sun, 25 Sep 2022 13:08:16 +0200 Subject: [PATCH 18/22] dm: core: Switch uclass_*_device_err to use uclass_*_device_check Clarify documentation, fix a few more cases that could be broken by the change. Signed-off-by: Michal Suchanek --- drivers/pci/pci-uclass.c | 7 +++---- drivers/sysinfo/sysinfo-uclass.c | 10 +++++++++- include/dm/uclass.h | 12 ++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 5cff81ac443..6dd19650f9c 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -1777,10 +1777,9 @@ int pci_sriov_init(struct udevice *pdev, int vf_en) bdf = dm_pci_get_bdf(pdev); - pci_get_bus(PCI_BUS(bdf), &bus); - - if (!bus) - return -ENODEV; + ret = pci_get_bus(PCI_BUS(bdf), &bus); + if (ret) + return ret; bdf += PCI_BDF(0, 0, vf_offset); diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c index c5cc3cb9596..10194d0e14c 100644 --- a/drivers/sysinfo/sysinfo-uclass.c +++ b/drivers/sysinfo/sysinfo-uclass.c @@ -16,7 +16,15 @@ struct sysinfo_priv { int sysinfo_get(struct udevice **devp) { - return uclass_first_device_err(UCLASS_SYSINFO, devp); + int ret = uclass_first_device_err(UCLASS_SYSINFO, devp); + + /* + * There is some very dodgy error handling in gazerbeam, + * do not return a device on error. + */ + if (ret) + *devp = NULL; + return ret; } int sysinfo_detect(struct udevice *dev) diff --git a/include/dm/uclass.h b/include/dm/uclass.h index 823a16527f7..b1c016ef9f5 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -350,7 +350,8 @@ int uclass_next_device(struct udevice **devp); /** * uclass_first_device_err() - Get the first device in a uclass * - * The device returned is probed if necessary, and ready for use + * The device returned is probed if necessary, and ready for use if no error is + * returned * * @id: Uclass ID to look up * @devp: Returns pointer to the first device in that uclass, or NULL if none @@ -361,7 +362,8 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp); /** * uclass_next_device_err() - Get the next device in a uclass * - * The device returned is probed if necessary, and ready for use + * The device returned is probed if necessary, and ready for use if no error is + * returned * * @devp: On entry, pointer to device to lookup. On exit, returns pointer * to the next device in the uclass if no error occurred, or NULL if @@ -373,7 +375,8 @@ int uclass_next_device_err(struct udevice **devp); /** * uclass_first_device_check() - Get the first device in a uclass * - * The device returned is probed if necessary, and ready for use + * The device returned is probed if necessary, and ready for use if no error is + * returned * * This function is useful to start iterating through a list of devices which * are functioning correctly and can be probed. @@ -389,7 +392,8 @@ int uclass_first_device_check(enum uclass_id id, struct udevice **devp); /** * uclass_next_device_check() - Get the next device in a uclass * - * The device returned is probed if necessary, and ready for use + * The device returned is probed if necessary, and ready for use if no error is + * returned * * This function is useful to start iterating through a list of devices which * are functioning correctly and can be probed. From 73f8fbc532c3546dd4bf6f267e530a82f04703fa Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Tue, 27 Sep 2022 23:24:36 +0200 Subject: [PATCH 19/22] dm: core: Document return value of device bind functions These functions use device_bind_with_driver_data internally, copy the return value description. Signed-off-by: Michal Suchanek --- include/dm/lists.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dm/lists.h b/include/dm/lists.h index fc3b4ae5850..97236f8fa0d 100644 --- a/include/dm/lists.h +++ b/include/dm/lists.h @@ -73,6 +73,7 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp, * @drv_name: Name of driver to attach to this parent * @dev_name: Name of the new device thus created * @devp: If non-NULL, returns the newly bound device + * Return: 0 if OK, -ve on error */ int device_bind_driver(struct udevice *parent, const char *drv_name, const char *dev_name, struct udevice **devp); @@ -88,6 +89,7 @@ int device_bind_driver(struct udevice *parent, const char *drv_name, * @dev_name: Name of the new device thus created * @node: Device tree node * @devp: If non-NULL, returns the newly bound device + * Return: 0 if OK, -ve on error */ int device_bind_driver_to_node(struct udevice *parent, const char *drv_name, const char *dev_name, ofnode node, From aa5511e77b8bd8f943c66b6403896d06083b1d92 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Tue, 27 Sep 2022 23:25:08 +0200 Subject: [PATCH 20/22] dm: core: Add note about device_probe idempotence device_probe returns early when the device is already activated. Add a note to the documentation that it can be used on already activated devices. Signed-off-by: Michal Suchanek --- include/dm/device-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index 94844d30d85..f31c4702086 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -184,8 +184,8 @@ int device_of_to_plat(struct udevice *dev); /** * device_probe() - Probe a device, activating it * - * Activate a device so that it is ready for use. All its parents are probed - * first. + * Activate a device (if not yet activated) so that it is ready for use. + * All its parents are probed first. * * @dev: Pointer to device to probe * Return: 0 if OK, -ve on error From 4954937d922840c212b7eba297cc2d4779f087ad Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Wed, 12 Oct 2022 21:58:08 +0200 Subject: [PATCH 21/22] dm: treewide: Do not use the return value of simple uclass iterator uclass_first_device/uclass_next_device return value will be removed, don't use it. With the current implementation dev is equivalent to !ret. It is redundant to check both, ret check can be replaced with dev check, and ret check inside the iteration is dead code. Signed-off-by: Michal Suchanek Reviewed-by: Simon Glass --- cmd/virtio.c | 9 +++------ drivers/dma/dma-uclass.c | 7 +++---- drivers/gpio/gpio-uclass.c | 14 ++++++-------- drivers/pci/pci-uclass.c | 15 +++------------ drivers/w1/w1-uclass.c | 9 ++------- 5 files changed, 17 insertions(+), 37 deletions(-) diff --git a/cmd/virtio.c b/cmd/virtio.c index ec87d4f02c9..019e317e755 100644 --- a/cmd/virtio.c +++ b/cmd/virtio.c @@ -23,18 +23,15 @@ static int do_virtio(struct cmd_tbl *cmdtp, int flag, int argc, * device_probe() for children (i.e. virtio devices) */ struct udevice *bus, *child; - int ret; - ret = uclass_first_device(UCLASS_VIRTIO, &bus); - if (ret) + uclass_first_device(UCLASS_VIRTIO, &bus); + if (!bus) return CMD_RET_FAILURE; while (bus) { device_foreach_child_probe(child, bus) ; - ret = uclass_next_device(&bus); - if (ret) - break; + uclass_next_device(&bus); } return CMD_RET_SUCCESS; diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c index 81dbb4da107..34f72fa5dc8 100644 --- a/drivers/dma/dma-uclass.c +++ b/drivers/dma/dma-uclass.c @@ -210,10 +210,9 @@ int dma_get_cfg(struct dma *dma, u32 cfg_id, void **cfg_data) int dma_get_device(u32 transfer_type, struct udevice **devp) { struct udevice *dev; - int ret; - for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret; - ret = uclass_next_device(&dev)) { + for (uclass_first_device(UCLASS_DMA, &dev); dev; + uclass_next_device(&dev)) { struct dma_dev_priv *uc_priv; uc_priv = dev_get_uclass_priv(dev); @@ -229,7 +228,7 @@ int dma_get_device(u32 transfer_type, struct udevice **devp) *devp = dev; - return ret; + return 0; } int dma_memcpy(void *dst, void *src, size_t len) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 65033258f47..3a6ef3b01d5 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -59,11 +59,10 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) { struct gpio_dev_priv *uc_priv; struct udevice *dev; - int ret; - for (ret = uclass_first_device(UCLASS_GPIO, &dev); + for (uclass_first_device(UCLASS_GPIO, &dev); dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { uc_priv = dev_get_uclass_priv(dev); if (gpio >= uc_priv->gpio_base && gpio < uc_priv->gpio_base + uc_priv->gpio_count) { @@ -73,7 +72,7 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) } /* No such GPIO */ - return ret ? ret : -ENOENT; + return -ENOENT; } #if CONFIG_IS_ENABLED(DM_GPIO_LOOKUP_LABEL) @@ -119,12 +118,11 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) struct udevice *dev; ulong offset; int numeric; - int ret; numeric = isdigit(*name) ? dectoul(name, NULL) : -1; - for (ret = uclass_first_device(UCLASS_GPIO, &dev); + for (uclass_first_device(UCLASS_GPIO, &dev); dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { int len; uc_priv = dev_get_uclass_priv(dev); @@ -152,7 +150,7 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) } if (!dev) - return ret ? ret : -EINVAL; + return -EINVAL; gpio_desc_init(desc, dev, offset); diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 6dd19650f9c..9343cfc62a9 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -1211,7 +1211,6 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, static int skip_to_next_device(struct udevice *bus, struct udevice **devp) { struct udevice *dev; - int ret = 0; /* * Scan through all the PCI controllers. On x86 there will only be one @@ -1223,9 +1222,7 @@ static int skip_to_next_device(struct udevice *bus, struct udevice **devp) *devp = dev; return 0; } - ret = uclass_next_device(&bus); - if (ret) - return ret; + uclass_next_device(&bus); } return 0; @@ -1235,7 +1232,6 @@ int pci_find_next_device(struct udevice **devp) { struct udevice *child = *devp; struct udevice *bus = child->parent; - int ret; /* First try all the siblings */ *devp = NULL; @@ -1248,9 +1244,7 @@ int pci_find_next_device(struct udevice **devp) } /* We ran out of siblings. Try the next bus */ - ret = uclass_next_device(&bus); - if (ret) - return ret; + uclass_next_device(&bus); return bus ? skip_to_next_device(bus, devp) : 0; } @@ -1258,12 +1252,9 @@ int pci_find_next_device(struct udevice **devp) int pci_find_first_device(struct udevice **devp) { struct udevice *bus; - int ret; *devp = NULL; - ret = uclass_first_device(UCLASS_PCI, &bus); - if (ret) - return ret; + uclass_first_device(UCLASS_PCI, &bus); return skip_to_next_device(bus, devp); } diff --git a/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c index de4f25bcf95..a4247ecd623 100644 --- a/drivers/w1/w1-uclass.c +++ b/drivers/w1/w1-uclass.c @@ -36,15 +36,10 @@ int w1_bus_find_dev(const struct udevice *bus, u64 id, struct udevice { struct udevice *dev; u8 family = id & 0xff; - int ret; - for (ret = uclass_first_device(UCLASS_W1_EEPROM, &dev); - !ret && dev; + for (uclass_first_device(UCLASS_W1_EEPROM, &dev); + dev; uclass_next_device(&dev)) { - if (ret || !dev) { - debug("cannot find w1 eeprom dev\n"); - return -ENODEV; - } if (dev_get_driver_data(dev) == family) { *devp = dev; From f21954750aa8ed445ab83998bb099e366136c428 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Wed, 12 Oct 2022 21:58:09 +0200 Subject: [PATCH 22/22] dm: core: Do not stop uclass iteration on error When probing a device fails NULL pointer is returned, and following devices in uclass list cannot be iterated. Skip to next device on error instead. With that the only condition under which these simple iteration functions return error is when the dm is not initialized at uclass_get time. This is not all that interesting, change return type to void. Fixes: 6494d708bf ("dm: Add base driver model support") Signed-off-by: Michal Suchanek Reviewed-by: Simon Glass --- drivers/core/uclass.c | 30 ++++++++++++++++++------------ include/dm/uclass.h | 13 ++++++------- test/dm/core.c | 10 ++++------ test/dm/test-fdt.c | 27 ++++++++++++++++++++------- 4 files changed, 48 insertions(+), 32 deletions(-) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index b7d11bdd23a..1762a0796db 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -574,28 +574,34 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent, } #endif -int uclass_first_device(enum uclass_id id, struct udevice **devp) +/* + * Starting from the given device @dev, return pointer to the first device in + * the uclass that probes successfully in @devp. + */ +static void _uclass_next_device(struct udevice *dev, struct udevice **devp) +{ + for (; dev; uclass_find_next_device(&dev)) { + if (!device_probe(dev)) + break; + } + *devp = dev; +} + +void uclass_first_device(enum uclass_id id, struct udevice **devp) { struct udevice *dev; int ret; - *devp = NULL; ret = uclass_find_first_device(id, &dev); - if (!dev) - return 0; - return uclass_get_device_tail(dev, ret, devp); + _uclass_next_device(dev, devp); } -int uclass_next_device(struct udevice **devp) +void uclass_next_device(struct udevice **devp) { struct udevice *dev = *devp; - int ret; - *devp = NULL; - ret = uclass_find_next_device(&dev); - if (!dev) - return 0; - return uclass_get_device_tail(dev, ret, devp); + uclass_find_next_device(&dev); + _uclass_next_device(dev, devp); } int uclass_first_device_err(enum uclass_id id, struct udevice **devp) diff --git a/include/dm/uclass.h b/include/dm/uclass.h index b1c016ef9f5..ee15c920633 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -320,32 +320,31 @@ int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv, * uclass_first_device() - Get the first device in a uclass * * The device returned is probed if necessary, and ready for use + * Devices that fail to probe are skipped * * This function is useful to start iterating through a list of devices which * are functioning correctly and can be probed. * * @id: Uclass ID to look up * @devp: Returns pointer to the first device in that uclass if no error - * occurred, or NULL if there is no first device, or an error occurred with - * that device. - * Return: 0 if OK (found or not found), other -ve on error + * occurred, or NULL if there is no usable device */ -int uclass_first_device(enum uclass_id id, struct udevice **devp); +void uclass_first_device(enum uclass_id id, struct udevice **devp); /** * uclass_next_device() - Get the next device in a uclass * * The device returned is probed if necessary, and ready for use + * Devices that fail to probe are skipped * * This function is useful to iterate through a list of devices which * are functioning correctly and can be probed. * * @devp: On entry, pointer to device to lookup. On exit, returns pointer * to the next device in the uclass if no error occurred, or NULL if there is - * no next device, or an error occurred with that next device. - * Return: 0 if OK (found or not found), other -ve on error + * no next device */ -int uclass_next_device(struct udevice **devp); +void uclass_next_device(struct udevice **devp); /** * uclass_first_device_err() - Get the first device in a uclass diff --git a/test/dm/core.c b/test/dm/core.c index 84eb76ed5fc..7f3f8d183bc 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -1078,11 +1078,10 @@ static int dm_test_uclass_devices_get(struct unit_test_state *uts) struct udevice *dev; int ret; - for (ret = uclass_first_device(UCLASS_TEST, &dev); + for (ret = uclass_first_device_check(UCLASS_TEST, &dev); dev; - ret = uclass_next_device(&dev)) { + ret = uclass_next_device_check(&dev)) { ut_assert(!ret); - ut_assert(dev); ut_assert(device_active(dev)); } @@ -1112,11 +1111,10 @@ static int dm_test_uclass_devices_get_by_name(struct unit_test_state *uts) * this will fail on checking condition: testdev == finddev, since the * uclass_get_device_by_name(), returns the first device by given name. */ - for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev); + for (ret = uclass_first_device_check(UCLASS_TEST_FDT, &testdev); testdev; - ret = uclass_next_device(&testdev)) { + ret = uclass_next_device_check(&testdev)) { ut_assertok(ret); - ut_assert(testdev); ut_assert(device_active(testdev)); findret = uclass_get_device_by_name(UCLASS_TEST_FDT, diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 1f14513d9f1..8bb868b6787 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -403,13 +403,12 @@ static int dm_test_first_next_device_probeall(struct unit_test_state *uts) int ret; /* There should be 4 devices */ - for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; + for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { count++; parent = dev_get_parent(dev); } - ut_assertok(ret); ut_asserteq(4, count); /* Remove them and try again, with an error on the second one */ @@ -417,16 +416,30 @@ static int dm_test_first_next_device_probeall(struct unit_test_state *uts) pdata = dev_get_plat(dev); pdata->probe_err = -ENOMEM; device_remove(parent, DM_REMOVE_NORMAL); - ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev)); - ut_asserteq(-ENOMEM, uclass_next_device(&dev)); - ut_asserteq_ptr(dev, NULL); + for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev), + count = 0; + dev; + ret = uclass_next_device_check(&dev)) { + if (!ret) + count++; + else + ut_asserteq(-ENOMEM, ret); + parent = dev_get_parent(dev); + } + ut_asserteq(3, count); /* Now an error on the first one */ ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev)); pdata = dev_get_plat(dev); pdata->probe_err = -ENOENT; device_remove(parent, DM_REMOVE_NORMAL); - ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev)); + for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; + dev; + uclass_next_device(&dev)) { + count++; + parent = dev_get_parent(dev); + } + ut_asserteq(2, count); /* Now that broken devices are set up test probe_all */ device_remove(parent, DM_REMOVE_NORMAL);