[PATCH] lmb: Bump CONFIG_LMB_MAX_REGIONS

2023-01-27 Thread Michal Suchanek
It is reported that in some configurations it is not possible to boot
because u-boot runs out of lmbs.

commit 06d514d77c ("lmb: consider EFI memory map") increases lmb usage,
hence is likely the cause of the lmb overflow.

Fixes: 06d514d77c ("lmb: consider EFI memory map")
Link: https://bugzilla.opensuse.org/show_bug.cgi?id=1207562
Signed-off-by: Michal Suchanek 
---
 lib/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Kconfig b/lib/Kconfig
index 549bd35778..06c873c2bd 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -1038,7 +1038,7 @@ config LMB_USE_MAX_REGIONS
 config LMB_MAX_REGIONS
int "Number of memory and reserved regions in lmb lib"
depends on LMB && LMB_USE_MAX_REGIONS
-   default 8
+   default 16
help
  Define the number of supported regions, memory and reserved, in the
  library logical memory blocks.
-- 
2.39.0



[PATCH] rockchip: Pinebook Pro: Do not initialize i2c before relocation

2022-12-03 Thread Michal Suchanek
The i2c locks up when initialized before relocation, and it stays broken
in Linux as well breaking the ability to boot Linux.

The i2c bus and pmic was not actually used in pre-reloc before
commit ad607512f575 ("power: pmic: rk8xx: Support sysreset shutdown method")

The cause is not known.

This is board-specific, other boards that do not add the option to
include the i2c bus in pre-reloc DT are not affected.

Signed-off-by: Michal Suchanek 
---

This is not tested, my board does not currentl;y boot at all, YMMV
---
 arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi | 8 
 1 file changed, 8 deletions(-)

diff --git a/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi 
b/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
index 2d87bea933..fd87102c0b 100644
--- a/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
@@ -20,14 +20,6 @@
rockchip,panel = <_panel>;
 };
 
- {
-   u-boot,dm-pre-reloc;
-};
-
- {
-   u-boot,dm-pre-reloc;
-};
-
  {
max-frequency = <2500>;
u-boot,dm-pre-reloc;
-- 
2.38.1



[PATCH] sandbox: Correctly define BITS_PER_LONG

2022-10-22 Thread Michal Suchanek
SANDBOX_BITS_PER_LONG is the number of bits in long on the sandbox
platform.

Signed-off-by: Michal Suchanek 
---

 arch/sandbox/include/asm/types.h | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h
index c1a5d2af82..5f4b649ee3 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -18,11 +18,7 @@ typedef unsigned short umode_t;
 /*
  * Number of bits in a C 'long' on this architecture.
  */
-#ifdef CONFIG_PHYS_64BIT
-#define BITS_PER_LONG 64
-#else  /* CONFIG_PHYS_64BIT */
-#define BITS_PER_LONG 32
-#endif /* CONFIG_PHYS_64BIT */
+#define BITS_PER_LONG CONFIG_SANDBOX_BITS_PER_LONG
 
 #ifdef CONFIG_PHYS_64BIT
 typedef unsigned long long dma_addr_t;
-- 
2.38.0



[PATCH] xen: pvblock: Use uclass_probe_all

2022-10-22 Thread Michal Suchanek
Also eliminate useless code and variables.

Signed-off-by: Michal Suchanek 
---

 drivers/xen/pvblock.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c
index 95e298d7dd..4ad548d599 100644
--- a/drivers/xen/pvblock.c
+++ b/drivers/xen/pvblock.c
@@ -818,8 +818,6 @@ static void print_pvblock_devices(void)
 void pvblock_init(void)
 {
struct driver_info info;
-   struct udevice *udev;
-   struct uclass *uc;
int ret;
 
/*
@@ -828,15 +826,12 @@ void pvblock_init(void)
 * virtual block devices.
 */
info.name = DRV_NAME;
-   ret = device_bind_by_name(gd->dm_root, false, , );
+   ret = device_bind_by_name(gd->dm_root, false, , NULL);
if (ret < 0)
printf("Failed to bind " DRV_NAME ", ret: %d\n", ret);
 
/* Bootstrap virtual block devices class driver */
-   ret = uclass_get(UCLASS_PVBLOCK, );
-   if (ret)
-   return;
-   uclass_foreach_dev_probe(UCLASS_PVBLOCK, udev);
+   uclass_probe_all(UCLASS_PVBLOCK);
 
print_pvblock_devices();
 }
-- 
2.38.0



[PATCH v2] test: Fix typo in test name

2022-10-15 Thread Michal Suchanek
For other sandbox tests the printed test name corresponds to the
configuration except for this one.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---

Changes in v2:
Also fix nearby comment typo

---
 test/run | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/run b/test/run
index 810b47e08d..c4ab046ce8 100755
--- a/test/run
+++ b/test/run
@@ -51,9 +51,9 @@ echo "${prompt}"
 run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build ${para} \
-k 'test_ofplatdata or test_handoff or test_spl'
 
-# Run the sane tests with sandbox_noinst (i.e. without OF_PLATDATA_INST)
+# Run the same tests with sandbox_noinst (i.e. without OF_PLATDATA_INST)
 echo "${prompt}"
-run_test "sandbox_spl" ./test/py/test.py --bd sandbox_noinst --build ${para} \
+run_test "sandbox_noinst" ./test/py/test.py --bd sandbox_noinst --build 
${para} \
-k 'test_ofplatdata or test_handoff or test_spl'
 
 if [ -z "$tools_only" ]; then
-- 
2.37.3



[PATCH v2] tests: Build correct sandbox configuration on 32bit

2022-10-14 Thread Michal Suchanek
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 
---

Changes in v2:
simplify and move detection to kconfig

---
 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 852a7c8bf2..35508c6b29 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 dad5583451..b7598ca5d9 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))
-- 
2.37.3



[PATCH] test: Fix typo in test name

2022-10-13 Thread Michal Suchanek
For other sandbox tests the printed test name corresponds to the
configuration except for this one.

Signed-off-by: Michal Suchanek 
---

 test/run | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/run b/test/run
index 810b47e08d..5b17204c73 100755
--- a/test/run
+++ b/test/run
@@ -53,7 +53,7 @@ run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl 
--build ${para} \
 
 # Run the sane tests with sandbox_noinst (i.e. without OF_PLATDATA_INST)
 echo "${prompt}"
-run_test "sandbox_spl" ./test/py/test.py --bd sandbox_noinst --build ${para} \
+run_test "sandbox_noinst" ./test/py/test.py --bd sandbox_noinst --build 
${para} \
-k 'test_ofplatdata or test_handoff or test_spl'
 
 if [ -z "$tools_only" ]; then
-- 
2.37.3



[PATCH] libfdt: Fix build with python 3.10

2022-10-13 Thread Michal Suchanek
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 
---

 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 27c29ea260..56cc5d48f4 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 
 
 %{
-- 
2.37.3



[PATCH] libfdt: Fix invalid version warning

2022-10-13 Thread Michal Suchanek
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 
---

 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 493995e303..a7579f0c5f 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)/.." \
-- 
2.37.3



[PATCH] clk: k210: Fix error calculation on 32bit

2022-10-13 Thread Michal Suchanek
k210 is 64bit but the driver and tests are also built in sandbox, and
that can be built 32bit.

BIT(32) does not work on 32bit, shift before subtraction to fit into
32bit integer with BIT values.

Signed-off-by: Michal Suchanek 
---

 drivers/clk/clk_k210.c | 2 +-
 test/dm/k210_pll.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk_k210.c b/drivers/clk/clk_k210.c
index 1961efaa5e..e85f8ae14a 100644
--- a/drivers/clk/clk_k210.c
+++ b/drivers/clk/clk_k210.c
@@ -846,7 +846,7 @@ again:
 
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
/* The lower 16 bits are spurious */
-   error = abs((error - BIT(32))) >> 16;
+   error = abs((error >> 16) - BIT(32 - 16));
 
if (error < best_error) {
best->r = r;
diff --git a/test/dm/k210_pll.c b/test/dm/k210_pll.c
index a0cc84c396..622b1c9bef 100644
--- a/test/dm/k210_pll.c
+++ b/test/dm/k210_pll.c
@@ -33,7 +33,7 @@ static int dm_test_k210_pll_calc_config(u32 rate, u32 rate_in,
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio,
  r * od);
/* The lower 16 bits are spurious */
-   error = abs((error - BIT(32))) >> 16;
+   error = abs((error >> 16) - BIT(32 - 16));
if (error < best_error) {
best->r = r;
best->f = f;
-- 
2.37.3



[PATCH] tests: Build correct sandbox configuration on 32bit

2022-10-13 Thread Michal Suchanek
Currently sandbox configuration defautls to 64bit and there is no
automation for building 32bit sandbox on 32bit hosts.

cpp does not know about target specification, code needs to be compiled
to determine integer width.

Add a test program that prints the integer width, and a make target that
aligns the sandbox configuration with the result.

Signed-off-by: Michal Suchanek 
---

 Makefile  |  6 ++
 doc/arch/sandbox.rst  | 16 +++-
 test/py/conftest.py   |  1 +
 tools/Makefile|  2 ++
 tools/bits-per-long.c | 14 ++
 5 files changed, 34 insertions(+), 5 deletions(-)
 create mode 100644 tools/bits-per-long.c

diff --git a/Makefile b/Makefile
index 3866cc62f9..e5463573f3 100644
--- a/Makefile
+++ b/Makefile
@@ -2166,6 +2166,12 @@ tools-all: envtools tools ;
 cross_tools: export CROSS_BUILD_TOOLS=y
 cross_tools: tools ;
 
+PHONY += set_host_bits
+set_host_bits: tools
+   $(Q)sed -i -e /CONFIG_HOST_$$($(objtree)/tools/bits-per-long)BIT/d 
$(KCONFIG_CONFIG)
+   $(Q)sed -i -E -e "s/CONFIG_HOST_(..)BIT=y/# CONFIG_HOST_\1BIT is not 
set/" $(KCONFIG_CONFIG)
+   $(Q)echo CONFIG_HOST_$$($(objtree)/tools/bits-per-long)BIT=y >> 
$(KCONFIG_CONFIG)
+
 .PHONY : CHANGELOG
 CHANGELOG:
git log --no-merges U-Boot-1_1_5.. | \
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index 068d4a3be4..d751205eba 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -33,9 +33,11 @@ machines.
 
 There are two versions of the sandbox: One using 32-bit-wide integers, and one
 using 64-bit-wide integers. The 32-bit version can be build and run on either
-32 or 64-bit hosts by either selecting or deselecting CONFIG_SANDBOX_32BIT; by
-default, the sandbox it built for a 32-bit host. The sandbox using 64-bit-wide
-integers can only be built on 64-bit hosts.
+32 or 64-bit hosts by either selecting or deselecting HOST_64BIT; by
+default, the sandbox it built for a 64-bit host. The sandbox using 64-bit-wide
+integers can only be built on 64-bit hosts. There is no automation for ensuring
+32bit build on 32bit hosts - use ``make set_host_bits`` to adjust the sandbox
+config.
 
 Note that standalone/API support is not available at present.
 
@@ -51,7 +53,9 @@ Basic Operation
 
 To run sandbox U-Boot use something like::
 
-   make sandbox_defconfig all
+   make sandbox_defconfig
+   make set_host_bits
+   make all
./u-boot
 
 Note: If you get errors about 'sdl-config: Command not found' you may need to
@@ -59,7 +63,9 @@ install libsdl2.0-dev or similar to get SDL support. 
Alternatively you can
 build sandbox without SDL (i.e. no display/keyboard support) by removing
 the CONFIG_SANDBOX_SDL line in include/configs/sandbox.h or using::
 
-   make sandbox_defconfig all NO_SDL=1
+   make sandbox_defconfig
+   make set_host_bits
+   make all NO_SDL=1
./u-boot
 
 U-Boot will start on your computer, showing a sandbox emulation of the serial
diff --git a/test/py/conftest.py b/test/py/conftest.py
index 304e93164a..3d1fd6883a 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -104,6 +104,7 @@ def run_build(config, source_dir, build_dir, board_type, 
log):
 o_opt = ''
 cmds = (
 ['make', o_opt, '-s', board_type + '_defconfig'],
+['make', o_opt, '-s', 'set_host_bits'],
 ['make', o_opt, '-s', '-j{}'.format(os.cpu_count())],
 )
 name = 'make'
diff --git a/tools/Makefile b/tools/Makefile
index 34a1aa7a8b..d6b585953d 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -68,6 +68,8 @@ HOSTCFLAGS_img2srec.o := -pedantic
 hostprogs-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes
 HOSTCFLAGS_xway-swap-bytes.o := -pedantic
 
+hostprogs-y += bits-per-long
+
 hostprogs-y += mkenvimage
 mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o
 
diff --git a/tools/bits-per-long.c b/tools/bits-per-long.c
new file mode 100644
index 00..7630e1623f
--- /dev/null
+++ b/tools/bits-per-long.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+#include 
+
+int main(int argc, char **argv)
+{
+   unsigned long testvar = ~0UL;
+   unsigned int i;
+
+   for (i = 0; testvar; i++, testvar >>= 1)
+   ;
+
+   return printf("%u\n", i);
+}
+
-- 
2.37.3



[PATCH v6 00/20] Do not stop uclass iteration on error

2022-10-13 Thread Michal Suchanek
Hello,

this patch series fixes the simple uclass iterators to be usable for
iterating uclasses even if some devices fail to probe.

Before this series when a probe error happens an error is returned
without any device pointer, and iteration cannot continue to devices
that happen to be after the failing device in the uclass list.

This is rarely expected, nor clearly documented, and for the most part
not useful in any way.

All but the last patch are new in v4 removing problematic iterator use.

v5:

Split off patches that can be applied independently

Fix uclass_foreach_dev_probe, pci_sriov_init, and sysinfo_get to work
after the uclass_first_device_err change.

Document that uclass_first_device_err and uclass_first_device_check can
return non-activated device on error.

Consolidate multiple similar cleanups into one patch.

v6:

Split off the fixups from uclass_*_device_err switch patch.

Thanks

Michal

Michal Suchanek (20):
  dm: core: Fix uclass_probe_all to really probe all devices
  dm: treewide: Do not opencode uclass_probe_all()
  dm: pci: Fix device PCI iteration
  bootstd: Fix listing boot devices
  usb: ether: Fix error handling in usb_ether_init
  stdio: Fix class iteration in stdio_add_devices()
  video: ipuv3: Fix error handling when getting the display
  w1: Fix bus counting in w1_get_bus
  cmd: List all uclass devices regardless of probe error
  dm: treewide: Use uclass_first_device_err when accessing one device
  dm: treewide: Use uclass_next_device_err when accessing second device
  dm: blk: Do not use uclass_next_device_err
  net: eth-uclass: Do not set device on error
  dm: pci: Update error handling in pci_sriov_init
  mpc83xx: gazerbeam: Update sysinfo_get error handling
  dm: core: Switch uclass_foreach_dev_probe to use simple iterator
  dm: core: Switch uclass_*_device_err to use uclass_*_device_check
  dm: core: Non-activated device may be returned from uclass iterators
that provide error handling
  dm: treewide: Do not use the return value of simple uclass iterator
  dm: core: Do not stop uclass iteration on error

 arch/arm/mach-k3/j721s2_init.c|  2 +-
 arch/arm/mach-omap2/am33xx/board.c|  4 +-
 arch/x86/cpu/broadwell/cpu.c  |  4 +-
 arch/x86/cpu/intel_common/cpu.c   |  4 +-
 arch/x86/lib/pinctrl_ich6.c   |  4 +-
 board/atmel/common/mac_eeprom.c   |  2 +-
 board/gdsys/mpc8308/gazerbeam.c   | 12 +++--
 board/intel/cougarcanyon2/cougarcanyon2.c |  4 +-
 boot/bootdev-uclass.c |  4 +-
 cmd/adc.c | 20 
 cmd/demo.c| 15 +++---
 cmd/gpio.c| 15 --
 cmd/pmic.c| 15 +++---
 cmd/regulator.c   | 13 +++---
 cmd/virtio.c  |  9 ++--
 common/stdio.c| 32 ++---
 drivers/block/blk-uclass.c| 16 +++
 drivers/core/uclass.c | 56 ---
 drivers/cpu/cpu-uclass.c  | 20 ++--
 drivers/dma/dma-uclass.c  |  7 ++-
 drivers/gpio/gpio-uclass.c| 14 +++---
 drivers/mmc/omap_hsmmc.c  |  2 +-
 drivers/pci/pci-uclass.c  | 26 ---
 drivers/serial/serial-uclass.c|  2 +-
 drivers/serial/serial_bcm283x_mu.c|  2 +-
 drivers/serial/serial_bcm283x_pl011.c |  2 +-
 drivers/sysreset/sysreset_ast.c   |  2 +-
 drivers/usb/gadget/ether.c| 11 ++---
 drivers/video/exynos/exynos_fb.c  | 14 ++
 drivers/video/imx/mxc_ipuv3_fb.c  |  9 ++--
 drivers/video/mali_dp.c   |  2 +-
 drivers/video/stm32/stm32_dsi.c   |  2 +-
 drivers/video/tegra124/dp.c   |  4 +-
 drivers/virtio/virtio-uclass.c| 15 +-
 drivers/w1/w1-uclass.c| 29 ++--
 include/dm/uclass.h   | 49 ++--
 lib/acpi/acpi_table.c |  2 +-
 lib/efi_loader/efi_gop.c  |  2 +-
 net/eth-uclass.c  |  6 ++-
 test/boot/bootmeth.c  |  2 +-
 test/dm/acpi.c| 14 +++---
 test/dm/core.c| 27 +++
 test/dm/devres.c  |  4 +-
 test/dm/i2c.c |  8 ++--
 test/dm/test-fdt.c| 46 ++-
 test/dm/virtio_device.c   |  8 ++--
 test/dm/virtio_rng.c  |  2 +-
 test/fuzz/cmd_fuzz.c  |  2 +-
 test/fuzz/virtio.c|  2 +-
 test/test-main.c  | 11 +
 50 files changed, 266 insertions(+), 313 deletions(-)

-- 
2.37.3



[PATCH v2 1/2] image: Fix string truncation warning

2022-10-13 Thread Michal Suchanek
In file included from ../tools/imagetool.h:24,
 from ../tools/default_image.c:16:
In function ‘image_set_name’,
inlined from ‘image_set_header’ at ../tools/default_image.c:133:2:
../include/image.h:786:9: warning: ‘strncpy’ specified bound 32 equals 
destination size [-Wstringop-truncation]
  786 | strncpy(image_get_name(hdr), name, IH_NMLEN);
  | ^~~~

Signed-off-by: Michal Suchanek 
---

Changes in v2:
Use __nonstring instead of suppressing the warning

---
 include/image.h  | 3 ++-
 tools/kwbimage.h | 6 --
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/include/image.h b/include/image.h
index d7d6a3fe5b..82b447aeb7 100644
--- a/include/image.h
+++ b/include/image.h
@@ -18,6 +18,7 @@
 #include "compiler.h"
 #include 
 #include 
+#include 
 
 /* Define this to avoid #ifdefs later on */
 struct lmb;
@@ -275,7 +276,7 @@ struct legacy_img_hdr {
uint8_t ih_arch;/* CPU architecture */
uint8_t ih_type;/* Image Type   */
uint8_t ih_comp;/* Compression Type */
-   uint8_t ih_name[IH_NMLEN];  /* Image Name   */
+   uint8_t ih_name[IH_NMLEN] __nonstring;  /* Image Name   */
 };
 
 struct image_info {
diff --git a/tools/kwbimage.h b/tools/kwbimage.h
index 505522332b..327ca34494 100644
--- a/tools/kwbimage.h
+++ b/tools/kwbimage.h
@@ -11,12 +11,6 @@
 #include 
 #include 
 
-#ifdef __GNUC__
-#define __packed __attribute((packed))
-#else
-#define __packed
-#endif
-
 #define KWBIMAGE_MAX_CONFIG((0x1dc - 0x20)/sizeof(struct reg_config))
 #define MAX_TEMPBUF_LEN32
 
-- 
2.37.3



[PATCH v2 2/2] spl: spl_legacy: Fix printing image name

2022-10-13 Thread Michal Suchanek
image_set_name does not terminate the name in the image header.

Then is should not be assumed it's nul terminated. image_print_contents
correctly print only IH_NMLEN characters.

Fix printing the unterminated field in spl_parse_legacy_header. The
format specifies the minimum printed length, not maximum.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---

(no changes since v1)

---
 common/spl/spl_legacy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c
index b3624dfbb7..11c459254b 100644
--- a/common/spl/spl_legacy.c
+++ b/common/spl/spl_legacy.c
@@ -55,7 +55,7 @@ int spl_parse_legacy_header(struct spl_image_info *spl_image,
spl_image->os = image_get_os(header);
spl_image->name = image_get_name(header);
debug(SPL_TPL_PROMPT
- "payload image: %32s load addr: 0x%lx size: %d\n",
+ "payload image: %.*s load addr: 0x%lx size: %d\n", IH_NMLEN,
  spl_image->name, spl_image->load_addr, spl_image->size);
 
return 0;
-- 
2.37.3



[PATCH v6 17/20] dm: core: Switch uclass_*_device_err to use uclass_*_device_check

2022-10-12 Thread Michal Suchanek
The _err variant iterators use the simple iterators without suffix as
basis.

However, there is no user that uclass_next_device_err for iteration,
many users of uclass_first_device_err use it to get the first and
(assumed) only device of an uclass, and a couple that use
uclass_next_device_err to get the device following a known device in the
uclass list.

While there are some truly singleton device classes in which more than
one device cannot exist these are quite rare, and most classes can have
multiple devices even if it is not the case on the SoC's EVB.

In a later patch the simple iterators will be updated to not stop on
error and return next device instead. With this in many cases the code
that expects the first device or an error if it fails to probe may get
the next device instead. Use the _check iterators as the basis of _err
iterators to preserve the old behavior.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v5: - udate documentation
- fix up a few more cases where device returned on error may cause
  problem
v6: - split the additional changes into separate patches
---
 drivers/core/uclass.c | 28 ++--
 include/dm/uclass.h   | 22 +++---
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index a591e22403..b7d11bdd23 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -586,19 +586,6 @@ int uclass_first_device(enum uclass_id id, struct udevice 
**devp)
return uclass_get_device_tail(dev, ret, devp);
 }
 
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
-{
-   int ret;
-
-   ret = uclass_first_device(id, devp);
-   if (ret)
-   return ret;
-   else if (!*devp)
-   return -ENODEV;
-
-   return 0;
-}
-
 int uclass_next_device(struct udevice **devp)
 {
struct udevice *dev = *devp;
@@ -611,11 +598,24 @@ int uclass_next_device(struct udevice **devp)
return uclass_get_device_tail(dev, ret, devp);
 }
 
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
+{
+   int ret;
+
+   ret = uclass_first_device_check(id, devp);
+   if (ret)
+   return ret;
+   else if (!*devp)
+   return -ENODEV;
+
+   return 0;
+}
+
 int uclass_next_device_err(struct udevice **devp)
 {
int ret;
 
-   ret = uclass_next_device(devp);
+   ret = uclass_next_device_check(devp);
if (ret)
return ret;
else if (!*devp)
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 990e9c02d1..823a16527f 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -332,17 +332,6 @@ int uclass_get_device_by_driver(enum uclass_id id, const 
struct driver *drv,
  */
 int uclass_first_device(enum uclass_id id, 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
- *
- * @id: Uclass ID to look up
- * @devp: Returns pointer to the first device in that uclass, or NULL if none
- * Return: 0 if found, -ENODEV if not found, other -ve on error
- */
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
-
 /**
  * uclass_next_device() - Get the next device in a uclass
  *
@@ -358,6 +347,17 @@ int uclass_first_device_err(enum uclass_id id, struct 
udevice **devp);
  */
 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
+ *
+ * @id: Uclass ID to look up
+ * @devp: Returns pointer to the first device in that uclass, or NULL if none
+ * Return: 0 if found, -ENODEV if not found, other -ve on error
+ */
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
+
 /**
  * uclass_next_device_err() - Get the next device in a uclass
  *
-- 
2.37.3



[PATCH v6 19/20] dm: treewide: Do not use the return value of simple uclass iterator

2022-10-12 Thread Michal Suchanek
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 
---
v5: - consolidate multiple similar patches
---
 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 ec87d4f02c..019e317e75 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, );
-   if (ret)
+   uclass_first_device(UCLASS_VIRTIO, );
+   if (!bus)
return CMD_RET_FAILURE;
 
while (bus) {
device_foreach_child_probe(child, bus)
;
-   ret = uclass_next_device();
-   if (ret)
-   break;
+   uclass_next_device();
}
 
return CMD_RET_SUCCESS;
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 012609bb53..952cbc2170 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -209,10 +209,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 && !ret;
-ret = uclass_next_device()) {
+   for (uclass_first_device(UCLASS_DMA, ); dev;
+uclass_next_device()) {
struct dma_dev_priv *uc_priv;
 
uc_priv = dev_get_uclass_priv(dev);
@@ -228,7 +227,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 a00880e446..3429ccaaca 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, );
+   for (uclass_first_device(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+uclass_next_device()) {
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)
@@ -121,12 +120,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, );
+   for (uclass_first_device(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+uclass_next_device()) {
int len;
 
uc_priv = dev_get_uclass_priv(dev);
@@ -154,7 +152,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 6dd19650f9..9343cfc62a 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();
-   if (ret)
-   return ret;
+  

[PATCH v6 20/20] dm: core: Do not stop uclass iteration on error

2022-10-12 Thread Michal Suchanek
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 
---
v2: - Fix up tests
v3: - Fix up API doc
- Correctly forward error from uclass_get
- Do not return an error when last device fails to probe
- Drop redundant initialization
- Wrap at 80 columns
v4: - change return value to void
- further simplify iteration
---
 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 b7d11bdd23..1762a0796d 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()) {
+   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, );
-   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();
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   uclass_find_next_device();
+   _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 b1c016ef9f..ee15c92063 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 84eb76ed5f..7f3f8d183b 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, );
+   for (ret = uclass_first_device_check(UCLASS_TEST, );
 dev;
-ret = uclass_next_device()) {
+ret = uclass_next_device_check()) {
ut_assert(!ret);
-   ut_assert(dev);
ut_assert(device_active(dev));
}
 
@@ -1112,11 +,10 @@ static int dm_test_uclass_devices_get_by_name(struct 
unit_test_

[PATCH v6 18/20] dm: core: Non-activated device may be returned from uclass iterators that provide error handling

2022-10-12 Thread Michal Suchanek
Note in documentation that a non-activated device can be returned on
error.

Signed-off-by: Michal Suchanek 
---
v6: - split off as separate patch
---
 include/dm/uclass.h | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 823a16527f..b1c016ef9f 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.
-- 
2.37.3



[PATCH v6 15/20] mpc83xx: gazerbeam: Update sysinfo_get error handling

2022-10-12 Thread Michal Suchanek
In a later patch sysinfo_get will be changed to return the device in cae
of an error. Set sysinfo to NULL on error to preserve previous behavior.

Signed-off-by: Michal Suchanek 
---
 board/gdsys/mpc8308/gazerbeam.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/board/gdsys/mpc8308/gazerbeam.c b/board/gdsys/mpc8308/gazerbeam.c
index 3d4a7e57fe..ba88401f13 100644
--- a/board/gdsys/mpc8308/gazerbeam.c
+++ b/board/gdsys/mpc8308/gazerbeam.c
@@ -49,8 +49,10 @@ int board_early_init_r(void)
int mc = 0;
int con = 0;
 
-   if (sysinfo_get())
+   if (sysinfo_get()) {
puts("Could not find sysinfo information device.\n");
+   sysinfo = NULL;
+   }
 
/* Initialize serdes */
uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, "serdes", );
@@ -92,8 +94,10 @@ int checksysinfo(void)
int mc = 0;
int con = 0;
 
-   if (sysinfo_get())
+   if (sysinfo_get()) {
puts("Could not find sysinfo information device.\n");
+   sysinfo = NULL;
+   }
 
sysinfo_get_int(sysinfo, BOARD_MULTICHANNEL, );
sysinfo_get_int(sysinfo, BOARD_VARIANT, );
@@ -130,8 +134,10 @@ int last_stage_init(void)
struct udevice *tpm;
int ret;
 
-   if (sysinfo_get())
+   if (sysinfo_get()) {
puts("Could not find sysinfo information device.\n");
+   sysinfo = NULL;
+   }
 
if (sysinfo) {
int res = sysinfo_get_int(sysinfo, BOARD_HWVERSION,
-- 
2.37.3



[PATCH v6 13/20] net: eth-uclass: Do not set device on error

2022-10-12 Thread Michal Suchanek
eth_get_dev relies on the broken behavior that returns an error but not
the device on which the error happened which gives the caller no
reasonable way to report or handle the error.

In a later patch uclass_first_device_err will be changed to return the
device on error but eth_get_dev stores the returned device pointer
directly in a global state without checking the return value. Unset the
pointer again in the error case.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v6: split off as separate patch
---
 net/eth-uclass.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 8c3f9cc31b..f41da4b37b 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -93,6 +93,8 @@ struct udevice *eth_get_dev(void)
if (eth_errno)
eth_errno = uclass_first_device_err(UCLASS_ETH,
_priv->current);
+   if (eth_errno)
+   uc_priv->current = NULL;
}
return uc_priv->current;
 }
-- 
2.37.3



[PATCH v6 14/20] dm: pci: Update error handling in pci_sriov_init

2022-10-12 Thread Michal Suchanek
Check the returned value from pci_get_bus. After a later patch
uclass_first_device_err may return a device on error and then checking
that a device is returned will not suffice.

Signed-off-by: Michal Suchanek 
---
v6: - split off as separate patch
---
 drivers/pci/pci-uclass.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 5cff81ac44..6dd19650f9 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), );
-
-   if (!bus)
-   return -ENODEV;
+   ret = pci_get_bus(PCI_BUS(bdf), );
+   if (ret)
+   return ret;
 
bdf += PCI_BDF(0, 0, vf_offset);
 
-- 
2.37.3



[PATCH v6 16/20] dm: core: Switch uclass_foreach_dev_probe to use simple iterator

2022-10-12 Thread Michal Suchanek
The return value is not used for anythig, and in a later patch the
behavior of the _err iterator will change in an incompatible way.

Signed-off-by: Michal Suchanek 
---
v6: - split off as separate patch
---
 include/dm/uclass.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index f6c0110b06..990e9c02d1 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -491,7 +491,7 @@ int uclass_id_count(enum uclass_id id);
  * are no more devices.
  */
 #define uclass_foreach_dev_probe(id, dev)  \
-   for (int _ret = uclass_first_device_err(id, ); !_ret && dev; \
-_ret = uclass_next_device_err())
+   for (uclass_first_device(id, ); dev; \
+uclass_next_device())
 
 #endif
-- 
2.37.3



[PATCH v6 12/20] dm: blk: Do not use uclass_next_device_err

2022-10-12 Thread Michal Suchanek
blk_first_device_err/blk_next_device_err uses
uclass_first_device_err/uclass_next_device_err for device iteration.

Although the function names superficially match the return value from
uclass_first_device_err/uclass_next_device_err is never used
meaningfully, and uclass_first_device/uclass_next_device works equally
well for this purpose.

In the following patch the semantic of
uclass_first_device_err/uclass_next_device_err will be changed to be
based on uclass_first_device_check/uclass_next_device_check breaking
this sole user that uses uclass_next_device_err for iteration.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
 drivers/block/blk-uclass.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 7d12d5413f..bcc14a684b 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -593,11 +593,9 @@ int blk_find_next(enum blk_flag_t flags, struct udevice 
**devp)
 
 int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp)
 {
-   int ret;
-
-   for (ret = uclass_first_device_err(UCLASS_BLK, devp);
-!ret;
-ret = uclass_next_device_err(devp)) {
+   for (uclass_first_device(UCLASS_BLK, devp);
+*devp;
+uclass_next_device(devp)) {
if (!blk_flags_check(*devp, flags))
return 0;
}
@@ -607,11 +605,9 @@ int blk_first_device_err(enum blk_flag_t flags, struct 
udevice **devp)
 
 int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp)
 {
-   int ret;
-
-   for (ret = uclass_next_device_err(devp);
-!ret;
-ret = uclass_next_device_err(devp)) {
+   for (uclass_next_device(devp);
+*devp;
+uclass_next_device(devp)) {
if (!blk_flags_check(*devp, flags))
return 0;
}
-- 
2.37.3



[PATCH v6 11/20] dm: treewide: Use uclass_next_device_err when accessing second device

2022-10-12 Thread Michal Suchanek
There are a couple users of uclass_next_device return value that get the
first device by other means and use uclass_next_device assuming the
following device in the uclass is related to the first one.

Use uclass_next_device_err because the return value from
uclass_next_device will be removed in a later patch.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
 arch/arm/mach-k3/j721s2_init.c  | 2 +-
 board/atmel/common/mac_eeprom.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-k3/j721s2_init.c b/arch/arm/mach-k3/j721s2_init.c
index 12da8136f9..dd0c7ba18f 100644
--- a/arch/arm/mach-k3/j721s2_init.c
+++ b/arch/arm/mach-k3/j721s2_init.c
@@ -164,7 +164,7 @@ void board_init_f(ulong dummy)
if (ret)
panic("DRAM 0 init failed: %d\n", ret);
 
-   ret = uclass_next_device();
+   ret = uclass_next_device_err();
if (ret)
panic("DRAM 1 init failed: %d\n", ret);
}
diff --git a/board/atmel/common/mac_eeprom.c b/board/atmel/common/mac_eeprom.c
index a723ba723c..4606008c69 100644
--- a/board/atmel/common/mac_eeprom.c
+++ b/board/atmel/common/mac_eeprom.c
@@ -56,7 +56,7 @@ int at91_set_eth1addr(int offset)
return ret;
 
/* attempt to obtain a second eeprom device */
-   ret = uclass_next_device();
+   ret = uclass_next_device_err();
if (ret)
return ret;
 
-- 
2.37.3



[PATCH v6 10/20] dm: treewide: Use uclass_first_device_err when accessing one device

2022-10-12 Thread Michal Suchanek
There is a number of users that use uclass_first_device to access the
first and (assumed) only device in uclass.

Some check the return value of uclass_first_device and also that a
device was returned which is exactly what uclass_first_device_err does.

Some are not checking that a device was returned and can potentially
crash if no device exists in the uclass. Finally there is one that
returns NULL on error either way.

Convert all of these to use uclass_first_device_err instead, the return
value will be removed from uclass_first_device in a later patch.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v6: drop errno_str
---
 arch/arm/mach-omap2/am33xx/board.c|  4 ++--
 arch/x86/cpu/broadwell/cpu.c  |  4 +---
 arch/x86/cpu/intel_common/cpu.c   |  4 +---
 arch/x86/lib/pinctrl_ich6.c   |  4 +---
 board/intel/cougarcanyon2/cougarcanyon2.c |  4 +---
 drivers/mmc/omap_hsmmc.c  |  2 +-
 drivers/serial/serial-uclass.c|  2 +-
 drivers/serial/serial_bcm283x_mu.c|  2 +-
 drivers/serial/serial_bcm283x_pl011.c |  2 +-
 drivers/sysreset/sysreset_ast.c   |  2 +-
 drivers/video/exynos/exynos_fb.c  | 14 +++---
 drivers/video/mali_dp.c   |  2 +-
 drivers/video/stm32/stm32_dsi.c   |  2 +-
 drivers/video/tegra124/dp.c   |  4 ++--
 lib/acpi/acpi_table.c |  2 +-
 lib/efi_loader/efi_gop.c  |  2 +-
 net/eth-uclass.c  |  4 ++--
 test/boot/bootmeth.c  |  2 +-
 test/dm/acpi.c| 14 +++---
 test/dm/devres.c  |  4 ++--
 test/dm/i2c.c |  8 
 test/dm/virtio_device.c   |  8 
 test/dm/virtio_rng.c  |  2 +-
 test/fuzz/cmd_fuzz.c  |  2 +-
 test/fuzz/virtio.c|  2 +-
 25 files changed, 43 insertions(+), 59 deletions(-)

diff --git a/arch/arm/mach-omap2/am33xx/board.c 
b/arch/arm/mach-omap2/am33xx/board.c
index 7f1b84e466..f393ff9144 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -265,8 +265,8 @@ int arch_misc_init(void)
struct udevice *dev;
int ret;
 
-   ret = uclass_first_device(UCLASS_MISC, );
-   if (ret || !dev)
+   ret = uclass_first_device_err(UCLASS_MISC, );
+   if (ret)
return ret;
 
 #if defined(CONFIG_DM_ETH) && defined(CONFIG_USB_ETHER)
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index 2adcf4b242..7877961451 100644
--- a/arch/x86/cpu/broadwell/cpu.c
+++ b/arch/x86/cpu/broadwell/cpu.c
@@ -31,11 +31,9 @@ static int broadwell_init_cpu(void *ctx, struct event *event)
int ret;
 
/* Start up the LPC so we have serial */
-   ret = uclass_first_device(UCLASS_LPC, );
+   ret = uclass_first_device_err(UCLASS_LPC, );
if (ret)
return ret;
-   if (!dev)
-   return -ENODEV;
ret = cpu_set_flex_ratio_to_tdp_nominal();
if (ret)
return ret;
diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c
index 96d05e2eb3..8f489e6c65 100644
--- a/arch/x86/cpu/intel_common/cpu.c
+++ b/arch/x86/cpu/intel_common/cpu.c
@@ -61,11 +61,9 @@ int cpu_common_init(void)
/* Early chipset init required before RAM init can work */
uclass_first_device(UCLASS_NORTHBRIDGE, );
 
-   ret = uclass_first_device(UCLASS_LPC, );
+   ret = uclass_first_device_err(UCLASS_LPC, );
if (ret)
return ret;
-   if (!lpc)
-   return -ENODEV;
 
/* Cause the SATA device to do its early init */
uclass_first_device(UCLASS_AHCI, );
diff --git a/arch/x86/lib/pinctrl_ich6.c b/arch/x86/lib/pinctrl_ich6.c
index fd5e311b29..c93f245845 100644
--- a/arch/x86/lib/pinctrl_ich6.c
+++ b/arch/x86/lib/pinctrl_ich6.c
@@ -160,11 +160,9 @@ static int ich6_pinctrl_probe(struct udevice *dev)
u32 iobase = -1;
 
debug("%s: start\n", __func__);
-   ret = uclass_first_device(UCLASS_PCH, );
+   ret = uclass_first_device_err(UCLASS_PCH, );
if (ret)
return ret;
-   if (!pch)
-   return -ENODEV;
 
/*
 * Get the memory/io base address to configure every pins.
diff --git a/board/intel/cougarcanyon2/cougarcanyon2.c 
b/board/intel/cougarcanyon2/cougarcanyon2.c
index ce11eae59d..7f61ef8b36 100644
--- a/board/intel/cougarcanyon2/cougarcanyon2.c
+++ b/board/intel/cougarcanyon2/cougarcanyon2.c
@@ -21,11 +21,9 @@ int board_early_init_f(void)
struct udevice *pch;
int ret;
 
-   ret = uclass_first_device(UCLASS_PCH, );
+   ret = uclass_first_device_err(UCLASS_PCH, );
if (ret)
return ret;
-   if (!pch)
-   return -ENODEV;
 
/* Initialize LPC

[PATCH v6 09/20] cmd: List all uclass devices regardless of probe error

2022-10-12 Thread Michal Suchanek
There are a few commands that iterate uclass with
uclass_first_device/uclass_next_device or the _err variant.

Use the _check class iterator variant to get devices that fail to probe
as well, and print the status.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v6: Drop errno_str
---
 cmd/adc.c   | 20 
 cmd/demo.c  | 15 +--
 cmd/gpio.c  | 15 +++
 cmd/pmic.c  | 15 ---
 cmd/regulator.c | 13 +++--
 5 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/cmd/adc.c b/cmd/adc.c
index 1c5d3e10a3..a739d9e464 100644
--- a/cmd/adc.c
+++ b/cmd/adc.c
@@ -12,23 +12,19 @@ static int do_adc_list(struct cmd_tbl *cmdtp, int flag, int 
argc,
   char *const argv[])
 {
struct udevice *dev;
-   int ret;
+   int ret, err;
 
-   ret = uclass_first_device_err(UCLASS_ADC, );
-   if (ret) {
-   printf("No available ADC device\n");
-   return CMD_RET_FAILURE;
-   }
+   ret = err = uclass_first_device_check(UCLASS_ADC, );
 
-   do {
-   printf("- %s\n", dev->name);
+   while (dev) {
+   printf("- %s status: %i\n", dev->name, ret);
 
-   ret = uclass_next_device();
+   ret = uclass_next_device_check();
if (ret)
-   return CMD_RET_FAILURE;
-   } while (dev);
+   err = ret;
+   }
 
-   return CMD_RET_SUCCESS;
+   return err ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
 }
 
 static int do_adc_info(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/cmd/demo.c b/cmd/demo.c
index 571f562ec6..ebd5a241c3 100644
--- a/cmd/demo.c
+++ b/cmd/demo.c
@@ -64,20 +64,23 @@ static int do_demo_light(struct cmd_tbl *cmdtp, int flag, 
int argc,
 int do_demo_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
struct udevice *dev;
-   int i, ret;
+   int i, ret, err = 0;
 
puts("Demo uclass entries:\n");
 
-   for (i = 0, ret = uclass_first_device(UCLASS_DEMO, );
+   for (i = 0, ret = uclass_first_device_check(UCLASS_DEMO, );
 dev;
-ret = uclass_next_device()) {
-   printf("entry %d - instance %08x, ops %08x, plat %08x\n",
+ret = uclass_next_device_check()) {
+   printf("entry %d - instance %08x, ops %08x, plat %08x, status 
%i\n",
   i++, (uint)map_to_sysmem(dev),
   (uint)map_to_sysmem(dev->driver->ops),
-  (uint)map_to_sysmem(dev_get_plat(dev)));
+  (uint)map_to_sysmem(dev_get_plat(dev)),
+  ret);
+   if (ret)
+   err = ret;
}
 
-   return cmd_process_error(cmdtp, ret);
+   return cmd_process_error(cmdtp, err);
 }
 
 static struct cmd_tbl demo_commands[] = {
diff --git a/cmd/gpio.c b/cmd/gpio.c
index 53e9ce666f..f4565982ec 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -77,17 +77,24 @@ static int do_gpio_status(bool all, const char *gpio_name)
struct udevice *dev;
int banklen;
int flags;
-   int ret;
+   int ret, err = 0;
 
flags = 0;
if (gpio_name && !*gpio_name)
gpio_name = NULL;
-   for (ret = uclass_first_device(UCLASS_GPIO, );
+   for (ret = uclass_first_device_check(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+ret = uclass_next_device_check()) {
const char *bank_name;
int num_bits;
 
+   if (ret) {
+   printf("GPIO device %s probe error %i\n",
+  dev->name, ret);
+   err = ret;
+   continue;
+   }
+
flags |= FLAG_SHOW_BANK;
if (all)
flags |= FLAG_SHOW_ALL;
@@ -120,7 +127,7 @@ static int do_gpio_status(bool all, const char *gpio_name)
flags |= FLAG_SHOW_NEWLINE;
}
 
-   return ret;
+   return err;
 }
 #endif
 
diff --git a/cmd/pmic.c b/cmd/pmic.c
index 0cb44d0740..49a405fa29 100644
--- a/cmd/pmic.c
+++ b/cmd/pmic.c
@@ -51,25 +51,26 @@ static int do_list(struct cmd_tbl *cmdtp, int flag, int 
argc,
   char *const argv[])
 {
struct udevice *dev;
-   int ret;
+   int ret, err = 0;
 
printf("| %-*.*s| %-*.*s| %s @ %s\n",
   LIMIT_DEV, LIMIT_DEV, "Name",
   LIMIT_PARENT, LIMIT_PARENT, "Parent name",
   "Parent uclass", "seq");
 
-   for (ret = uclass_first_device(UCLASS_PMIC, ); dev;
-ret = uclass_next_device()) {
+   for (ret = uclass_first_device_check(UCLASS_PMIC, ); dev;
+ret = uclass_next_device_chec

[PATCH v6 07/20] video: ipuv3: Fix error handling when getting the display

2022-10-12 Thread Michal Suchanek
The code checks that uclass_first_device returned a device but the
returned value that is assigned is never used. Use
uclass_first_device_err instead, and move the error return outside of
the if block.

Fixes: f4ec1ae08e ("mxc_ipuv3_fb.c: call display_enable")
Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
 drivers/video/imx/mxc_ipuv3_fb.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 49bbeefdd8..8b01a1be11 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -609,12 +609,11 @@ static int ipuv3_video_probe(struct udevice *dev)
return ret;
 
 #if defined(CONFIG_DISPLAY)
-   ret = uclass_first_device(UCLASS_DISPLAY, _dev);
-   if (disp_dev) {
+   ret = uclass_first_device_err(UCLASS_DISPLAY, _dev);
+   if (!ret)
ret = display_enable(disp_dev, 16, NULL);
-   if (ret < 0)
-   return ret;
-   }
+   if (ret < 0)
+   return ret;
 #endif
if (CONFIG_IS_ENABLED(PANEL)) {
struct udevice *panel_dev;
-- 
2.37.3



[PATCH v6 06/20] stdio: Fix class iteration in stdio_add_devices()

2022-10-12 Thread Michal Suchanek
There is a complaint in the code that iterates keyboards that we don't
have the _check variant of class iterator but we in fact do, use it.

In the code that iterates video devices there is an attempt to print
errors but the simple iterator does not return a device when there is an
error. Use the _check variant of the iterator as well.

Also format error messages consistently.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v6:
 - drop errno_str
 - fix dev vs vdev in video error print
---
 common/stdio.c | 32 +---
 1 file changed, 13 insertions(+), 19 deletions(-)

diff --git a/common/stdio.c b/common/stdio.c
index 13083842cb..e316a355fa 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -314,7 +314,6 @@ int stdio_init_tables(void)
 int stdio_add_devices(void)
 {
struct udevice *dev;
-   struct uclass *uc;
int ret;
 
if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
@@ -324,24 +323,18 @@ int stdio_add_devices(void)
 * have a list of input devices to start up in the stdin
 * environment variable. That work probably makes more sense
 * when stdio itself is converted to driver model.
-*
-* TODO(s...@chromium.org): Convert changing
-* uclass_first_device() etc. to return the device even on
-* error. Then we could use that here.
 */
-   ret = uclass_get(UCLASS_KEYBOARD, );
-   if (ret)
-   return ret;
 
/*
 * Don't report errors to the caller - assume that they are
 * non-fatal
 */
-   uclass_foreach_dev(dev, uc) {
-   ret = device_probe(dev);
+   for (ret = uclass_first_device_check(UCLASS_KEYBOARD, );
+   dev;
+   ret = uclass_next_device_check()) {
if (ret)
-   printf("Failed to probe keyboard '%s'\n",
-  dev->name);
+   printf("%s: Failed to probe keyboard '%s' 
(ret=%d)\n",
+  __func__, dev->name, ret);
}
}
 #if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
@@ -361,13 +354,14 @@ int stdio_add_devices(void)
int ret;
 
if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
-   for (ret = uclass_first_device(UCLASS_VIDEO, );
-vdev;
-ret = uclass_next_device())
-   ;
-   if (ret)
-   printf("%s: Video device failed (ret=%d)\n",
-  __func__, ret);
+   for (ret = uclass_first_device_check(UCLASS_VIDEO,
+);
+   vdev;
+   ret = uclass_next_device_check()) {
+   if (ret)
+   printf("%s: Failed to probe video 
device '%s' (ret=%d)\n",
+  __func__, vdev->name, ret);
+   }
}
if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
IS_ENABLED(CONFIG_CMD_BMP))
-- 
2.37.3



[PATCH v6 08/20] w1: Fix bus counting in w1_get_bus

2022-10-12 Thread Michal Suchanek
Use uclass_first_device_check/uclass_next_device_check to correctly
count buses that fail to probe.

Fixes: d3e19cf919 ("w1: Add 1-Wire uclass")
Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
 drivers/w1/w1-uclass.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c
index 52b519c21d..de4f25bcf9 100644
--- a/drivers/w1/w1-uclass.c
+++ b/drivers/w1/w1-uclass.c
@@ -16,6 +16,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -182,24 +183,25 @@ static int w1_enumerate(struct udevice *bus)
 int w1_get_bus(int busnum, struct udevice **busp)
 {
int ret, i = 0;
-
struct udevice *dev;
 
-   for (ret = uclass_first_device(UCLASS_W1, );
-dev && !ret;
-ret = uclass_next_device(), i++) {
+   for (ret = uclass_first_device_check(UCLASS_W1, );
+   dev;
+   ret = uclass_next_device_check(), i++) {
if (i == busnum) {
+   if (ret) {
+   debug("Cannot probe w1 bus %d: %d (%s)\n",
+ busnum, ret, errno_str(ret));
+   return ret;
+   }
*busp = dev;
return 0;
}
}
 
-   if (!ret) {
-   debug("Cannot find w1 bus %d\n", busnum);
-   ret = -ENODEV;
-   }
+   debug("Cannot find w1 bus %d\n", busnum);
 
-   return ret;
+   return -ENODEV;
 }
 
 u8 w1_get_device_family(struct udevice *dev)
-- 
2.37.3



[PATCH v6 05/20] usb: ether: Fix error handling in usb_ether_init

2022-10-12 Thread Michal Suchanek
The code checks the return value from uclass_first_device as well as
that the device exists but it passes on the return value which may be
zero if there are no gadget devices. Just check that a device was
returned and return -ENODEV otherwise.

Also remove the dev variable which is not really used for anything.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
 drivers/usb/gadget/ether.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 6ce389de9f..43aec7ffa7 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2636,18 +2636,17 @@ static const struct eth_ops usb_eth_ops = {
 
 int usb_ether_init(void)
 {
-   struct udevice *dev;
struct udevice *usb_dev;
int ret;
 
-   ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, _dev);
-   if (!usb_dev || ret) {
+   uclass_first_device(UCLASS_USB_GADGET_GENERIC, _dev);
+   if (!usb_dev) {
pr_err("No USB device found\n");
-   return ret;
+   return -ENODEV;
}
 
-   ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", );
-   if (!dev || ret) {
+   ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", NULL);
+   if (ret) {
pr_err("usb - not able to bind usb_ether device\n");
return ret;
}
-- 
2.37.3



[PATCH v6 04/20] bootstd: Fix listing boot devices

2022-10-12 Thread Michal Suchanek
bootdev_list() uses uclass_*_device_err() to iterate devices.
However, the only value _err adds is returning an error when the device
pointer is null, and that's checked anyway.

Also there is some intent to report errors, and that's what
uclass_*_device_check() is for, use it.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v6: Drop errno_str
---
 boot/bootdev-uclass.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 13ac69eb39..9d98bee454 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -195,7 +195,7 @@ void bootdev_list(bool probe)
printf("Seq  Probed  Status  UclassName\n");
printf("---  --  --    --\n");
if (probe)
-   ret = uclass_first_device_err(UCLASS_BOOTDEV, );
+   ret = uclass_first_device_check(UCLASS_BOOTDEV, );
else
ret = uclass_find_first_device(UCLASS_BOOTDEV, );
for (i = 0; dev; i++) {
@@ -204,7 +204,7 @@ void bootdev_list(bool probe)
   ret ? simple_itoa(ret) : "OK",
   dev_get_uclass_name(dev_get_parent(dev)), dev->name);
if (probe)
-   ret = uclass_next_device_err();
+   ret = uclass_next_device_check();
else
ret = uclass_find_next_device();
}
-- 
2.37.3



[PATCH v6 02/20] dm: treewide: Do not opencode uclass_probe_all()

2022-10-12 Thread Michal Suchanek
We already have a function for probing all devices of a specific class,
use it.

Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
 drivers/cpu/cpu-uclass.c   | 20 
 drivers/virtio/virtio-uclass.c | 15 +--
 test/dm/core.c | 17 +++--
 test/test-main.c   | 11 +--
 4 files changed, 9 insertions(+), 54 deletions(-)

diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index 71e5900d70..a754832526 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -20,25 +20,13 @@ DECLARE_GLOBAL_DATA_PTR;
 
 int cpu_probe_all(void)
 {
-   struct udevice *cpu;
-   int ret;
+   int ret = uclass_probe_all(UCLASS_CPU);
 
-   ret = uclass_first_device(UCLASS_CPU, );
if (ret) {
-   debug("%s: No CPU found (err = %d)\n", __func__, ret);
-   return ret;
-   }
-
-   while (cpu) {
-   ret = uclass_next_device();
-   if (ret) {
-   debug("%s: Error while probing CPU (err = %d)\n",
- __func__, ret);
-   return ret;
-   }
+   debug("%s: Error while probing CPUs (err = %d %s)\n",
+ __func__, ret, errno_str(ret));
}
-
-   return 0;
+   return ret;
 }
 
 int cpu_is_current(struct udevice *cpu)
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index 9e2d0e06a1..da4f2f26a6 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -183,21 +183,8 @@ void virtio_driver_features_init(struct virtio_dev_priv 
*priv,
 
 int virtio_init(void)
 {
-   struct udevice *bus;
-   int ret;
-
/* Enumerate all known virtio devices */
-   ret = uclass_first_device(UCLASS_VIRTIO, );
-   if (ret)
-   return ret;
-
-   while (bus) {
-   ret = uclass_next_device();
-   if (ret)
-   break;
-   }
-
-   return ret;
+   return uclass_probe_all(UCLASS_VIRTIO);
 }
 
 static int virtio_uclass_pre_probe(struct udevice *udev)
diff --git a/test/dm/core.c b/test/dm/core.c
index fd4d756972..84eb76ed5f 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -512,23 +512,15 @@ static int dm_test_leak(struct unit_test_state *uts)
int i;
 
for (i = 0; i < 2; i++) {
-   struct udevice *dev;
int ret;
-   int id;
 
dm_leak_check_start(uts);
 
ut_assertok(dm_scan_plat(false));
ut_assertok(dm_scan_fdt(false));
 
-   /* Scanning the uclass is enough to probe all the devices */
-   for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) {
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
-   ut_assertok(ret);
-   }
+   ret = uclass_probe_all(UCLASS_TEST);
+   ut_assertok(ret);
 
ut_assertok(dm_leak_check_end(uts));
}
@@ -653,10 +645,7 @@ static int dm_test_children(struct unit_test_state *uts)
ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
 
/* Probe everything */
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
+   ret = uclass_probe_all(UCLASS_TEST);
ut_assertok(ret);
 
ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
diff --git a/test/test-main.c b/test/test-main.c
index d74df297c4..a98a77d68f 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -165,16 +165,7 @@ static int dm_test_post_run(struct unit_test_state *uts)
 /* Ensure all the test devices are probed */
 static int do_autoprobe(struct unit_test_state *uts)
 {
-   struct udevice *dev;
-   int ret;
-
-   /* Scanning the uclass is enough to probe all the devices */
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
-
-   return ret;
+   return uclass_probe_all(UCLASS_TEST);
 }
 
 /*
-- 
2.37.3



[PATCH v6 01/20] dm: core: Fix uclass_probe_all to really probe all devices

2022-10-12 Thread Michal Suchanek
uclass_probe_all uses uclass_first_device/uclass_next_device assigning
the return value.

The interface for getting meaningful error is
uclass_first_device_check/uclass_next_device_check, use it.

Also do not stop iteration when an error is encountered. Probing all
devices includes those that happen to be after a failing device in the
uclass order.

Fixes: a59153dfeb ("dm: core: add function uclass_probe_all() to probe all 
devices")
Signed-off-by: Michal Suchanek 
---
v6: add test
---
 drivers/core/uclass.c | 12 +---
 test/dm/test-fdt.c| 19 +++
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 08d9ed82de..a591e22403 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -799,20 +799,18 @@ int uclass_pre_remove_device(struct udevice *dev)
 int uclass_probe_all(enum uclass_id id)
 {
struct udevice *dev;
-   int ret;
+   int ret, err;
 
-   ret = uclass_first_device(id, );
-   if (ret || !dev)
-   return ret;
+   err = uclass_first_device_check(id, );
 
/* Scanning uclass to probe all devices */
while (dev) {
-   ret = uclass_next_device();
+   ret = uclass_next_device_check();
if (ret)
-   return ret;
+   err = ret;
}
 
-   return 0;
+   return err;
 }
 
 int uclass_id_count(enum uclass_id id)
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 012f2f455f..1f14513d9f 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -392,10 +392,10 @@ DM_TEST(dm_test_fdt_offset,
UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE);
 
 /**
- * Test various error conditions with uclass_first_device() and
- * uclass_next_device()
+ * Test various error conditions with uclass_first_device(),
+ * uclass_next_device(), and uclass_probe_all()
  */
-static int dm_test_first_next_device(struct unit_test_state *uts)
+static int dm_test_first_next_device_probeall(struct unit_test_state *uts)
 {
struct dm_testprobe_pdata *pdata;
struct udevice *dev, *parent = NULL;
@@ -428,9 +428,20 @@ static int dm_test_first_next_device(struct 
unit_test_state *uts)
device_remove(parent, DM_REMOVE_NORMAL);
ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, ));
 
+   /* Now that broken devices are set up test probe_all */
+   device_remove(parent, DM_REMOVE_NORMAL);
+   /* There are broken devices so an error should be returned */
+   ut_assert(uclass_probe_all(UCLASS_TEST_PROBE) < 0);
+   /* but non-error device should be probed nonetheless */
+   ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 2, ));
+   ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED);
+   ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 3, ));
+   ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED);
+
return 0;
 }
-DM_TEST(dm_test_first_next_device, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+DM_TEST(dm_test_first_next_device_probeall,
+   UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 
 /* Test iteration through devices in a uclass */
 static int dm_test_uclass_foreach(struct unit_test_state *uts)
-- 
2.37.3



[PATCH v6 03/20] dm: pci: Fix device PCI iteration

2022-10-12 Thread Michal Suchanek
When there is no PCI bus uclass_first_device will return no bus and no
error which will result in pci_find_first_device calling
skip_to_next_device with no bus, and the bus is only checked at the end
of the while cycle, not the beginning.

Fixes: 76c3fbcd3d ("dm: pci: Add a way to iterate through all PCI devices")
Signed-off-by: Michal Suchanek 
Reviewed-by: Simon Glass 
---
v6: Move dropping the use of uclass iterator return value to later patch
---
 drivers/pci/pci-uclass.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 058b2f6359..5cff81ac44 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1217,7 +1217,7 @@ static int skip_to_next_device(struct udevice *bus, 
struct udevice **devp)
 * Scan through all the PCI controllers. On x86 there will only be one
 * but that is not necessarily true on other hardware.
 */
-   do {
+   while (bus) {
device_find_first_child(bus, );
if (dev) {
*devp = dev;
@@ -1226,7 +1226,7 @@ static int skip_to_next_device(struct udevice *bus, 
struct udevice **devp)
ret = uclass_next_device();
if (ret)
return ret;
-   } while (bus);
+   }
 
return 0;
 }
-- 
2.37.3



[PATCH 2/2] spl: spl_legacy: Fix printing image name

2022-10-12 Thread Michal Suchanek
image_set_name does not terminate the name in the image header.

Then is should not be assument it's nul terminated. image_print_contents
correctly print only IH_NMLEN characters.

Fix printing the unterminated field in spl_parse_legacy_header. The
format specifies the minimum printed length, not maximum.

Signed-off-by: Michal Suchanek 
---

 common/spl/spl_legacy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c
index b3624dfbb7..11c459254b 100644
--- a/common/spl/spl_legacy.c
+++ b/common/spl/spl_legacy.c
@@ -55,7 +55,7 @@ int spl_parse_legacy_header(struct spl_image_info *spl_image,
spl_image->os = image_get_os(header);
spl_image->name = image_get_name(header);
debug(SPL_TPL_PROMPT
- "payload image: %32s load addr: 0x%lx size: %d\n",
+ "payload image: %.*s load addr: 0x%lx size: %d\n", IH_NMLEN,
  spl_image->name, spl_image->load_addr, spl_image->size);
 
return 0;
-- 
2.37.3



[PATCH 1/2] image: Suppress string truncation warning

2022-10-12 Thread Michal Suchanek
In file included from ../tools/imagetool.h:24,
 from ../tools/default_image.c:16:
In function ‘image_set_name’,
inlined from ‘image_set_header’ at ../tools/default_image.c:133:2:
../include/image.h:786:9: warning: ‘strncpy’ specified bound 32 equals 
destination size [-Wstringop-truncation]
  786 | strncpy(image_get_name(hdr), name, IH_NMLEN);
  | ^~~~

There is no standard function that can be used to make the copy without
a warning.

Signed-off-by: Michal Suchanek 
---

 include/image.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/image.h b/include/image.h
index d7d6a3fe5b..e08ef6ed55 100644
--- a/include/image.h
+++ b/include/image.h
@@ -783,7 +783,14 @@ image_set_hdr_b(comp)  /* image_set_comp */
 
 static inline void image_set_name(struct legacy_img_hdr *hdr, const char *name)
 {
+#if defined(__GNUC__) && (__GNUC__ > 7)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
strncpy(image_get_name(hdr), name, IH_NMLEN);
+#if defined(__GNUC__) && (__GNUC__ > 7)
+#pragma GCC diagnostic pop
+#endif
 }
 
 int image_check_hcrc(const struct legacy_img_hdr *hdr);
-- 
2.37.3



[PATCH v2 2/2] common: board_f: Print information for all sysresets

2022-10-10 Thread Michal Suchanek
Boards can have multiple sysresets, iterate all when printing sysreset
info.

Fixes: 23471aed5c ("board_f: Add reset status printing")
Signed-off-by: Michal Suchanek 
---

v2:
 - do not use errno_str
 - rename flag variable
---
 common/board_f.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/common/board_f.c b/common/board_f.c
index 5f1711181c..4355d1c82d 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -146,20 +146,27 @@ static int print_resetinfo(void)
 {
struct udevice *dev;
char status[256];
+   bool status_printed = false;
int ret;
 
-   ret = uclass_first_device_err(UCLASS_SYSRESET, );
-   if (ret) {
-   debug("%s: No sysreset device found (error: %d)\n",
- __func__, ret);
-   /* Not all boards have sysreset drivers available during early
-* boot, so don't fail if one can't be found.
-*/
-   return 0;
-   }
+   /* Not all boards have sysreset drivers available during early
+* boot, so don't fail if one can't be found.
+*/
+   for (ret = uclass_first_device_check(UCLASS_SYSRESET, ); dev;
+   ret = uclass_next_device_check()) {
+   if (ret) {
+   debug("%s: %s sysreset device (error: %d)\n",
+ __func__, dev->name, ret);
+   continue;
+   }
 
-   if (!sysreset_get_status(dev, status, sizeof(status)))
-   printf("%s", status);
+   if (!sysreset_get_status(dev, status, sizeof(status))) {
+   printf("%s%s", status_printed ? " " : "", status);
+   status_printed = true;
+   }
+   }
+   if (status_printed)
+   printf("\n");
 
return 0;
 }
-- 
2.37.3



[PATCH v2 1/2] sandbox: Initialize sysreset before relocation

2022-10-10 Thread Michal Suchanek
Without this the early sysreset code cannot be tested.

Signed-off-by: Michal Suchanek 
---
v2: use u-boot,dm-pre-proper rather than u-boot,dm-pre-reloc - sandbox
SPL cannot build otherwise
---
 arch/sandbox/dts/sandbox.dtsi | 1 +
 arch/sandbox/dts/test.dts | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index de7a218f45..14c3f54563 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -239,6 +239,7 @@
 
reset@1 {
compatible = "sandbox,reset";
+   u-boot,dm-pre-proper;
};
 
rng {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 4ee471238e..88ddc7c4da 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1121,10 +1121,12 @@
 
reset@0 {
compatible = "sandbox,warm-reset";
+   u-boot,dm-pre-proper;
};
 
reset@1 {
compatible = "sandbox,reset";
+   u-boot,dm-pre-proper;
};
 
resetc: reset-ctl {
-- 
2.37.3



[PATCH v5 00/15] Do not stop uclass iteration on error

2022-09-28 Thread Michal Suchanek
Hello,

this patch series fixes the simple uclass iterators to be usable for
iterating uclasses even if some devices fail to probe.

Before this series when a probe error happens an error is returned
without any device pointer, and iteration cannot continue to devices
that happen to be after the failing device in the uclass list.

This is rarely expected, nor clearly documented, and for the most part
not useful in any way.

All but the last patch are new in v4 removing problematic iterator use.

v5:

Split off patches that can be applied independently

Fix uclass_foreach_dev_probe, pci_sriov_init, and sysinfo_get to work
after the uclass_first_device_err change.

Document that uclass_first_device_err and uclass_first_device_check can
return non-activated device on error.

Consolidate multiple similar cleanups into one patch.

Thanks

Michal

Michal Suchanek (15):
  dm: core: Fix uclass_probe_all to really probe all devices
  dm: treewide: Do not opencode uclass_probe_all()
  dm: pci: Fix device PCI iteration
  bootstd: Fix listing boot devices
  usb: ether: Fix error handling in usb_ether_init
  stdio: Fix class iteration in stdio_add_devices()
  video: ipuv3: Fix error handling when getting the display
  w1: Fix bus counting in w1_get_bus
  cmd: List all uclass devices regardless of probe error
  dm: treewide: Use uclass_first_device_err when accessing one device
  dm: treewide: Use uclass_next_device_err when accessing second device
  dm: blk: Do not use uclass_next_device_err
  dm: core: Switch uclass_*_device_err to use uclass_*_device_check
  dm: treewide: Do not use the return value of simple uclass iterator
  dm: core: Do not stop uclass iteration on error

 arch/arm/mach-k3/j721s2_init.c|  2 +-
 arch/arm/mach-omap2/am33xx/board.c|  4 +-
 arch/x86/cpu/broadwell/cpu.c  |  4 +-
 arch/x86/cpu/intel_common/cpu.c   |  4 +-
 arch/x86/lib/pinctrl_ich6.c   |  4 +-
 board/atmel/common/mac_eeprom.c   |  2 +-
 board/intel/cougarcanyon2/cougarcanyon2.c |  4 +-
 boot/bootdev-uclass.c |  7 +--
 cmd/adc.c | 22 -
 cmd/demo.c| 16 ---
 cmd/gpio.c| 15 --
 cmd/pmic.c| 15 +++---
 cmd/regulator.c   | 13 +++---
 cmd/virtio.c  |  9 ++--
 common/stdio.c| 33 ++---
 drivers/block/blk-uclass.c| 16 +++
 drivers/core/uclass.c | 56 ---
 drivers/cpu/cpu-uclass.c  | 20 ++--
 drivers/dma/dma-uclass.c  |  7 ++-
 drivers/gpio/gpio-uclass.c| 14 +++---
 drivers/mmc/omap_hsmmc.c  |  2 +-
 drivers/pci/pci-uclass.c  | 26 ---
 drivers/serial/serial-uclass.c|  2 +-
 drivers/serial/serial_bcm283x_mu.c|  2 +-
 drivers/serial/serial_bcm283x_pl011.c |  2 +-
 drivers/sysinfo/sysinfo-uclass.c  | 10 +++-
 drivers/sysreset/sysreset_ast.c   |  2 +-
 drivers/usb/gadget/ether.c| 11 ++---
 drivers/video/exynos/exynos_fb.c  | 24 --
 drivers/video/imx/mxc_ipuv3_fb.c  |  9 ++--
 drivers/video/mali_dp.c   |  2 +-
 drivers/video/stm32/stm32_dsi.c   |  6 ++-
 drivers/video/tegra124/dp.c   |  7 +--
 drivers/virtio/virtio-uclass.c| 15 +-
 drivers/w1/w1-uclass.c| 29 ++--
 include/dm/uclass.h   | 49 ++--
 lib/acpi/acpi_table.c |  2 +-
 lib/efi_loader/efi_gop.c  |  2 +-
 net/eth-uclass.c  |  6 ++-
 test/boot/bootmeth.c  |  2 +-
 test/dm/acpi.c| 14 +++---
 test/dm/core.c| 27 +++
 test/dm/devres.c  |  4 +-
 test/dm/i2c.c |  8 ++--
 test/dm/test-fdt.c| 27 ---
 test/dm/virtio_device.c   |  8 ++--
 test/dm/virtio_rng.c  |  2 +-
 test/fuzz/cmd_fuzz.c  |  2 +-
 test/fuzz/virtio.c|  2 +-
 test/test-main.c  | 11 +
 50 files changed, 269 insertions(+), 313 deletions(-)

--
2.37.3



[PATCH] rockchip: clk: pll: Fix constant typo

2022-09-28 Thread Michal Suchanek
Fixes: bbda2ed584 ("rockchip: clk: pll: add common pll setting funcs")
Signed-off-by: Michal Suchanek 
---

 drivers/clk/rockchip/clk_pll.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/rockchip/clk_pll.c b/drivers/clk/rockchip/clk_pll.c
index 8d2aaf5b84..09b97cf57a 100644
--- a/drivers/clk/rockchip/clk_pll.c
+++ b/drivers/clk/rockchip/clk_pll.c
@@ -31,7 +31,7 @@ static struct rockchip_pll_rate_table rockchip_auto_table;
 #define RK3036_PLLCON1_DSMPD_SHIFT 12
 #define RK3036_PLLCON2_FRAC_MASK   0xff
 #define RK3036_PLLCON2_FRAC_SHIFT  0
-#define RK3036_PLLCON1_PWRDOWN_SHIT13
+#define RK3036_PLLCON1_PWRDOWN_SHIFT   13
 
 #define MHZ100
 #define KHZ1000
@@ -207,7 +207,7 @@ static int rk3036_pll_set_rate(struct rockchip_pll_clock 
*pll,
 
/* Power down */
rk_setreg(base + pll->con_offset + 0x4,
- 1 << RK3036_PLLCON1_PWRDOWN_SHIT);
+ 1 << RK3036_PLLCON1_PWRDOWN_SHIFT);
 
rk_clrsetreg(base + pll->con_offset,
 (RK3036_PLLCON0_POSTDIV1_MASK |
@@ -231,7 +231,7 @@ static int rk3036_pll_set_rate(struct rockchip_pll_clock 
*pll,
 
/* Power Up */
rk_clrreg(base + pll->con_offset + 0x4,
- 1 << RK3036_PLLCON1_PWRDOWN_SHIT);
+ 1 << RK3036_PLLCON1_PWRDOWN_SHIFT);
 
/* waiting for pll lock */
while (!(readl(base + pll->con_offset + 0x4) & (1 << pll->lock_shift)))
-- 
2.37.3



[PATCH] clk: change return type of clk_get_parent_rate from long long to ulong

2022-09-28 Thread Michal Suchanek
All functions getting and setting clock rate use ulong for rate, only
clk_get_parent_rate is an exception. Change the return value to match
other clock rate funcrions.

Most users directly assign the rate to unsigned long anyway, and the few
users that use u64 (not s64) multiply the rate so they may need the
extra bits for the result in their use case.

Fixes: 4aa78300a0 ("dm: clk: Define clk_get_parent_rate() for clk operations")
Signed-off-by: Michal Suchanek 
---

 drivers/clk/clk-uclass.c | 2 +-
 include/clk.h| 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index b89c77bf79..4678ed43af 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -505,7 +505,7 @@ struct clk *clk_get_parent(struct clk *clk)
return pclk;
 }
 
-long long clk_get_parent_rate(struct clk *clk)
+ulong clk_get_parent_rate(struct clk *clk)
 {
const struct clk_ops *ops;
struct clk *pclk;
diff --git a/include/clk.h b/include/clk.h
index 76bb64bb5e..41a8fb3419 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -444,7 +444,7 @@ struct clk *clk_get_parent(struct clk *clk);
  *
  * Return: clock rate in Hz, or -ve error code.
  */
-long long clk_get_parent_rate(struct clk *clk);
+ulong clk_get_parent_rate(struct clk *clk);
 
 /**
  * clk_round_rate() - Adjust a rate to the exact rate a clock can provide
@@ -577,7 +577,7 @@ static inline struct clk *clk_get_parent(struct clk *clk)
return ERR_PTR(-ENOSYS);
 }
 
-static inline long long clk_get_parent_rate(struct clk *clk)
+static inline ulong clk_get_parent_rate(struct clk *clk)
 {
return -ENOSYS;
 }
-- 
2.37.3



[PATCH v5 15/15] dm: core: Do not stop uclass iteration on error

2022-09-27 Thread Michal Suchanek
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 
---
v2: - Fix up tests
v3: - Fix up API doc
- Correctly forward error from uclass_get
- Do not return an error when last device fails to probe
- Drop redundant initialization
- Wrap at 80 columns
v4: - change return value to void
- further simplify iteration
---
 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 b7d11bdd23..6dec6a3973 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 return first device in the uclass that
+ * probes successfully.
+ */
+static void _uclass_next_device(struct udevice *dev, struct udevice **devp)
+{
+   for (; dev; uclass_find_next_device()) {
+   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, );
-   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();
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   uclass_find_next_device();
+   _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 b1c016ef9f..ee15c92063 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 84eb76ed5f..7f3f8d183b 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, );
+   for (ret = uclass_first_device_check(UCLASS_TEST, );
 dev;
-ret = uclass_next_device()) {
+ret = uclass_next_device_check()) {
ut_assert(!ret);
-   ut_assert(dev);
ut_assert(device_active(dev));
}
 
@@ -1112,11 +,10 @@ static int dm_test_uclass_devices_get_by_name(struct 
unit_test_state *uts)
 * this will fail on checking

[PATCH v5 13/15] dm: core: Switch uclass_*_device_err to use uclass_*_device_check

2022-09-27 Thread Michal Suchanek
The _err variant iterators use the simple iterators without suffix as
basis.

However, there is no user that uclass_next_device_err for iteration,
many users of uclass_first_device_err use it to get the first and
(assumed) only device of an uclass, and a couple that use
uclass_next_device_err to get the device following a known device in the
uclass list.

While there are some truly singleton device classes in which more than
one device cannot exist these are quite rare, and most classes can have
multiple devices even if it is not the case on the SoC's EVB.

In a later patch the simple iterators will be updated to not stop on
error and return next device instead. With this in many cases the code
that expects the first device or an error if it fails to probe may get
the next device instead. Use the _check iterators as the basis of _err
iterators to preserve the old behavior.

This is problematic for eth_get_dev: it relies on the broken behavior
that returns an error but not the device on which the error happened
which gives the caller no reasonable way to report or handle the error.
With this change the device is returned but eth_get_dev stores the
returned device pointer directly in a global state without checking the
return value. Unset the pointer again in the error case.

Do the same for sysinfo_get because it is not clear how exactly the
sysinfo is used by some callers, and fix up a call to pci_get_bus that
checks the returned device and not the return value.

Switch uclass_foreach_dev_probe to the simple iterator - it does not
use the returned value, and did not give out the failing devices
previously.

Note in documentation that a non-activated device can be returned on
error.

Signed-off-by: Michal Suchanek 
---
v5: - udate documentation
- fix up a few more cases where device returned on error may cause
  problem
---
 drivers/core/uclass.c| 28 -
 drivers/pci/pci-uclass.c |  7 +++
 drivers/sysinfo/sysinfo-uclass.c | 10 -
 include/dm/uclass.h  | 36 ++--
 net/eth-uclass.c |  2 ++
 5 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index a591e22403..b7d11bdd23 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -586,19 +586,6 @@ int uclass_first_device(enum uclass_id id, struct udevice 
**devp)
return uclass_get_device_tail(dev, ret, devp);
 }
 
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
-{
-   int ret;
-
-   ret = uclass_first_device(id, devp);
-   if (ret)
-   return ret;
-   else if (!*devp)
-   return -ENODEV;
-
-   return 0;
-}
-
 int uclass_next_device(struct udevice **devp)
 {
struct udevice *dev = *devp;
@@ -611,11 +598,24 @@ int uclass_next_device(struct udevice **devp)
return uclass_get_device_tail(dev, ret, devp);
 }
 
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
+{
+   int ret;
+
+   ret = uclass_first_device_check(id, devp);
+   if (ret)
+   return ret;
+   else if (!*devp)
+   return -ENODEV;
+
+   return 0;
+}
+
 int uclass_next_device_err(struct udevice **devp)
 {
int ret;
 
-   ret = uclass_next_device(devp);
+   ret = uclass_next_device_check(devp);
if (ret)
return ret;
else if (!*devp)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 00e3828d95..2aa1043604 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1768,10 +1768,9 @@ int pci_sriov_init(struct udevice *pdev, int vf_en)
 
bdf = dm_pci_get_bdf(pdev);
 
-   pci_get_bus(PCI_BUS(bdf), );
-
-   if (!bus)
-   return -ENODEV;
+   ret = pci_get_bus(PCI_BUS(bdf), );
+   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 c5cc3cb959..10194d0e14 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 f6c0110b06..b1c016ef9f 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -332,17 +332,6 @@ int uclass_get_device_by_driver(enum uclass_id id, const 
struct driver *drv,
  */
 int uclass_first_device(enum uclass_id id, struct udevice **devp);
 
-/**
- * uclass_first_device_err() - Get the first

[PATCH v5 08/15] w1: Fix bus counting in w1_get_bus

2022-09-27 Thread Michal Suchanek
Use uclass_first_device_check/uclass_next_device_check to correctly
count buses that fail to probe.

Fixes: d3e19cf919 ("w1: Add 1-Wire uclass")
Signed-off-by: Michal Suchanek 
---
 drivers/w1/w1-uclass.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c
index 52b519c21d..de4f25bcf9 100644
--- a/drivers/w1/w1-uclass.c
+++ b/drivers/w1/w1-uclass.c
@@ -16,6 +16,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -182,24 +183,25 @@ static int w1_enumerate(struct udevice *bus)
 int w1_get_bus(int busnum, struct udevice **busp)
 {
int ret, i = 0;
-
struct udevice *dev;
 
-   for (ret = uclass_first_device(UCLASS_W1, );
-dev && !ret;
-ret = uclass_next_device(), i++) {
+   for (ret = uclass_first_device_check(UCLASS_W1, );
+   dev;
+   ret = uclass_next_device_check(), i++) {
if (i == busnum) {
+   if (ret) {
+   debug("Cannot probe w1 bus %d: %d (%s)\n",
+ busnum, ret, errno_str(ret));
+   return ret;
+   }
*busp = dev;
return 0;
}
}
 
-   if (!ret) {
-   debug("Cannot find w1 bus %d\n", busnum);
-   ret = -ENODEV;
-   }
+   debug("Cannot find w1 bus %d\n", busnum);
 
-   return ret;
+   return -ENODEV;
 }
 
 u8 w1_get_device_family(struct udevice *dev)
-- 
2.37.3



[PATCH v5 14/15] dm: treewide: Do not use the return value of simple uclass iterator

2022-09-27 Thread Michal Suchanek
uclass_first_device/uclass_next_device return value will be removed,
don't use it.

With the current implementation bus is equivalent to !ret. It i
redundant to check both, ret check can be replaced with bus check, and
ret check inside the iteration is dead code.

Signed-off-by: Michal Suchanek 
---
v5: - consolidate multiple similar patches
---
 cmd/virtio.c   |  9 +++--
 drivers/dma/dma-uclass.c   |  7 +++
 drivers/gpio/gpio-uclass.c | 14 ++
 drivers/w1/w1-uclass.c |  9 ++---
 4 files changed, 14 insertions(+), 25 deletions(-)

diff --git a/cmd/virtio.c b/cmd/virtio.c
index ea3ed2e631..f7a2ef4313 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, );
-   if (ret)
+   uclass_first_device(UCLASS_VIRTIO, );
+   if (!bus)
return CMD_RET_FAILURE;
 
while (bus) {
device_foreach_child_probe(child, bus)
;
-   ret = uclass_next_device();
-   if (ret)
-   break;
+   uclass_next_device();
}
 
return CMD_RET_SUCCESS;
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 012609bb53..952cbc2170 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -209,10 +209,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 && !ret;
-ret = uclass_next_device()) {
+   for (uclass_first_device(UCLASS_DMA, ); dev;
+uclass_next_device()) {
struct dma_dev_priv *uc_priv;
 
uc_priv = dev_get_uclass_priv(dev);
@@ -228,7 +227,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 0ed32b7217..3a35f1e30a 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, );
+   for (uclass_first_device(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+uclass_next_device()) {
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)
@@ -121,12 +120,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, );
+   for (uclass_first_device(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+uclass_next_device()) {
int len;
 
uc_priv = dev_get_uclass_priv(dev);
@@ -154,7 +152,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/w1/w1-uclass.c b/drivers/w1/w1-uclass.c
index de4f25bcf9..a4247ecd62 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, );
-   !ret && dev;
+   for (uclass_first_device(UCLASS_W1_EEPROM, );
+   dev;
uclass_next_device()) {
-   if (ret || !dev) {
-   debug("cannot find w1 eeprom dev\n");
-   return -ENODEV;
-   }
 
if (dev_get_driver_data(dev) == family) {
*devp = dev;
-- 
2.37.3



[PATCH v5 12/15] dm: blk: Do not use uclass_next_device_err

2022-09-27 Thread Michal Suchanek
blk_first_device_err/blk_next_device_err uses
uclass_first_device_err/uclass_next_device_err for device iteration.

Although the function names superficially match the return value from
uclass_first_device_err/uclass_next_device_err is never used
meaningfully, and uclass_first_device/uclass_next_device works equally
well for this purpose.

In the following patch the semantic of
uclass_first_device_err/uclass_next_device_err will be changed to be
based on uclass_first_device_check/uclass_next_device_check breaking
this sole user that uses uclass_next_device_err for iteration.

Signed-off-by: Michal Suchanek 
---
 drivers/block/blk-uclass.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 21c5209bb6..676f2444bf 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -585,11 +585,9 @@ int blk_find_next(enum blk_flag_t flags, struct udevice 
**devp)
 
 int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp)
 {
-   int ret;
-
-   for (ret = uclass_first_device_err(UCLASS_BLK, devp);
-!ret;
-ret = uclass_next_device_err(devp)) {
+   for (uclass_first_device(UCLASS_BLK, devp);
+*devp;
+uclass_next_device(devp)) {
if (!blk_flags_check(*devp, flags))
return 0;
}
@@ -599,11 +597,9 @@ int blk_first_device_err(enum blk_flag_t flags, struct 
udevice **devp)
 
 int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp)
 {
-   int ret;
-
-   for (ret = uclass_next_device_err(devp);
-!ret;
-ret = uclass_next_device_err(devp)) {
+   for (uclass_next_device(devp);
+*devp;
+uclass_next_device(devp)) {
if (!blk_flags_check(*devp, flags))
return 0;
}
-- 
2.37.3



[PATCH v5 10/15] dm: treewide: Use uclass_first_device_err when accessing one device

2022-09-27 Thread Michal Suchanek
There is a number of users that use uclass_first_device to access the
first and (assumed) only device in uclass.

Some check the return value of uclass_first_device and also that a
device was returned which is exactly what uclass_first_device_err does.

Some are not checking that a device was returned and can potentially
crash if no device exists in the uclass. Finally there is one that
returns NULL on error either way.

Convert all of these to use uclass_first_device_err instead, the return
value will be removed from uclass_first_device in a later patch.

Also print the symbolic error when the return value is printed.

Signed-off-by: Michal Suchanek 
---
 arch/arm/mach-omap2/am33xx/board.c|  4 ++--
 arch/x86/cpu/broadwell/cpu.c  |  4 +---
 arch/x86/cpu/intel_common/cpu.c   |  4 +---
 arch/x86/lib/pinctrl_ich6.c   |  4 +---
 board/intel/cougarcanyon2/cougarcanyon2.c |  4 +---
 drivers/mmc/omap_hsmmc.c  |  2 +-
 drivers/serial/serial-uclass.c|  2 +-
 drivers/serial/serial_bcm283x_mu.c|  2 +-
 drivers/serial/serial_bcm283x_pl011.c |  2 +-
 drivers/sysreset/sysreset_ast.c   |  2 +-
 drivers/video/exynos/exynos_fb.c  | 24 ++-
 drivers/video/mali_dp.c   |  2 +-
 drivers/video/stm32/stm32_dsi.c   |  6 --
 drivers/video/tegra124/dp.c   |  7 ---
 lib/acpi/acpi_table.c |  2 +-
 lib/efi_loader/efi_gop.c  |  2 +-
 net/eth-uclass.c  |  4 ++--
 test/boot/bootmeth.c  |  2 +-
 test/dm/acpi.c| 14 ++---
 test/dm/devres.c  |  4 ++--
 test/dm/i2c.c |  8 
 test/dm/virtio_device.c   |  8 
 test/dm/virtio_rng.c  |  2 +-
 test/fuzz/cmd_fuzz.c  |  2 +-
 test/fuzz/virtio.c|  2 +-
 25 files changed, 55 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-omap2/am33xx/board.c 
b/arch/arm/mach-omap2/am33xx/board.c
index 7f1b84e466..f393ff9144 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -265,8 +265,8 @@ int arch_misc_init(void)
struct udevice *dev;
int ret;
 
-   ret = uclass_first_device(UCLASS_MISC, );
-   if (ret || !dev)
+   ret = uclass_first_device_err(UCLASS_MISC, );
+   if (ret)
return ret;
 
 #if defined(CONFIG_DM_ETH) && defined(CONFIG_USB_ETHER)
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index 2adcf4b242..7877961451 100644
--- a/arch/x86/cpu/broadwell/cpu.c
+++ b/arch/x86/cpu/broadwell/cpu.c
@@ -31,11 +31,9 @@ static int broadwell_init_cpu(void *ctx, struct event *event)
int ret;
 
/* Start up the LPC so we have serial */
-   ret = uclass_first_device(UCLASS_LPC, );
+   ret = uclass_first_device_err(UCLASS_LPC, );
if (ret)
return ret;
-   if (!dev)
-   return -ENODEV;
ret = cpu_set_flex_ratio_to_tdp_nominal();
if (ret)
return ret;
diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c
index 96d05e2eb3..8f489e6c65 100644
--- a/arch/x86/cpu/intel_common/cpu.c
+++ b/arch/x86/cpu/intel_common/cpu.c
@@ -61,11 +61,9 @@ int cpu_common_init(void)
/* Early chipset init required before RAM init can work */
uclass_first_device(UCLASS_NORTHBRIDGE, );
 
-   ret = uclass_first_device(UCLASS_LPC, );
+   ret = uclass_first_device_err(UCLASS_LPC, );
if (ret)
return ret;
-   if (!lpc)
-   return -ENODEV;
 
/* Cause the SATA device to do its early init */
uclass_first_device(UCLASS_AHCI, );
diff --git a/arch/x86/lib/pinctrl_ich6.c b/arch/x86/lib/pinctrl_ich6.c
index fd5e311b29..c93f245845 100644
--- a/arch/x86/lib/pinctrl_ich6.c
+++ b/arch/x86/lib/pinctrl_ich6.c
@@ -160,11 +160,9 @@ static int ich6_pinctrl_probe(struct udevice *dev)
u32 iobase = -1;
 
debug("%s: start\n", __func__);
-   ret = uclass_first_device(UCLASS_PCH, );
+   ret = uclass_first_device_err(UCLASS_PCH, );
if (ret)
return ret;
-   if (!pch)
-   return -ENODEV;
 
/*
 * Get the memory/io base address to configure every pins.
diff --git a/board/intel/cougarcanyon2/cougarcanyon2.c 
b/board/intel/cougarcanyon2/cougarcanyon2.c
index ce11eae59d..7f61ef8b36 100644
--- a/board/intel/cougarcanyon2/cougarcanyon2.c
+++ b/board/intel/cougarcanyon2/cougarcanyon2.c
@@ -21,11 +21,9 @@ int board_early_init_f(void)
struct udevice *pch;
int ret;
 
-   ret = uclass_first_device(UCLASS_PCH, );
+   ret = uclass_first_device_err(UCLASS_PCH, );
if (ret)
return ret;
-   if (!pch)
-   

[PATCH v5 11/15] dm: treewide: Use uclass_next_device_err when accessing second device

2022-09-27 Thread Michal Suchanek
There are a couple users of uclass_next_device return value that get the
first device by other means and use uclass_next_device assuming the
following device in the uclass is related to the first one.

Use uclass_next_device_err because the return value from
uclass_next_device will be removed in a later patch.

Signed-off-by: Michal Suchanek 
---
 arch/arm/mach-k3/j721s2_init.c  | 2 +-
 board/atmel/common/mac_eeprom.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-k3/j721s2_init.c b/arch/arm/mach-k3/j721s2_init.c
index 12da8136f9..dd0c7ba18f 100644
--- a/arch/arm/mach-k3/j721s2_init.c
+++ b/arch/arm/mach-k3/j721s2_init.c
@@ -164,7 +164,7 @@ void board_init_f(ulong dummy)
if (ret)
panic("DRAM 0 init failed: %d\n", ret);
 
-   ret = uclass_next_device();
+   ret = uclass_next_device_err();
if (ret)
panic("DRAM 1 init failed: %d\n", ret);
}
diff --git a/board/atmel/common/mac_eeprom.c b/board/atmel/common/mac_eeprom.c
index a723ba723c..4606008c69 100644
--- a/board/atmel/common/mac_eeprom.c
+++ b/board/atmel/common/mac_eeprom.c
@@ -56,7 +56,7 @@ int at91_set_eth1addr(int offset)
return ret;
 
/* attempt to obtain a second eeprom device */
-   ret = uclass_next_device();
+   ret = uclass_next_device_err();
if (ret)
return ret;
 
-- 
2.37.3



[PATCH v5 07/15] video: ipuv3: Fix error handling when getting the display

2022-09-27 Thread Michal Suchanek
The code checks that uclass_first_device returned a device but the
returned value that is assigned is never used. Use
uclass_first_device_err instead, and move the error return outside of
the if block.

Fixes: f4ec1ae08e ("mxc_ipuv3_fb.c: call display_enable")
Signed-off-by: Michal Suchanek 
---
 drivers/video/imx/mxc_ipuv3_fb.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 49bbeefdd8..8b01a1be11 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -609,12 +609,11 @@ static int ipuv3_video_probe(struct udevice *dev)
return ret;
 
 #if defined(CONFIG_DISPLAY)
-   ret = uclass_first_device(UCLASS_DISPLAY, _dev);
-   if (disp_dev) {
+   ret = uclass_first_device_err(UCLASS_DISPLAY, _dev);
+   if (!ret)
ret = display_enable(disp_dev, 16, NULL);
-   if (ret < 0)
-   return ret;
-   }
+   if (ret < 0)
+   return ret;
 #endif
if (CONFIG_IS_ENABLED(PANEL)) {
struct udevice *panel_dev;
-- 
2.37.3



[PATCH v5 09/15] cmd: List all uclass devices regardless of probe error

2022-09-27 Thread Michal Suchanek
There are a few commands that iterate uclass with
uclass_first_device/uclass_next_device or the _err variant.

Use the _check class iterator variant to get devices that fail to probe
as well, and print the status.

Signed-off-by: Michal Suchanek 
---
 cmd/adc.c   | 22 ++
 cmd/demo.c  | 16 ++--
 cmd/gpio.c  | 15 +++
 cmd/pmic.c  | 15 ---
 cmd/regulator.c | 13 +++--
 5 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/cmd/adc.c b/cmd/adc.c
index 1c5d3e10a3..7dcb44eb61 100644
--- a/cmd/adc.c
+++ b/cmd/adc.c
@@ -6,29 +6,27 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static int do_adc_list(struct cmd_tbl *cmdtp, int flag, int argc,
   char *const argv[])
 {
struct udevice *dev;
-   int ret;
+   int ret, err;
 
-   ret = uclass_first_device_err(UCLASS_ADC, );
-   if (ret) {
-   printf("No available ADC device\n");
-   return CMD_RET_FAILURE;
-   }
+   ret = err = uclass_first_device_check(UCLASS_ADC, );
 
-   do {
-   printf("- %s\n", dev->name);
+   while (dev) {
+   printf("- %s status: %s\n", dev->name,
+  ret ? errno_str(ret) : "OK");
 
-   ret = uclass_next_device();
+   ret = uclass_next_device_check();
if (ret)
-   return CMD_RET_FAILURE;
-   } while (dev);
+   err = ret;
+   }
 
-   return CMD_RET_SUCCESS;
+   return err ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
 }
 
 static int do_adc_info(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/cmd/demo.c b/cmd/demo.c
index 571f562ec6..56551f269d 100644
--- a/cmd/demo.c
+++ b/cmd/demo.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -64,20 +65,23 @@ static int do_demo_light(struct cmd_tbl *cmdtp, int flag, 
int argc,
 int do_demo_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
struct udevice *dev;
-   int i, ret;
+   int i, ret, err = 0;
 
puts("Demo uclass entries:\n");
 
-   for (i = 0, ret = uclass_first_device(UCLASS_DEMO, );
+   for (i = 0, ret = uclass_first_device_check(UCLASS_DEMO, );
 dev;
-ret = uclass_next_device()) {
-   printf("entry %d - instance %08x, ops %08x, plat %08x\n",
+ret = uclass_next_device_check()) {
+   printf("entry %d - instance %08x, ops %08x, plat %08x, probe %i 
(%s)\n",
   i++, (uint)map_to_sysmem(dev),
   (uint)map_to_sysmem(dev->driver->ops),
-  (uint)map_to_sysmem(dev_get_plat(dev)));
+  (uint)map_to_sysmem(dev_get_plat(dev)),
+  ret, errno_str(ret));
+   if (ret)
+   err = ret;
}
 
-   return cmd_process_error(cmdtp, ret);
+   return cmd_process_error(cmdtp, err);
 }
 
 static struct cmd_tbl demo_commands[] = {
diff --git a/cmd/gpio.c b/cmd/gpio.c
index 53e9ce666f..4bf410a9e7 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -77,17 +77,24 @@ static int do_gpio_status(bool all, const char *gpio_name)
struct udevice *dev;
int banklen;
int flags;
-   int ret;
+   int ret, err = 0;
 
flags = 0;
if (gpio_name && !*gpio_name)
gpio_name = NULL;
-   for (ret = uclass_first_device(UCLASS_GPIO, );
+   for (ret = uclass_first_device_check(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+ret = uclass_next_device_check()) {
const char *bank_name;
int num_bits;
 
+   if (ret) {
+   printf("GPIO device %s probe error %i (%s)\n",
+  dev->name, ret, errno_str(ret));
+   err = ret;
+   continue;
+   }
+
flags |= FLAG_SHOW_BANK;
if (all)
flags |= FLAG_SHOW_ALL;
@@ -120,7 +127,7 @@ static int do_gpio_status(bool all, const char *gpio_name)
flags |= FLAG_SHOW_NEWLINE;
}
 
-   return ret;
+   return err;
 }
 #endif
 
diff --git a/cmd/pmic.c b/cmd/pmic.c
index 0cb44d0740..d5624241e6 100644
--- a/cmd/pmic.c
+++ b/cmd/pmic.c
@@ -51,25 +51,26 @@ static int do_list(struct cmd_tbl *cmdtp, int flag, int 
argc,
   char *const argv[])
 {
struct udevice *dev;
-   int ret;
+   int ret, err = 0;
 
printf("| %-*.*s| %-*.*s| %s @ %s\n",
   LIMIT_DEV, LIMIT_DEV, "Name",
   LIMIT_PARENT, LIMIT_PARENT, "Parent name",
   "Parent uclass", "seq");
 
-   for (r

[PATCH v5 05/15] usb: ether: Fix error handling in usb_ether_init

2022-09-27 Thread Michal Suchanek
The code checks the return value from uclass_first_device as well as
that the device exists but it passes on the return value which may be
zero if there are no gadget devices. Just check that a device was
returned and return -ENODEV otherwise.

Also remove the dev variable which is not really used for anything.

Signed-off-by: Michal Suchanek 
---
 drivers/usb/gadget/ether.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index abb5332f13..ad394c80fc 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2636,18 +2636,17 @@ static const struct eth_ops usb_eth_ops = {
 
 int usb_ether_init(void)
 {
-   struct udevice *dev;
struct udevice *usb_dev;
int ret;
 
-   ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, _dev);
-   if (!usb_dev || ret) {
+   uclass_first_device(UCLASS_USB_GADGET_GENERIC, _dev);
+   if (!usb_dev) {
pr_err("No USB device found\n");
-   return ret;
+   return -ENODEV;
}
 
-   ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", );
-   if (!dev || ret) {
+   ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", NULL);
+   if (ret) {
pr_err("usb - not able to bind usb_ether device\n");
return ret;
}
-- 
2.37.3



[PATCH v5 06/15] stdio: Fix class iteration in stdio_add_devices()

2022-09-27 Thread Michal Suchanek
There is a complaint in the code that iterates keyboards that we don't
have the _check variant of class iterator but we in fact do, use it.

In the code that iterates video devices there is an attempt to print
errors but the simple iterator does not return a device when there is an
error. Use the _check variant of the iterator as well.

Also print the symbolic error.

Fixes: b206cd7372 ("dm: stdio: Plumb in the new keyboard uclass")
Fixes: e3b81c1c0d ("dm: stdio: video: Plumb the video uclass into stdio")
Signed-off-by: Michal Suchanek 
---
 common/stdio.c | 33 ++---
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/common/stdio.c b/common/stdio.c
index 92161a0df8..17f0aef76d 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -306,7 +306,6 @@ int stdio_init_tables(void)
 int stdio_add_devices(void)
 {
struct udevice *dev;
-   struct uclass *uc;
int ret;
 
if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
@@ -316,24 +315,18 @@ int stdio_add_devices(void)
 * have a list of input devices to start up in the stdin
 * environment variable. That work probably makes more sense
 * when stdio itself is converted to driver model.
-*
-* TODO(s...@chromium.org): Convert changing
-* uclass_first_device() etc. to return the device even on
-* error. Then we could use that here.
 */
-   ret = uclass_get(UCLASS_KEYBOARD, );
-   if (ret)
-   return ret;
 
/*
 * Don't report errors to the caller - assume that they are
 * non-fatal
 */
-   uclass_foreach_dev(dev, uc) {
-   ret = device_probe(dev);
+   for (ret = uclass_first_device_check(UCLASS_KEYBOARD, );
+   dev;
+   ret = uclass_next_device_check()) {
if (ret)
-   printf("Failed to probe keyboard '%s'\n",
-  dev->name);
+   printf("%s: Failed to probe keyboard '%s' 
(ret=%d %s)\n",
+  __func__, dev->name, ret, 
errno_str(ret));
}
}
 #if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
@@ -353,13 +346,15 @@ int stdio_add_devices(void)
int ret;
 
if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
-   for (ret = uclass_first_device(UCLASS_VIDEO, );
-vdev;
-ret = uclass_next_device())
-   ;
-   if (ret)
-   printf("%s: Video device failed (ret=%d)\n",
-  __func__, ret);
+   for (ret = uclass_first_device_check(UCLASS_VIDEO,
+);
+   vdev;
+   ret = uclass_next_device_check()) {
+   if (ret)
+   printf("%s: Failed to probe video 
device '%s' (ret=%d %s)\n",
+  __func__, dev->name,
+  ret, errno_str(ret));
+   }
}
if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
IS_ENABLED(CONFIG_CMD_BMP))
-- 
2.37.3



[PATCH v5 04/15] bootstd: Fix listing boot devices

2022-09-27 Thread Michal Suchanek
bootdev_list() uses uclass_*_device_err() to iterate devices.
However, the only value _err adds is returning an error when the device
pointer is null, and that's checked anyway.

Also there is some intent to report errors, and that's what
uclass_*_device_check() is for, use it.

Also print the symbolic error.

Signed-off-by: Michal Suchanek 
---
 boot/bootdev-uclass.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 13ac69eb39..e7115c5750 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -195,16 +196,16 @@ void bootdev_list(bool probe)
printf("Seq  Probed  Status  UclassName\n");
printf("---  --  --    --\n");
if (probe)
-   ret = uclass_first_device_err(UCLASS_BOOTDEV, );
+   ret = uclass_first_device_check(UCLASS_BOOTDEV, );
else
ret = uclass_find_first_device(UCLASS_BOOTDEV, );
for (i = 0; dev; i++) {
printf("%3x   [ %c ]  %6s  %-9.9s %s\n", dev_seq(dev),
   device_active(dev) ? '+' : ' ',
-  ret ? simple_itoa(ret) : "OK",
+  ret ? errno_str(ret) : "OK",
   dev_get_uclass_name(dev_get_parent(dev)), dev->name);
if (probe)
-   ret = uclass_next_device_err();
+   ret = uclass_next_device_check();
else
ret = uclass_find_next_device();
}
-- 
2.37.3



[PATCH v5 03/15] dm: pci: Fix device PCI iteration

2022-09-27 Thread Michal Suchanek
When there is no PCI bus uclass_first_device will return no bus and no
error which will result in pci_find_first_device calling
skip_to_next_device with no bus, and the bus is only checked at the end
of the while cycle, not the beginning.

Also stop dealing with the return value of
uclass_first_device/uclass_next_device - once the iteration is fixed to
continue after an error there is nothing meaningful to get anymore.

Fixes: 76c3fbcd3d ("dm: pci: Add a way to iterate through all PCI devices")
Signed-off-by: Michal Suchanek 
---
 drivers/pci/pci-uclass.c | 19 +--
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 16a6a699f9..00e3828d95 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1211,22 +1211,19 @@ 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
 * but that is not necessarily true on other hardware.
 */
-   do {
+   while (bus) {
device_find_first_child(bus, );
if (dev) {
*devp = dev;
return 0;
}
-   ret = uclass_next_device();
-   if (ret)
-   return ret;
-   } while (bus);
+   uclass_next_device();
+   }
 
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();
-   if (ret)
-   return ret;
+   uclass_next_device();
 
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, );
-   if (ret)
-   return ret;
+   uclass_first_device(UCLASS_PCI, );
 
return skip_to_next_device(bus, devp);
 }
-- 
2.37.3



[PATCH v5 02/15] dm: treewide: Do not opencode uclass_probe_all()

2022-09-27 Thread Michal Suchanek
We already have a function for probing all devices of a specific class,
use it.

Signed-off-by: Michal Suchanek 
---
 drivers/cpu/cpu-uclass.c   | 20 
 drivers/virtio/virtio-uclass.c | 15 +--
 test/dm/core.c | 17 +++--
 test/test-main.c   | 11 +--
 4 files changed, 9 insertions(+), 54 deletions(-)

diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index 71e5900d70..a754832526 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -20,25 +20,13 @@ DECLARE_GLOBAL_DATA_PTR;
 
 int cpu_probe_all(void)
 {
-   struct udevice *cpu;
-   int ret;
+   int ret = uclass_probe_all(UCLASS_CPU);
 
-   ret = uclass_first_device(UCLASS_CPU, );
if (ret) {
-   debug("%s: No CPU found (err = %d)\n", __func__, ret);
-   return ret;
-   }
-
-   while (cpu) {
-   ret = uclass_next_device();
-   if (ret) {
-   debug("%s: Error while probing CPU (err = %d)\n",
- __func__, ret);
-   return ret;
-   }
+   debug("%s: Error while probing CPUs (err = %d %s)\n",
+ __func__, ret, errno_str(ret));
}
-
-   return 0;
+   return ret;
 }
 
 int cpu_is_current(struct udevice *cpu)
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index 9e2d0e06a1..da4f2f26a6 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -183,21 +183,8 @@ void virtio_driver_features_init(struct virtio_dev_priv 
*priv,
 
 int virtio_init(void)
 {
-   struct udevice *bus;
-   int ret;
-
/* Enumerate all known virtio devices */
-   ret = uclass_first_device(UCLASS_VIRTIO, );
-   if (ret)
-   return ret;
-
-   while (bus) {
-   ret = uclass_next_device();
-   if (ret)
-   break;
-   }
-
-   return ret;
+   return uclass_probe_all(UCLASS_VIRTIO);
 }
 
 static int virtio_uclass_pre_probe(struct udevice *udev)
diff --git a/test/dm/core.c b/test/dm/core.c
index fd4d756972..84eb76ed5f 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -512,23 +512,15 @@ static int dm_test_leak(struct unit_test_state *uts)
int i;
 
for (i = 0; i < 2; i++) {
-   struct udevice *dev;
int ret;
-   int id;
 
dm_leak_check_start(uts);
 
ut_assertok(dm_scan_plat(false));
ut_assertok(dm_scan_fdt(false));
 
-   /* Scanning the uclass is enough to probe all the devices */
-   for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) {
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
-   ut_assertok(ret);
-   }
+   ret = uclass_probe_all(UCLASS_TEST);
+   ut_assertok(ret);
 
ut_assertok(dm_leak_check_end(uts));
}
@@ -653,10 +645,7 @@ static int dm_test_children(struct unit_test_state *uts)
ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
 
/* Probe everything */
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
+   ret = uclass_probe_all(UCLASS_TEST);
ut_assertok(ret);
 
ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
diff --git a/test/test-main.c b/test/test-main.c
index 31837e57a8..be0bf9d52c 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -89,16 +89,7 @@ static int dm_test_post_run(struct unit_test_state *uts)
 /* Ensure all the test devices are probed */
 static int do_autoprobe(struct unit_test_state *uts)
 {
-   struct udevice *dev;
-   int ret;
-
-   /* Scanning the uclass is enough to probe all the devices */
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
-
-   return ret;
+   return uclass_probe_all(UCLASS_TEST);
 }
 
 /*
-- 
2.37.3



[PATCH v5 01/15] dm: core: Fix uclass_probe_all to really probe all devices

2022-09-27 Thread Michal Suchanek
uclass_probe_all uses uclass_first_device/uclass_next_device assigning
the return value.

The interface for getting meaningful error is
uclass_first_device_check/uclass_next_device_check, use it.

Also do not stop iteration when an error is encountered. Probing all
devices includes those that happen to be after a failing device in the
uclass order.

Fixes: a59153dfeb ("dm: core: add function uclass_probe_all() to probe all 
devices")
Signed-off-by: Michal Suchanek 
---
 drivers/core/uclass.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 08d9ed82de..a591e22403 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -799,20 +799,18 @@ int uclass_pre_remove_device(struct udevice *dev)
 int uclass_probe_all(enum uclass_id id)
 {
struct udevice *dev;
-   int ret;
+   int ret, err;
 
-   ret = uclass_first_device(id, );
-   if (ret || !dev)
-   return ret;
+   err = uclass_first_device_check(id, );
 
/* Scanning uclass to probe all devices */
while (dev) {
-   ret = uclass_next_device();
+   ret = uclass_next_device_check();
if (ret)
-   return ret;
+   err = ret;
}
 
-   return 0;
+   return err;
 }
 
 int uclass_id_count(enum uclass_id id)
-- 
2.37.3



[PATCH] dm: pci: Fix doc typo first -> next

2022-09-27 Thread Michal Suchanek
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 
---
Resent separately

 include/pci.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/pci.h b/include/pci.h
index d7ed35dd52..c55d6107a4 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.
  *
-- 
2.37.3



[PATCH] dm: core: Add note about device_probe idempotence

2022-09-27 Thread Michal Suchanek
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 
---
Resent separately

 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 94844d30d8..f31c470208 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
-- 
2.37.3



[PATCH] dm: core: Document return value of device bind functions

2022-09-27 Thread Michal Suchanek
These functions use device_bind_with_driver_data internally, copy the
return value description.

Signed-off-by: Michal Suchanek 
---
Resent separately

 include/dm/lists.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/dm/lists.h b/include/dm/lists.h
index fc3b4ae585..97236f8fa0 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,
-- 
2.37.3



[PATCH] dm: blk: Add probe in blk_first_device/blk_next_device

2022-09-27 Thread Michal Suchanek
The description claims that the device is probed but it isn't.

Add the device_probe() call.

Also consolidate the iteration into one function.

Fixes: 8a5cbc065d ("dm: blk: Use uclass_find_first/next_device() in 
blk_first/next_device()")
Signed-off-by: Michal Suchanek 
---
Resent separately

 drivers/block/blk-uclass.c | 46 ++
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 676f2444bf..35beedfdf7 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -361,45 +361,43 @@ int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
return blk_select_hwpart(desc->bdev, hwpart);
 }
 
-int blk_first_device(int if_type, struct udevice **devp)
+static int _blk_next_device(int if_type, struct udevice **devp)
 {
struct blk_desc *desc;
-   int ret;
+   int ret = 0;
+
+   for (; *devp; uclass_find_next_device(devp)) {
+   desc = dev_get_uclass_plat(*devp);
+   if (desc->if_type == if_type) {
+   ret = device_probe(*devp);
+   if (!ret)
+   return 0;
+   }
+   }
 
-   ret = uclass_find_first_device(UCLASS_BLK, devp);
if (ret)
return ret;
-   if (!*devp)
-   return -ENODEV;
-   do {
-   desc = dev_get_uclass_plat(*devp);
-   if (desc->if_type == if_type)
-   return 0;
-   ret = uclass_find_next_device(devp);
-   if (ret)
-   return ret;
-   } while (*devp);
 
return -ENODEV;
 }
 
+int blk_first_device(int if_type, struct udevice **devp)
+{
+   uclass_find_first_device(UCLASS_BLK, devp);
+
+   return _blk_next_device(if_type, devp);
+}
+
 int blk_next_device(struct udevice **devp)
 {
struct blk_desc *desc;
-   int ret, if_type;
+   int if_type;
 
desc = dev_get_uclass_plat(*devp);
if_type = desc->if_type;
-   do {
-   ret = uclass_find_next_device(devp);
-   if (ret)
-   return ret;
-   if (!*devp)
-   return -ENODEV;
-   desc = dev_get_uclass_plat(*devp);
-   if (desc->if_type == if_type)
-   return 0;
-   } while (1);
+   uclass_find_next_device(devp);
+
+   return _blk_next_device(if_type, devp);
 }
 
 int blk_find_device(int if_type, int devnum, struct udevice **devp)
-- 
2.37.3



[PATCH v4 00/21] Do not stop uclass iteration on error

2022-09-25 Thread Michal Suchanek
Hello,

this patch series fixes the simple uclass iterators to be usable for
iterating uclasses even if some devices fail to probe.

Before this series when a probe error happens an error is returned
without any device pointer, and iteration cannot continue to devices
that happen to be after the failing device in the uclass list.

This is rarely expected, nor clearly documented, and for the most part
not useful in any way.

The first four patches are independent fixes, the remaining until the
last remove problematic iterator use.

All but the last are new in v4.

Thanks

Michal

Michal Suchanek (21):
  dm: pci: Fix doc typo first -> next
  dm: core: Add note about device_probe idempotence
  dm: core: Document return value of device bind functions
  dm: blk: Add probe in blk_first_device/blk_next_device
  dm: core: Fix uclass_probe_all to really probe all devices
  dm: treewide: Do not opencode uclass_probe_all()
  dm: pci: Fix device PCI iteration
  bootstd: Fix listing boot devices
  usb: ether: Fix error handling in usb_ether_init
  stdio: Fix class iteration in stdio_add_devices()
  video: ipuv3: Fix error handling when getting the display
  w1: Fix bus counting in w1_get_bus
  w1: Clean up device iteration in w1_bus_find_dev
  dma: Eliminate unused variable in dma_get_cfg()
  cmd: List all uclass devices regardless of probe error
  dm: treewide: Use uclass_first_device_err when accessing one device
  dm: treewide: Use uclass_next_device_err when accessing second device
  dm: blk: Do not use uclass_next_device_err
  dm: treewide: Do not use the return value of simple uclass iterator
  dm: core: Switch uclass_*_device_err to use uclass_*_device_check
  dm: core: Do not stop uclass iteration on error

 arch/arm/mach-k3/j721s2_init.c|  2 +-
 arch/arm/mach-omap2/am33xx/board.c|  4 +-
 arch/x86/cpu/broadwell/cpu.c  |  4 +-
 arch/x86/cpu/intel_common/cpu.c   |  4 +-
 arch/x86/lib/pinctrl_ich6.c   |  4 +-
 board/atmel/common/mac_eeprom.c   |  2 +-
 board/intel/cougarcanyon2/cougarcanyon2.c |  4 +-
 boot/bootdev-uclass.c |  7 +--
 cmd/adc.c | 22 
 cmd/demo.c| 16 +++---
 cmd/gpio.c| 15 --
 cmd/pmic.c| 15 +++---
 cmd/regulator.c   | 13 ++---
 cmd/virtio.c  |  9 ++--
 common/stdio.c| 33 +---
 drivers/block/blk-uclass.c| 62 ++-
 drivers/core/uclass.c | 56 ++--
 drivers/cpu/cpu-uclass.c  | 20 ++--
 drivers/dma/dma-uclass.c  |  7 ++-
 drivers/gpio/gpio-uclass.c| 14 +++--
 drivers/mmc/omap_hsmmc.c  |  2 +-
 drivers/pci/pci-uclass.c  | 19 ++-
 drivers/serial/serial-uclass.c|  2 +-
 drivers/serial/serial_bcm283x_mu.c|  2 +-
 drivers/serial/serial_bcm283x_pl011.c |  2 +-
 drivers/sysreset/sysreset_ast.c   |  2 +-
 drivers/usb/gadget/ether.c| 11 ++--
 drivers/video/exynos/exynos_fb.c  | 24 -
 drivers/video/imx/mxc_ipuv3_fb.c  |  9 ++--
 drivers/video/mali_dp.c   |  2 +-
 drivers/video/stm32/stm32_dsi.c   |  6 ++-
 drivers/video/tegra124/dp.c   |  7 +--
 drivers/virtio/virtio-uclass.c| 15 +-
 drivers/w1/w1-uclass.c| 29 +--
 include/dm/device-internal.h  |  4 +-
 include/dm/lists.h|  2 +
 include/dm/uclass.h   | 35 +++--
 include/pci.h |  2 +-
 lib/acpi/acpi_table.c |  2 +-
 lib/efi_loader/efi_gop.c  |  2 +-
 net/eth-uclass.c  |  6 ++-
 test/boot/bootmeth.c  |  2 +-
 test/dm/acpi.c| 14 ++---
 test/dm/core.c| 27 +++---
 test/dm/devres.c  |  4 +-
 test/dm/i2c.c |  8 +--
 test/dm/test-fdt.c| 27 +++---
 test/dm/virtio_device.c   |  8 +--
 test/dm/virtio_rng.c  |  2 +-
 test/fuzz/cmd_fuzz.c  |  2 +-
 test/fuzz/virtio.c|  2 +-
 test/test-main.c  | 11 +---
 52 files changed, 275 insertions(+), 330 deletions(-)

-- 
2.37.3



[PATCH] power: fan53555: Fix missing newline in error message

2022-09-25 Thread Michal Suchanek
Avoid concatenation with following message.

Signed-off-by: Michal Suchanek 
---

 drivers/power/pmic/fan53555.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/power/pmic/fan53555.c b/drivers/power/pmic/fan53555.c
index 4d1e686d27..0d91628f57 100644
--- a/drivers/power/pmic/fan53555.c
+++ b/drivers/power/pmic/fan53555.c
@@ -23,7 +23,7 @@ static int pmic_fan53555_read(struct udevice *dev, uint reg,
  u8 *buff, int len)
 {
if (dm_i2c_read(dev, reg, buff, len)) {
-   pr_err("%s: read error for register: %#x!", dev->name, reg);
+   pr_err("%s: read error for register: %#x!\n", dev->name, reg);
return -EIO;
}
 
-- 
2.37.3



[PATCH] dm: doc: Fix serial howto u-boot,dm-pre-reloc typo

2022-09-25 Thread Michal Suchanek
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 
---

 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 9da0e57eab..5b1d57d83a 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.
 
-- 
2.37.3



[PATCH 2/2] common: board_f: Print information for all sysresets

2022-09-25 Thread Michal Suchanek
Boards can have multiple sysresets, iterate all when printing sysreset
info.

Also print the symbolic error when reporting sysreset failure.

Fixes: 23471aed5c ("board_f: Add reset status printing")
Signed-off-by: Michal Suchanek 
---

 common/board_f.c | 31 +++
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/common/board_f.c b/common/board_f.c
index 18e2246733..0835b376bc 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -55,7 +55,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 /*
  * Pointer to initial global data area
@@ -163,20 +163,27 @@ static int print_resetinfo(void)
 {
struct udevice *dev;
char status[256];
+   bool first = true;
int ret;
 
-   ret = uclass_first_device_err(UCLASS_SYSRESET, );
-   if (ret) {
-   debug("%s: No sysreset device found (error: %d)\n",
- __func__, ret);
-   /* Not all boards have sysreset drivers available during early
-* boot, so don't fail if one can't be found.
-*/
-   return 0;
-   }
+   /* Not all boards have sysreset drivers available during early
+* boot, so don't fail if one can't be found.
+*/
+   for (ret = uclass_first_device_check(UCLASS_SYSRESET, ); dev;
+   ret = uclass_next_device_check()) {
+   if (ret) {
+   debug("%s: %s sysreset device (error: %d %s)\n",
+ __func__, dev->name, ret, errno_str(ret));
+   continue;
+   }
 
-   if (!sysreset_get_status(dev, status, sizeof(status)))
-   printf("%s", status);
+   if (!sysreset_get_status(dev, status, sizeof(status))) {
+   printf("%s%s", first ? "" : " ", status);
+   first = false;
+   }
+   }
+   if (!first)
+   printf("\n");
 
return 0;
 }
-- 
2.37.3



[PATCH 1/2] sandbox: Initialize sysreset before relocation

2022-09-25 Thread Michal Suchanek
Without this the early sysreset code cannot be tested.

Signed-off-by: Michal Suchanek 
---

 arch/sandbox/dts/sandbox.dtsi | 1 +
 arch/sandbox/dts/test.dts | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 56e6b38bfa..9e96ff12a1 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -239,6 +239,7 @@
 
reset@1 {
compatible = "sandbox,reset";
+   u-boot,dm-pre-reloc;
};
 
rng {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2761588f0d..c59b118e96 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1119,10 +1119,12 @@
 
reset@0 {
compatible = "sandbox,warm-reset";
+   u-boot,dm-pre-reloc;
};
 
reset@1 {
compatible = "sandbox,reset";
+   u-boot,dm-pre-reloc;
};
 
resetc: reset-ctl {
-- 
2.37.3



[PATCH] fixup: dm: core: Switch uclass_*_device_err to use uclass_*_device_check

2022-09-25 Thread Michal Suchanek
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  | 15 +--
 3 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 00e3828d95..2aa1043604 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1768,10 +1768,9 @@ int pci_sriov_init(struct udevice *pdev, int vf_en)
 
bdf = dm_pci_get_bdf(pdev);
 
-   pci_get_bus(PCI_BUS(bdf), );
-
-   if (!bus)
-   return -ENODEV;
+   ret = pci_get_bus(PCI_BUS(bdf), );
+   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 c5cc3cb959..10194d0e14 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 40df0b34b1..888adbd0cb 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -349,7 +349,7 @@ void 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
@@ -360,7 +360,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
@@ -372,7 +373,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.
@@ -388,7 +390,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.
@@ -490,7 +493,7 @@ int uclass_id_count(enum uclass_id id);
  * are no more devices.
  */
 #define uclass_foreach_dev_probe(id, dev)  \
-   for (int _ret = uclass_first_device_err(id, ); !_ret && dev; \
-_ret = uclass_next_device_err())
+   for (uclass_first_device(id, ); dev; \
+uclass_next_device())
 
 #endif
-- 
2.37.3



[PATCH v4 21/21] dm: core: Do not stop uclass iteration on error

2022-09-25 Thread Michal Suchanek
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 
---
v2: - Fix up tests
v3: - Fix up API doc
- Correctly forward error from uclass_get
- Do not return an error when last device fails to probe
- Drop redundant initialization
- Wrap at 80 columns
v4: - change return value to void
- further simplify iteration
---
 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 b7d11bdd23..6dec6a3973 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 return first device in the uclass that
+ * probes successfully.
+ */
+static void _uclass_next_device(struct udevice *dev, struct udevice **devp)
+{
+   for (; dev; uclass_find_next_device()) {
+   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, );
-   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();
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   uclass_find_next_device();
+   _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 5e9da2b106..40df0b34b1 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 84eb76ed5f..7f3f8d183b 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, );
+   for (ret = uclass_first_device_check(UCLASS_TEST, );
 dev;
-ret = uclass_next_device()) {
+ret = uclass_next_device_check()) {
ut_assert(!ret);
-   ut_assert(dev);
ut_assert(device_active(dev));
}
 
@@ -1112,11 +,10 @@ static int dm_test_uclass_devices_get_by_name(struct 
unit_test_state *uts)
 * this will fail on checking

[PATCH v4 19/21] dm: treewide: Do not use the return value of simple uclass iterator

2022-09-25 Thread Michal Suchanek
uclass_first_device/uclass_next_device return value will be removed,
don't use it.

Signed-off-by: Michal Suchanek 
---
 cmd/virtio.c   |  9 +++--
 drivers/gpio/gpio-uclass.c | 14 ++
 2 files changed, 9 insertions(+), 14 deletions(-)

diff --git a/cmd/virtio.c b/cmd/virtio.c
index ea3ed2e631..f7a2ef4313 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, );
-   if (ret)
+   uclass_first_device(UCLASS_VIRTIO, );
+   if (!bus)
return CMD_RET_FAILURE;
 
while (bus) {
device_foreach_child_probe(child, bus)
;
-   ret = uclass_next_device();
-   if (ret)
-   break;
+   uclass_next_device();
}
 
return CMD_RET_SUCCESS;
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 0ed32b7217..3a35f1e30a 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, );
+   for (uclass_first_device(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+uclass_next_device()) {
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)
@@ -121,12 +120,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, );
+   for (uclass_first_device(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+uclass_next_device()) {
int len;
 
uc_priv = dev_get_uclass_priv(dev);
@@ -154,7 +152,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);
 
-- 
2.37.3



[PATCH v4 20/21] dm: core: Switch uclass_*_device_err to use uclass_*_device_check

2022-09-25 Thread Michal Suchanek
The _err variant iterators use the simple iterators without suffix as
basis.

However, there is no user that uclass_next_device_err for iteration,
many users of uclass_first_device_err use it to get the first and
(assumed) only device of an uclass, and a couple that use
uclass_next_device_err to get the device following a known device in the
uclass list.

While there are some truly singleton device classes in which more than
one device cannot exist these are quite rare, and most classes can have
multiple devices even if it is not the case on the SoC's EVB.

In a later patch the simple iterators will be updated to not stop on
error and return next device instead. With this in many cases the code
that expects the first device or an error if it fails to probe may get
the next device instead. Use the _check iterators as the basis of _err
iterators to preserve the old behavior.

This is problematic for eth_get_dev: it relies on the broken behavior
that returns an error but not the device on which the error happened
which gives the caller no reasonable way to report or handle the error.
With this change the device is returned but eth_get_dev stores the
returned device pointer directly in a global state without checking the
return value. Unset the pointer again in the error case.

Signed-off-by: Michal Suchanek 
---
 drivers/core/uclass.c | 28 ++--
 include/dm/uclass.h   | 22 +++---
 net/eth-uclass.c  |  2 ++
 3 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index a591e22403..b7d11bdd23 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -586,19 +586,6 @@ int uclass_first_device(enum uclass_id id, struct udevice 
**devp)
return uclass_get_device_tail(dev, ret, devp);
 }
 
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
-{
-   int ret;
-
-   ret = uclass_first_device(id, devp);
-   if (ret)
-   return ret;
-   else if (!*devp)
-   return -ENODEV;
-
-   return 0;
-}
-
 int uclass_next_device(struct udevice **devp)
 {
struct udevice *dev = *devp;
@@ -611,11 +598,24 @@ int uclass_next_device(struct udevice **devp)
return uclass_get_device_tail(dev, ret, devp);
 }
 
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
+{
+   int ret;
+
+   ret = uclass_first_device_check(id, devp);
+   if (ret)
+   return ret;
+   else if (!*devp)
+   return -ENODEV;
+
+   return 0;
+}
+
 int uclass_next_device_err(struct udevice **devp)
 {
int ret;
 
-   ret = uclass_next_device(devp);
+   ret = uclass_next_device_check(devp);
if (ret)
return ret;
else if (!*devp)
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index f6c0110b06..5e9da2b106 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -332,17 +332,6 @@ int uclass_get_device_by_driver(enum uclass_id id, const 
struct driver *drv,
  */
 int uclass_first_device(enum uclass_id id, 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
- *
- * @id: Uclass ID to look up
- * @devp: Returns pointer to the first device in that uclass, or NULL if none
- * Return: 0 if found, -ENODEV if not found, other -ve on error
- */
-int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
-
 /**
  * uclass_next_device() - Get the next device in a uclass
  *
@@ -358,6 +347,17 @@ int uclass_first_device_err(enum uclass_id id, struct 
udevice **devp);
  */
 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
+ *
+ * @id: Uclass ID to look up
+ * @devp: Returns pointer to the first device in that uclass, or NULL if none
+ * Return: 0 if found, -ENODEV if not found, other -ve on error
+ */
+int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
+
 /**
  * uclass_next_device_err() - Get the next device in a uclass
  *
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 8c3f9cc31b..f41da4b37b 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -93,6 +93,8 @@ struct udevice *eth_get_dev(void)
if (eth_errno)
eth_errno = uclass_first_device_err(UCLASS_ETH,
_priv->current);
+   if (eth_errno)
+   uc_priv->current = NULL;
}
return uc_priv->current;
 }
-- 
2.37.3



[PATCH v4 16/21] dm: treewide: Use uclass_first_device_err when accessing one device

2022-09-25 Thread Michal Suchanek
There is a number of users that use uclass_first_device to access the
first and (assumed) only device in uclass.

Some check the return value of uclass_first_device and also that a
device was returned which is exactly what uclass_first_device_err does.

Some are not checking that a device was returned and can potentially
crash if no device exists in the uclass. Finally there is one that
returns NULL on error either way.

Convert all of these to use uclass_first_device_err instead, the return
value will be removed from uclass_first_device in a later patch.

Also print the symbolic error when the return value is printed.

Signed-off-by: Michal Suchanek 
---
 arch/arm/mach-omap2/am33xx/board.c|  4 ++--
 arch/x86/cpu/broadwell/cpu.c  |  4 +---
 arch/x86/cpu/intel_common/cpu.c   |  4 +---
 arch/x86/lib/pinctrl_ich6.c   |  4 +---
 board/intel/cougarcanyon2/cougarcanyon2.c |  4 +---
 drivers/mmc/omap_hsmmc.c  |  2 +-
 drivers/serial/serial-uclass.c|  2 +-
 drivers/serial/serial_bcm283x_mu.c|  2 +-
 drivers/serial/serial_bcm283x_pl011.c |  2 +-
 drivers/sysreset/sysreset_ast.c   |  2 +-
 drivers/video/exynos/exynos_fb.c  | 24 ++-
 drivers/video/mali_dp.c   |  2 +-
 drivers/video/stm32/stm32_dsi.c   |  6 --
 drivers/video/tegra124/dp.c   |  7 ---
 lib/acpi/acpi_table.c |  2 +-
 lib/efi_loader/efi_gop.c  |  2 +-
 net/eth-uclass.c  |  4 ++--
 test/boot/bootmeth.c  |  2 +-
 test/dm/acpi.c| 14 ++---
 test/dm/devres.c  |  4 ++--
 test/dm/i2c.c |  8 
 test/dm/virtio_device.c   |  8 
 test/dm/virtio_rng.c  |  2 +-
 test/fuzz/cmd_fuzz.c  |  2 +-
 test/fuzz/virtio.c|  2 +-
 25 files changed, 55 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-omap2/am33xx/board.c 
b/arch/arm/mach-omap2/am33xx/board.c
index 7f1b84e466..f393ff9144 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -265,8 +265,8 @@ int arch_misc_init(void)
struct udevice *dev;
int ret;
 
-   ret = uclass_first_device(UCLASS_MISC, );
-   if (ret || !dev)
+   ret = uclass_first_device_err(UCLASS_MISC, );
+   if (ret)
return ret;
 
 #if defined(CONFIG_DM_ETH) && defined(CONFIG_USB_ETHER)
diff --git a/arch/x86/cpu/broadwell/cpu.c b/arch/x86/cpu/broadwell/cpu.c
index 2adcf4b242..7877961451 100644
--- a/arch/x86/cpu/broadwell/cpu.c
+++ b/arch/x86/cpu/broadwell/cpu.c
@@ -31,11 +31,9 @@ static int broadwell_init_cpu(void *ctx, struct event *event)
int ret;
 
/* Start up the LPC so we have serial */
-   ret = uclass_first_device(UCLASS_LPC, );
+   ret = uclass_first_device_err(UCLASS_LPC, );
if (ret)
return ret;
-   if (!dev)
-   return -ENODEV;
ret = cpu_set_flex_ratio_to_tdp_nominal();
if (ret)
return ret;
diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c
index 96d05e2eb3..8f489e6c65 100644
--- a/arch/x86/cpu/intel_common/cpu.c
+++ b/arch/x86/cpu/intel_common/cpu.c
@@ -61,11 +61,9 @@ int cpu_common_init(void)
/* Early chipset init required before RAM init can work */
uclass_first_device(UCLASS_NORTHBRIDGE, );
 
-   ret = uclass_first_device(UCLASS_LPC, );
+   ret = uclass_first_device_err(UCLASS_LPC, );
if (ret)
return ret;
-   if (!lpc)
-   return -ENODEV;
 
/* Cause the SATA device to do its early init */
uclass_first_device(UCLASS_AHCI, );
diff --git a/arch/x86/lib/pinctrl_ich6.c b/arch/x86/lib/pinctrl_ich6.c
index fd5e311b29..c93f245845 100644
--- a/arch/x86/lib/pinctrl_ich6.c
+++ b/arch/x86/lib/pinctrl_ich6.c
@@ -160,11 +160,9 @@ static int ich6_pinctrl_probe(struct udevice *dev)
u32 iobase = -1;
 
debug("%s: start\n", __func__);
-   ret = uclass_first_device(UCLASS_PCH, );
+   ret = uclass_first_device_err(UCLASS_PCH, );
if (ret)
return ret;
-   if (!pch)
-   return -ENODEV;
 
/*
 * Get the memory/io base address to configure every pins.
diff --git a/board/intel/cougarcanyon2/cougarcanyon2.c 
b/board/intel/cougarcanyon2/cougarcanyon2.c
index ce11eae59d..7f61ef8b36 100644
--- a/board/intel/cougarcanyon2/cougarcanyon2.c
+++ b/board/intel/cougarcanyon2/cougarcanyon2.c
@@ -21,11 +21,9 @@ int board_early_init_f(void)
struct udevice *pch;
int ret;
 
-   ret = uclass_first_device(UCLASS_PCH, );
+   ret = uclass_first_device_err(UCLASS_PCH, );
if (ret)
return ret;
-   if (!pch)
-   

[PATCH v4 17/21] dm: treewide: Use uclass_next_device_err when accessing second device

2022-09-25 Thread Michal Suchanek
There are a couple users of uclass_next_device return value that get the
first device by other means and use uclass_next_device assuming the
following device in the uclass is related to the first one.

Use uclass_next_device_err because the return value from
uclass_next_device will be removed in a later patch.

Signed-off-by: Michal Suchanek 
---
 arch/arm/mach-k3/j721s2_init.c  | 2 +-
 board/atmel/common/mac_eeprom.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-k3/j721s2_init.c b/arch/arm/mach-k3/j721s2_init.c
index 12da8136f9..dd0c7ba18f 100644
--- a/arch/arm/mach-k3/j721s2_init.c
+++ b/arch/arm/mach-k3/j721s2_init.c
@@ -164,7 +164,7 @@ void board_init_f(ulong dummy)
if (ret)
panic("DRAM 0 init failed: %d\n", ret);
 
-   ret = uclass_next_device();
+   ret = uclass_next_device_err();
if (ret)
panic("DRAM 1 init failed: %d\n", ret);
}
diff --git a/board/atmel/common/mac_eeprom.c b/board/atmel/common/mac_eeprom.c
index a723ba723c..4606008c69 100644
--- a/board/atmel/common/mac_eeprom.c
+++ b/board/atmel/common/mac_eeprom.c
@@ -56,7 +56,7 @@ int at91_set_eth1addr(int offset)
return ret;
 
/* attempt to obtain a second eeprom device */
-   ret = uclass_next_device();
+   ret = uclass_next_device_err();
if (ret)
return ret;
 
-- 
2.37.3



[PATCH v4 15/21] cmd: List all uclass devices regardless of probe error

2022-09-25 Thread Michal Suchanek
There are a few commands that iterate uclass with
uclass_first_device/uclass_next_device or the _err variant.

Use the _check class iterator variant to get devices that fail to probe
as well, and print the status.

Signed-off-by: Michal Suchanek 
---
 cmd/adc.c   | 22 ++
 cmd/demo.c  | 16 ++--
 cmd/gpio.c  | 15 +++
 cmd/pmic.c  | 15 ---
 cmd/regulator.c | 13 +++--
 5 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/cmd/adc.c b/cmd/adc.c
index 1c5d3e10a3..7dcb44eb61 100644
--- a/cmd/adc.c
+++ b/cmd/adc.c
@@ -6,29 +6,27 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static int do_adc_list(struct cmd_tbl *cmdtp, int flag, int argc,
   char *const argv[])
 {
struct udevice *dev;
-   int ret;
+   int ret, err;
 
-   ret = uclass_first_device_err(UCLASS_ADC, );
-   if (ret) {
-   printf("No available ADC device\n");
-   return CMD_RET_FAILURE;
-   }
+   ret = err = uclass_first_device_check(UCLASS_ADC, );
 
-   do {
-   printf("- %s\n", dev->name);
+   while (dev) {
+   printf("- %s status: %s\n", dev->name,
+  ret ? errno_str(ret) : "OK");
 
-   ret = uclass_next_device();
+   ret = uclass_next_device_check();
if (ret)
-   return CMD_RET_FAILURE;
-   } while (dev);
+   err = ret;
+   }
 
-   return CMD_RET_SUCCESS;
+   return err ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
 }
 
 static int do_adc_info(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/cmd/demo.c b/cmd/demo.c
index 571f562ec6..56551f269d 100644
--- a/cmd/demo.c
+++ b/cmd/demo.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -64,20 +65,23 @@ static int do_demo_light(struct cmd_tbl *cmdtp, int flag, 
int argc,
 int do_demo_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
struct udevice *dev;
-   int i, ret;
+   int i, ret, err = 0;
 
puts("Demo uclass entries:\n");
 
-   for (i = 0, ret = uclass_first_device(UCLASS_DEMO, );
+   for (i = 0, ret = uclass_first_device_check(UCLASS_DEMO, );
 dev;
-ret = uclass_next_device()) {
-   printf("entry %d - instance %08x, ops %08x, plat %08x\n",
+ret = uclass_next_device_check()) {
+   printf("entry %d - instance %08x, ops %08x, plat %08x, probe %i 
(%s)\n",
   i++, (uint)map_to_sysmem(dev),
   (uint)map_to_sysmem(dev->driver->ops),
-  (uint)map_to_sysmem(dev_get_plat(dev)));
+  (uint)map_to_sysmem(dev_get_plat(dev)),
+  ret, errno_str(ret));
+   if (ret)
+   err = ret;
}
 
-   return cmd_process_error(cmdtp, ret);
+   return cmd_process_error(cmdtp, err);
 }
 
 static struct cmd_tbl demo_commands[] = {
diff --git a/cmd/gpio.c b/cmd/gpio.c
index 53e9ce666f..4bf410a9e7 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -77,17 +77,24 @@ static int do_gpio_status(bool all, const char *gpio_name)
struct udevice *dev;
int banklen;
int flags;
-   int ret;
+   int ret, err = 0;
 
flags = 0;
if (gpio_name && !*gpio_name)
gpio_name = NULL;
-   for (ret = uclass_first_device(UCLASS_GPIO, );
+   for (ret = uclass_first_device_check(UCLASS_GPIO, );
 dev;
-ret = uclass_next_device()) {
+ret = uclass_next_device_check()) {
const char *bank_name;
int num_bits;
 
+   if (ret) {
+   printf("GPIO device %s probe error %i (%s)\n",
+  dev->name, ret, errno_str(ret));
+   err = ret;
+   continue;
+   }
+
flags |= FLAG_SHOW_BANK;
if (all)
flags |= FLAG_SHOW_ALL;
@@ -120,7 +127,7 @@ static int do_gpio_status(bool all, const char *gpio_name)
flags |= FLAG_SHOW_NEWLINE;
}
 
-   return ret;
+   return err;
 }
 #endif
 
diff --git a/cmd/pmic.c b/cmd/pmic.c
index 0cb44d0740..d5624241e6 100644
--- a/cmd/pmic.c
+++ b/cmd/pmic.c
@@ -51,25 +51,26 @@ static int do_list(struct cmd_tbl *cmdtp, int flag, int 
argc,
   char *const argv[])
 {
struct udevice *dev;
-   int ret;
+   int ret, err = 0;
 
printf("| %-*.*s| %-*.*s| %s @ %s\n",
   LIMIT_DEV, LIMIT_DEV, "Name",
   LIMIT_PARENT, LIMIT_PARENT, "Parent name",
   "Parent uclass", "seq");
 
-   for (r

[PATCH v4 18/21] dm: blk: Do not use uclass_next_device_err

2022-09-25 Thread Michal Suchanek
blk_first_device_err/blk_next_device_err uses
uclass_first_device_err/uclass_next_device_err for device iteration.

Although the function names superficially match the return value from
uclass_first_device_err/uclass_next_device_err is never used
meaningfully, and uclass_first_device/uclass_next_device works equally
well for this purpose.

In the following patch the semantic of
uclass_first_device_err/uclass_next_device_err will be changed to be
based on uclass_first_device_check/uclass_next_device_check breaking
this sole user that uses uclass_next_device_err for iteration.

Signed-off-by: Michal Suchanek 
---
 drivers/block/blk-uclass.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 992f8ad3da..35beedfdf7 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -583,11 +583,9 @@ int blk_find_next(enum blk_flag_t flags, struct udevice 
**devp)
 
 int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp)
 {
-   int ret;
-
-   for (ret = uclass_first_device_err(UCLASS_BLK, devp);
-!ret;
-ret = uclass_next_device_err(devp)) {
+   for (uclass_first_device(UCLASS_BLK, devp);
+*devp;
+uclass_next_device(devp)) {
if (!blk_flags_check(*devp, flags))
return 0;
}
@@ -597,11 +595,9 @@ int blk_first_device_err(enum blk_flag_t flags, struct 
udevice **devp)
 
 int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp)
 {
-   int ret;
-
-   for (ret = uclass_next_device_err(devp);
-!ret;
-ret = uclass_next_device_err(devp)) {
+   for (uclass_next_device(devp);
+*devp;
+uclass_next_device(devp)) {
if (!blk_flags_check(*devp, flags))
return 0;
}
-- 
2.37.3



[PATCH v4 13/21] w1: Clean up device iteration in w1_bus_find_dev

2022-09-25 Thread Michal Suchanek
The cycle is guarded by !ret && dev, code in if (ret || ! dev) is never
executed. dev implies !ret, and ret is not even checked when getting
next device, just drop the ret variable completely.

Signed-off-by: Michal Suchanek 
---
 drivers/w1/w1-uclass.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c
index de4f25bcf9..a4247ecd62 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, );
-   !ret && dev;
+   for (uclass_first_device(UCLASS_W1_EEPROM, );
+   dev;
uclass_next_device()) {
-   if (ret || !dev) {
-   debug("cannot find w1 eeprom dev\n");
-   return -ENODEV;
-   }
 
if (dev_get_driver_data(dev) == family) {
*devp = dev;
-- 
2.37.3



[PATCH v4 14/21] dma: Eliminate unused variable in dma_get_cfg()

2022-09-25 Thread Michal Suchanek
The ret value is never used. It is only set when no device is returned,
and that is handled before the value of ret would be used.

Signed-off-by: Michal Suchanek 
---
 drivers/dma/dma-uclass.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 012609bb53..952cbc2170 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -209,10 +209,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 && !ret;
-ret = uclass_next_device()) {
+   for (uclass_first_device(UCLASS_DMA, ); dev;
+uclass_next_device()) {
struct dma_dev_priv *uc_priv;
 
uc_priv = dev_get_uclass_priv(dev);
@@ -228,7 +227,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)
-- 
2.37.3



[PATCH v4 12/21] w1: Fix bus counting in w1_get_bus

2022-09-25 Thread Michal Suchanek
Use uclass_first_device_check/uclass_next_device_check to correctly
count buses that fail to probe.

Fixes: d3e19cf919 ("w1: Add 1-Wire uclass")
Signed-off-by: Michal Suchanek 
---
 drivers/w1/w1-uclass.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c
index 52b519c21d..de4f25bcf9 100644
--- a/drivers/w1/w1-uclass.c
+++ b/drivers/w1/w1-uclass.c
@@ -16,6 +16,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -182,24 +183,25 @@ static int w1_enumerate(struct udevice *bus)
 int w1_get_bus(int busnum, struct udevice **busp)
 {
int ret, i = 0;
-
struct udevice *dev;
 
-   for (ret = uclass_first_device(UCLASS_W1, );
-dev && !ret;
-ret = uclass_next_device(), i++) {
+   for (ret = uclass_first_device_check(UCLASS_W1, );
+   dev;
+   ret = uclass_next_device_check(), i++) {
if (i == busnum) {
+   if (ret) {
+   debug("Cannot probe w1 bus %d: %d (%s)\n",
+ busnum, ret, errno_str(ret));
+   return ret;
+   }
*busp = dev;
return 0;
}
}
 
-   if (!ret) {
-   debug("Cannot find w1 bus %d\n", busnum);
-   ret = -ENODEV;
-   }
+   debug("Cannot find w1 bus %d\n", busnum);
 
-   return ret;
+   return -ENODEV;
 }
 
 u8 w1_get_device_family(struct udevice *dev)
-- 
2.37.3



[PATCH v4 11/21] video: ipuv3: Fix error handling when getting the display

2022-09-25 Thread Michal Suchanek
The code checks that uclass_first_device returned a device but the
returned value that is assigned is never used. Use
uclass_first_device_err instead, and move the error return outside of
the if block.

Fixes: f4ec1ae08e ("mxc_ipuv3_fb.c: call display_enable")
Signed-off-by: Michal Suchanek 
---
 drivers/video/imx/mxc_ipuv3_fb.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/video/imx/mxc_ipuv3_fb.c b/drivers/video/imx/mxc_ipuv3_fb.c
index 49bbeefdd8..8b01a1be11 100644
--- a/drivers/video/imx/mxc_ipuv3_fb.c
+++ b/drivers/video/imx/mxc_ipuv3_fb.c
@@ -609,12 +609,11 @@ static int ipuv3_video_probe(struct udevice *dev)
return ret;
 
 #if defined(CONFIG_DISPLAY)
-   ret = uclass_first_device(UCLASS_DISPLAY, _dev);
-   if (disp_dev) {
+   ret = uclass_first_device_err(UCLASS_DISPLAY, _dev);
+   if (!ret)
ret = display_enable(disp_dev, 16, NULL);
-   if (ret < 0)
-   return ret;
-   }
+   if (ret < 0)
+   return ret;
 #endif
if (CONFIG_IS_ENABLED(PANEL)) {
struct udevice *panel_dev;
-- 
2.37.3



[PATCH v4 09/21] usb: ether: Fix error handling in usb_ether_init

2022-09-25 Thread Michal Suchanek
The code checks the return value from uclass_first_device as well as
that the device exists but it passes on the return value which may be
zero if there are no gadget devices. Just check that a device was
returned and return -ENODEV otherwise.

Also remove the dev variable which is not really used for anything.

Signed-off-by: Michal Suchanek 
---
 drivers/usb/gadget/ether.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index abb5332f13..ad394c80fc 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2636,18 +2636,17 @@ static const struct eth_ops usb_eth_ops = {
 
 int usb_ether_init(void)
 {
-   struct udevice *dev;
struct udevice *usb_dev;
int ret;
 
-   ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, _dev);
-   if (!usb_dev || ret) {
+   uclass_first_device(UCLASS_USB_GADGET_GENERIC, _dev);
+   if (!usb_dev) {
pr_err("No USB device found\n");
-   return ret;
+   return -ENODEV;
}
 
-   ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", );
-   if (!dev || ret) {
+   ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", NULL);
+   if (ret) {
pr_err("usb - not able to bind usb_ether device\n");
return ret;
}
-- 
2.37.3



[PATCH v4 08/21] bootstd: Fix listing boot devices

2022-09-25 Thread Michal Suchanek
bootdev_list() uses uclass_*_device_err() to iterate devices.
However, the only value _err adds is returning an error when the device
pointer is null, and that's checked anyway.

Also there is some intent to report errors, and that's what
uclass_*_device_check() is for, use it.

Also print the symbolic error.

Signed-off-by: Michal Suchanek 
---
 boot/bootdev-uclass.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 13ac69eb39..e7115c5750 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -195,16 +196,16 @@ void bootdev_list(bool probe)
printf("Seq  Probed  Status  UclassName\n");
printf("---  --  --    --\n");
if (probe)
-   ret = uclass_first_device_err(UCLASS_BOOTDEV, );
+   ret = uclass_first_device_check(UCLASS_BOOTDEV, );
else
ret = uclass_find_first_device(UCLASS_BOOTDEV, );
for (i = 0; dev; i++) {
printf("%3x   [ %c ]  %6s  %-9.9s %s\n", dev_seq(dev),
   device_active(dev) ? '+' : ' ',
-  ret ? simple_itoa(ret) : "OK",
+  ret ? errno_str(ret) : "OK",
   dev_get_uclass_name(dev_get_parent(dev)), dev->name);
if (probe)
-   ret = uclass_next_device_err();
+   ret = uclass_next_device_check();
else
ret = uclass_find_next_device();
}
-- 
2.37.3



[PATCH v4 10/21] stdio: Fix class iteration in stdio_add_devices()

2022-09-25 Thread Michal Suchanek
There is a complaint in the code that iterates keyboards that we don't
have the _check variant of class iterator but we in fact do, use it.

In the code that iterates video devices there is an attempt to print
errors but the simple iterator does not return a device when there is an
error. Use the _check variant of the iterator as well.

Also print the symbolic error.

Fixes: b206cd7372 ("dm: stdio: Plumb in the new keyboard uclass")
Fixes: e3b81c1c0d ("dm: stdio: video: Plumb the video uclass into stdio")
Signed-off-by: Michal Suchanek 
---
 common/stdio.c | 33 ++---
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/common/stdio.c b/common/stdio.c
index 92161a0df8..17f0aef76d 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -306,7 +306,6 @@ int stdio_init_tables(void)
 int stdio_add_devices(void)
 {
struct udevice *dev;
-   struct uclass *uc;
int ret;
 
if (IS_ENABLED(CONFIG_DM_KEYBOARD)) {
@@ -316,24 +315,18 @@ int stdio_add_devices(void)
 * have a list of input devices to start up in the stdin
 * environment variable. That work probably makes more sense
 * when stdio itself is converted to driver model.
-*
-* TODO(s...@chromium.org): Convert changing
-* uclass_first_device() etc. to return the device even on
-* error. Then we could use that here.
 */
-   ret = uclass_get(UCLASS_KEYBOARD, );
-   if (ret)
-   return ret;
 
/*
 * Don't report errors to the caller - assume that they are
 * non-fatal
 */
-   uclass_foreach_dev(dev, uc) {
-   ret = device_probe(dev);
+   for (ret = uclass_first_device_check(UCLASS_KEYBOARD, );
+   dev;
+   ret = uclass_next_device_check()) {
if (ret)
-   printf("Failed to probe keyboard '%s'\n",
-  dev->name);
+   printf("%s: Failed to probe keyboard '%s' 
(ret=%d %s)\n",
+  __func__, dev->name, ret, 
errno_str(ret));
}
}
 #if CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
@@ -353,13 +346,15 @@ int stdio_add_devices(void)
int ret;
 
if (!IS_ENABLED(CONFIG_SYS_CONSOLE_IS_IN_ENV)) {
-   for (ret = uclass_first_device(UCLASS_VIDEO, );
-vdev;
-ret = uclass_next_device())
-   ;
-   if (ret)
-   printf("%s: Video device failed (ret=%d)\n",
-  __func__, ret);
+   for (ret = uclass_first_device_check(UCLASS_VIDEO,
+);
+   vdev;
+   ret = uclass_next_device_check()) {
+   if (ret)
+   printf("%s: Failed to probe video 
device '%s' (ret=%d %s)\n",
+  __func__, dev->name,
+  ret, errno_str(ret));
+   }
}
if (IS_ENABLED(CONFIG_SPLASH_SCREEN) &&
IS_ENABLED(CONFIG_CMD_BMP))
-- 
2.37.3



[PATCH v4 07/21] dm: pci: Fix device PCI iteration

2022-09-25 Thread Michal Suchanek
When there is no PCI bus uclass_first_device will return no bus and no
error which will result in pci_find_first_device calling
skip_to_next_device with no bus, and the bus is only checked at the end
of the while cycle, not the beginning.

Also stop dealing with the return value of
uclass_first_device/uclass_next_device - once the iteration is fixed to
continue after an error there is nothing meaningful to get anymore.

Fixes: 76c3fbcd3d ("dm: pci: Add a way to iterate through all PCI devices")
Signed-off-by: Michal Suchanek 
---
 drivers/pci/pci-uclass.c | 19 +--
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 16a6a699f9..00e3828d95 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1211,22 +1211,19 @@ 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
 * but that is not necessarily true on other hardware.
 */
-   do {
+   while (bus) {
device_find_first_child(bus, );
if (dev) {
*devp = dev;
return 0;
}
-   ret = uclass_next_device();
-   if (ret)
-   return ret;
-   } while (bus);
+   uclass_next_device();
+   }
 
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();
-   if (ret)
-   return ret;
+   uclass_next_device();
 
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, );
-   if (ret)
-   return ret;
+   uclass_first_device(UCLASS_PCI, );
 
return skip_to_next_device(bus, devp);
 }
-- 
2.37.3



[PATCH v4 05/21] dm: core: Fix uclass_probe_all to really probe all devices

2022-09-25 Thread Michal Suchanek
uclass_probe_all uses uclass_first_device/uclass_next_device assigning
the return value.

The interface for getting meaningful error is
uclass_first_device_check/uclass_next_device_check, use it.

Also do not stop iteration when an error is encountered. Probing all
devices includes those that happen to be after a failing device in the
uclass order.

Fixes: a59153dfeb ("dm: core: add function uclass_probe_all() to probe all 
devices")
Signed-off-by: Michal Suchanek 
---
 drivers/core/uclass.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 08d9ed82de..a591e22403 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -799,20 +799,18 @@ int uclass_pre_remove_device(struct udevice *dev)
 int uclass_probe_all(enum uclass_id id)
 {
struct udevice *dev;
-   int ret;
+   int ret, err;
 
-   ret = uclass_first_device(id, );
-   if (ret || !dev)
-   return ret;
+   err = uclass_first_device_check(id, );
 
/* Scanning uclass to probe all devices */
while (dev) {
-   ret = uclass_next_device();
+   ret = uclass_next_device_check();
if (ret)
-   return ret;
+   err = ret;
}
 
-   return 0;
+   return err;
 }
 
 int uclass_id_count(enum uclass_id id)
-- 
2.37.3



[PATCH v4 06/21] dm: treewide: Do not opencode uclass_probe_all()

2022-09-25 Thread Michal Suchanek
We already have a function for probing all devices of a specific class,
use it.

Signed-off-by: Michal Suchanek 
---
 drivers/cpu/cpu-uclass.c   | 20 
 drivers/virtio/virtio-uclass.c | 15 +--
 test/dm/core.c | 17 +++--
 test/test-main.c   | 11 +--
 4 files changed, 9 insertions(+), 54 deletions(-)

diff --git a/drivers/cpu/cpu-uclass.c b/drivers/cpu/cpu-uclass.c
index 71e5900d70..a754832526 100644
--- a/drivers/cpu/cpu-uclass.c
+++ b/drivers/cpu/cpu-uclass.c
@@ -20,25 +20,13 @@ DECLARE_GLOBAL_DATA_PTR;
 
 int cpu_probe_all(void)
 {
-   struct udevice *cpu;
-   int ret;
+   int ret = uclass_probe_all(UCLASS_CPU);
 
-   ret = uclass_first_device(UCLASS_CPU, );
if (ret) {
-   debug("%s: No CPU found (err = %d)\n", __func__, ret);
-   return ret;
-   }
-
-   while (cpu) {
-   ret = uclass_next_device();
-   if (ret) {
-   debug("%s: Error while probing CPU (err = %d)\n",
- __func__, ret);
-   return ret;
-   }
+   debug("%s: Error while probing CPUs (err = %d %s)\n",
+ __func__, ret, errno_str(ret));
}
-
-   return 0;
+   return ret;
 }
 
 int cpu_is_current(struct udevice *cpu)
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index 9e2d0e06a1..da4f2f26a6 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -183,21 +183,8 @@ void virtio_driver_features_init(struct virtio_dev_priv 
*priv,
 
 int virtio_init(void)
 {
-   struct udevice *bus;
-   int ret;
-
/* Enumerate all known virtio devices */
-   ret = uclass_first_device(UCLASS_VIRTIO, );
-   if (ret)
-   return ret;
-
-   while (bus) {
-   ret = uclass_next_device();
-   if (ret)
-   break;
-   }
-
-   return ret;
+   return uclass_probe_all(UCLASS_VIRTIO);
 }
 
 static int virtio_uclass_pre_probe(struct udevice *udev)
diff --git a/test/dm/core.c b/test/dm/core.c
index fd4d756972..84eb76ed5f 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -512,23 +512,15 @@ static int dm_test_leak(struct unit_test_state *uts)
int i;
 
for (i = 0; i < 2; i++) {
-   struct udevice *dev;
int ret;
-   int id;
 
dm_leak_check_start(uts);
 
ut_assertok(dm_scan_plat(false));
ut_assertok(dm_scan_fdt(false));
 
-   /* Scanning the uclass is enough to probe all the devices */
-   for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) {
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
-   ut_assertok(ret);
-   }
+   ret = uclass_probe_all(UCLASS_TEST);
+   ut_assertok(ret);
 
ut_assertok(dm_leak_check_end(uts));
}
@@ -653,10 +645,7 @@ static int dm_test_children(struct unit_test_state *uts)
ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
 
/* Probe everything */
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
+   ret = uclass_probe_all(UCLASS_TEST);
ut_assertok(ret);
 
ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
diff --git a/test/test-main.c b/test/test-main.c
index 31837e57a8..be0bf9d52c 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -89,16 +89,7 @@ static int dm_test_post_run(struct unit_test_state *uts)
 /* Ensure all the test devices are probed */
 static int do_autoprobe(struct unit_test_state *uts)
 {
-   struct udevice *dev;
-   int ret;
-
-   /* Scanning the uclass is enough to probe all the devices */
-   for (ret = uclass_first_device(UCLASS_TEST, );
-dev;
-ret = uclass_next_device())
-   ;
-
-   return ret;
+   return uclass_probe_all(UCLASS_TEST);
 }
 
 /*
-- 
2.37.3



[PATCH v4 04/21] dm: blk: Add probe in blk_first_device/blk_next_device

2022-09-25 Thread Michal Suchanek
The description claims that the device is probed but it isn't.

Add the device_probe() call.

Also consolidate the iteration into one function.

Fixes: 8a5cbc065d ("dm: blk: Use uclass_find_first/next_device() in 
blk_first/next_device()")
Signed-off-by: Michal Suchanek 
---
 drivers/block/blk-uclass.c | 46 ++
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 21c5209bb6..992f8ad3da 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -361,45 +361,43 @@ int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
return blk_select_hwpart(desc->bdev, hwpart);
 }
 
-int blk_first_device(int if_type, struct udevice **devp)
+static int _blk_next_device(int if_type, struct udevice **devp)
 {
struct blk_desc *desc;
-   int ret;
+   int ret = 0;
+
+   for (; *devp; uclass_find_next_device(devp)) {
+   desc = dev_get_uclass_plat(*devp);
+   if (desc->if_type == if_type) {
+   ret = device_probe(*devp);
+   if (!ret)
+   return 0;
+   }
+   }
 
-   ret = uclass_find_first_device(UCLASS_BLK, devp);
if (ret)
return ret;
-   if (!*devp)
-   return -ENODEV;
-   do {
-   desc = dev_get_uclass_plat(*devp);
-   if (desc->if_type == if_type)
-   return 0;
-   ret = uclass_find_next_device(devp);
-   if (ret)
-   return ret;
-   } while (*devp);
 
return -ENODEV;
 }
 
+int blk_first_device(int if_type, struct udevice **devp)
+{
+   uclass_find_first_device(UCLASS_BLK, devp);
+
+   return _blk_next_device(if_type, devp);
+}
+
 int blk_next_device(struct udevice **devp)
 {
struct blk_desc *desc;
-   int ret, if_type;
+   int if_type;
 
desc = dev_get_uclass_plat(*devp);
if_type = desc->if_type;
-   do {
-   ret = uclass_find_next_device(devp);
-   if (ret)
-   return ret;
-   if (!*devp)
-   return -ENODEV;
-   desc = dev_get_uclass_plat(*devp);
-   if (desc->if_type == if_type)
-   return 0;
-   } while (1);
+   uclass_find_next_device(devp);
+
+   return _blk_next_device(if_type, devp);
 }
 
 int blk_find_device(int if_type, int devnum, struct udevice **devp)
-- 
2.37.3



[PATCH v4 02/21] dm: core: Add note about device_probe idempotence

2022-09-25 Thread Michal Suchanek
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 94844d30d8..f31c470208 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
-- 
2.37.3



[PATCH v4 01/21] dm: pci: Fix doc typo first -> next

2022-09-25 Thread Michal Suchanek
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 d7ed35dd52..c55d6107a4 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.
  *
-- 
2.37.3



[PATCH v4 03/21] dm: core: Document return value of device bind functions

2022-09-25 Thread Michal Suchanek
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 fc3b4ae585..97236f8fa0 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,
-- 
2.37.3



[PATCH 2/2] tests: Do not hardcode sudo tool

2022-08-25 Thread Michal Suchanek
In some situations it may be needed to pass parameters to sudo or to use
a different tool to gain root access. Add SUDO variable to specify the
sudo tool.

Signed-off-by: Michal Suchanek 
---
 doc/develop/testing.rst   |  5 +++--
 test/fs/fat-noncontig-test.sh |  9 +
 test/fs/fs-test.sh| 26 ++
 test/py/tests/test_fs/conftest.py |  8 +---
 test/py/tests/test_ut.py  | 14 --
 5 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/doc/develop/testing.rst b/doc/develop/testing.rst
index 054fbfc814..622c2f7924 100644
--- a/doc/develop/testing.rst
+++ b/doc/develop/testing.rst
@@ -17,8 +17,9 @@ To run most tests on sandbox, type this::
 in the U-Boot directory. Note that only the pytest suite is run using this
 command.
 
-Note: external tool `python3-coverage` is used by tests. The environment
-variable `COVERAGE` can be set to alternative name or location of this tool.
+Note: external tools `sudo` and  `python3-coverage` are used by tests. The
+environment variables `SUDO` and `COVERAGE` can be set to alternative name or
+location of the tools or to specify additional parameters.
 
 Some tests take ages to run and are marked with @pytest.mark.slow. To run just
 the quick ones, type this::
diff --git a/test/fs/fat-noncontig-test.sh b/test/fs/fat-noncontig-test.sh
index b02dae765f..7e478c6705 100755
--- a/test/fs/fat-noncontig-test.sh
+++ b/test/fs/fat-noncontig-test.sh
@@ -60,6 +60,7 @@ testfn=noncontig.img
 mnttestfn=${mnt}/${testfn}
 crcaddr=0
 loadaddr=1000
+[ -n "$SUDO" ] || SUDO=sudo
 
 for prereq in fallocate mkfs.fat dd crc32; do
 if [ ! -x "`which $prereq`" ]; then
@@ -87,7 +88,7 @@ if [ ! -f ${img} ]; then
 exit $?
 fi
 
-sudo mount -o loop,uid=$(id -u) ${img} ${mnt}
+$SUDO mount -o loop,uid=$(id -u) ${img} ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not mount test filesystem
 exit $?
@@ -106,20 +107,20 @@ if [ ! -f ${img} ]; then
 # sector size (ignoring sizes that are multiples of both).
 dd if=${fill} of=${mnttestfn} bs=511 >/dev/null 2>&1
 
-sudo umount ${mnt}
+$SUDO umount ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not unmount test filesystem
 exit $?
 fi
 fi
 
-sudo mount -o ro,loop,uid=$(id -u) ${img} ${mnt}
+$SUDO mount -o ro,loop,uid=$(id -u) ${img} ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not mount test filesystem
 exit $?
 fi
 crc=0x`crc32 ${mnttestfn}`
-sudo umount ${mnt}
+$SUDO umount ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not unmount test filesystem
 exit $?
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index b87748106c..bd55ff51b6 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -55,6 +55,8 @@ OUT="${OUT_DIR}/fs-test"
 MB1="${MOUNT_DIR}/${SMALL_FILE}"
 GB2p5="${MOUNT_DIR}/${BIG_FILE}"
 
+[ -n "$SUDO" ] || SUDO=sudo
+
 # 
 # * Functions start here *
 # 
@@ -351,34 +353,34 @@ EOF
 function create_files() {
# Mount the image so we can populate it.
mkdir -p "$MOUNT_DIR"
-   sudo mount -o loop,rw "$1" "$MOUNT_DIR"
+   $SUDO mount -o loop,rw "$1" "$MOUNT_DIR"
 
# Create a subdirectory.
-   sudo mkdir -p "$MOUNT_DIR/SUBDIR"
+   $SUDO mkdir -p "$MOUNT_DIR/SUBDIR"
 
# Create big file in this image.
# Note that we work only on the start 1MB, couple MBs in the 2GB range
# and the last 1 MB of the huge 2.5GB file.
# So, just put random values only in those areas.
if [ ! -f "${GB2p5}" ]; then
-   sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 \
+   $SUDO dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 \
&> /dev/null
-   sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=2 seek=2047 \
+   $SUDO dd if=/dev/urandom of="${GB2p5}" bs=1M count=2 seek=2047 \
&> /dev/null
-   sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 seek=2499 \
+   $SUDO dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 seek=2499 \
&> /dev/null
fi
 
# Create a small file in this image.
if [ ! -f "${MB1}" ]; then
-   sudo dd if=/dev/urandom of="${MB1}" bs=1M count=1 \
+   $SUDO dd if=/dev/urandom of="${MB1}" bs=1M count=1 \
&> /dev/null
fi
 
# Delete the small file copies which possibly are written as part of a
# previous test.
-   sudo rm -f "${MB1}.w"
-   sudo rm -f "${MB1}.w2"
+   $SUDO rm -f "${MB1}.w"
+   $SUDO rm -f "${MB1}.w2"
 
  

[PATCH 1/2] patman: do not hardcode coverage tool

2022-08-25 Thread Michal Suchanek
The coverage tool name varies across distributions.

Add COVERAGE variable to specify the tool name.

Also there is one place where prefix is prepended to the tool path,
remove the prefix.

Signed-off-by: Michal Suchanek 
---
 doc/develop/testing.rst   |  3 +++
 tools/patman/test_util.py | 18 ++
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/doc/develop/testing.rst b/doc/develop/testing.rst
index 1abe4d7f0f..054fbfc814 100644
--- a/doc/develop/testing.rst
+++ b/doc/develop/testing.rst
@@ -17,6 +17,9 @@ To run most tests on sandbox, type this::
 in the U-Boot directory. Note that only the pytest suite is run using this
 command.
 
+Note: external tool `python3-coverage` is used by tests. The environment
+variable `COVERAGE` can be set to alternative name or location of this tool.
+
 Some tests take ages to run and are marked with @pytest.mark.slow. To run just
 the quick ones, type this::
 
diff --git a/tools/patman/test_util.py b/tools/patman/test_util.py
index 0f6d1aa902..e11806b626 100644
--- a/tools/patman/test_util.py
+++ b/tools/patman/test_util.py
@@ -15,6 +15,8 @@ from patman import command
 
 from io import StringIO
 
+coverage = os.environ.get('COVERAGE', 'python3-coverage')
+
 buffer_outputs = True
 use_concurrent = True
 try:
@@ -58,11 +60,11 @@ def run_test_coverage(prog, filter_fname, exclude_list, 
build_dir, required=None
 prefix = ''
 if build_dir:
 prefix = 'PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools ' % build_dir
-cmd = ('%spython3-coverage run '
-   '--omit "%s" %s %s %s -P1' % (prefix, ','.join(glob_list),
+cmd = ('%s run '
+   '--omit "%s" %s %s %s -P1' % (coverage, ','.join(glob_list),
  prog, extra_args or '', test_cmd))
 os.system(cmd)
-stdout = command.output('python3-coverage', 'report')
+stdout = command.output(coverage, 'report')
 lines = stdout.splitlines()
 if required:
 # Convert '/path/to/name.py' just the module name 'name'
@@ -76,13 +78,13 @@ def run_test_coverage(prog, filter_fname, exclude_list, 
build_dir, required=None
 print(stdout)
 ok = False
 
-coverage = lines[-1].split(' ')[-1]
+cov_result = lines[-1].split(' ')[-1]
 ok = True
-print(coverage)
-if coverage != '100%':
+print(cov_result)
+if cov_result != '100%':
 print(stdout)
-print("To get a report in 'htmlcov/index.html', type: python3-coverage 
html")
-print('Coverage error: %s, but should be 100%%' % coverage)
+print("To get a report in 'htmlcov/index.html', type: %s html" % 
coverage)
+print('Coverage error: %s, but should be 100%%' % cov_result)
 ok = False
 if not ok:
 raise ValueError('Test coverage failure')
-- 
2.37.1



[PATCH] tests: Do not hardcode sudo tool

2022-08-24 Thread Michal Suchanek
In some situations it may be needed to pass parameters to sudo or to use
a different tool to gain root access. Add SUDO variable to specify the
sudo tool.

Signed-off-by: Michal Suchanek 
---
 test/fs/fat-noncontig-test.sh |  9 +
 test/fs/fs-test.sh| 26 ++
 test/py/tests/test_fs/conftest.py |  8 +---
 test/py/tests/test_ut.py  | 14 --
 4 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/test/fs/fat-noncontig-test.sh b/test/fs/fat-noncontig-test.sh
index b02dae765f..7e478c6705 100755
--- a/test/fs/fat-noncontig-test.sh
+++ b/test/fs/fat-noncontig-test.sh
@@ -60,6 +60,7 @@ testfn=noncontig.img
 mnttestfn=${mnt}/${testfn}
 crcaddr=0
 loadaddr=1000
+[ -n "$SUDO" ] || SUDO=sudo
 
 for prereq in fallocate mkfs.fat dd crc32; do
 if [ ! -x "`which $prereq`" ]; then
@@ -87,7 +88,7 @@ if [ ! -f ${img} ]; then
 exit $?
 fi
 
-sudo mount -o loop,uid=$(id -u) ${img} ${mnt}
+$SUDO mount -o loop,uid=$(id -u) ${img} ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not mount test filesystem
 exit $?
@@ -106,20 +107,20 @@ if [ ! -f ${img} ]; then
 # sector size (ignoring sizes that are multiples of both).
 dd if=${fill} of=${mnttestfn} bs=511 >/dev/null 2>&1
 
-sudo umount ${mnt}
+$SUDO umount ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not unmount test filesystem
 exit $?
 fi
 fi
 
-sudo mount -o ro,loop,uid=$(id -u) ${img} ${mnt}
+$SUDO mount -o ro,loop,uid=$(id -u) ${img} ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not mount test filesystem
 exit $?
 fi
 crc=0x`crc32 ${mnttestfn}`
-sudo umount ${mnt}
+$SUDO umount ${mnt}
 if [ $? -ne 0 ]; then
 echo Could not unmount test filesystem
 exit $?
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index b87748106c..bd55ff51b6 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -55,6 +55,8 @@ OUT="${OUT_DIR}/fs-test"
 MB1="${MOUNT_DIR}/${SMALL_FILE}"
 GB2p5="${MOUNT_DIR}/${BIG_FILE}"
 
+[ -n "$SUDO" ] || SUDO=sudo
+
 # 
 # * Functions start here *
 # 
@@ -351,34 +353,34 @@ EOF
 function create_files() {
# Mount the image so we can populate it.
mkdir -p "$MOUNT_DIR"
-   sudo mount -o loop,rw "$1" "$MOUNT_DIR"
+   $SUDO mount -o loop,rw "$1" "$MOUNT_DIR"
 
# Create a subdirectory.
-   sudo mkdir -p "$MOUNT_DIR/SUBDIR"
+   $SUDO mkdir -p "$MOUNT_DIR/SUBDIR"
 
# Create big file in this image.
# Note that we work only on the start 1MB, couple MBs in the 2GB range
# and the last 1 MB of the huge 2.5GB file.
# So, just put random values only in those areas.
if [ ! -f "${GB2p5}" ]; then
-   sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 \
+   $SUDO dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 \
&> /dev/null
-   sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=2 seek=2047 \
+   $SUDO dd if=/dev/urandom of="${GB2p5}" bs=1M count=2 seek=2047 \
&> /dev/null
-   sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 seek=2499 \
+   $SUDO dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 seek=2499 \
&> /dev/null
fi
 
# Create a small file in this image.
if [ ! -f "${MB1}" ]; then
-   sudo dd if=/dev/urandom of="${MB1}" bs=1M count=1 \
+   $SUDO dd if=/dev/urandom of="${MB1}" bs=1M count=1 \
&> /dev/null
fi
 
# Delete the small file copies which possibly are written as part of a
# previous test.
-   sudo rm -f "${MB1}.w"
-   sudo rm -f "${MB1}.w2"
+   $SUDO rm -f "${MB1}.w"
+   $SUDO rm -f "${MB1}.w2"
 
# Generate the md5sums of reads that we will test against small file
dd if="${MB1}" bs=1M skip=0 count=1 2> /dev/null | md5sum > "$2"
@@ -405,7 +407,7 @@ function create_files() {
2> /dev/null | md5sum >> "$2"
 
sync
-   sudo umount "$MOUNT_DIR"
+   $SUDO umount "$MOUNT_DIR"
rmdir "$MOUNT_DIR"
 }
 
@@ -597,13 +599,13 @@ for fs in ext4 fat16 fat32; do
uid=""
;;
esac
-   sudo mount -o loop,rw,$uid "$IMAGE" "$MOUNT_DIR"
-   sudo chmod 777 "$MOUNT_DIR"
+   $SUDO mount -o loop,rw,$uid "$IMAGE" "$MOUNT_DIR"
+   $SUDO chmod 777 "$MOUNT_DIR"
 
OUT_FILE="${OUT}.sb.${fs

[PATCH] patman: do not hardcode coverage tool

2022-08-24 Thread Michal Suchanek
The coverage tool name varies across distributions.

Add COVERAGE variable to specify the tool name.

Also there is one place where prefix is prepended to the tool path,
remove the prefix.

Signed-off-by: Michal Suchanek 
---
 tools/patman/test_util.py | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/tools/patman/test_util.py b/tools/patman/test_util.py
index 0f6d1aa902..e11806b626 100644
--- a/tools/patman/test_util.py
+++ b/tools/patman/test_util.py
@@ -15,6 +15,8 @@ from patman import command
 
 from io import StringIO
 
+coverage = os.environ.get('COVERAGE', 'python3-coverage')
+
 buffer_outputs = True
 use_concurrent = True
 try:
@@ -58,11 +60,11 @@ def run_test_coverage(prog, filter_fname, exclude_list, 
build_dir, required=None
 prefix = ''
 if build_dir:
 prefix = 'PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools ' % build_dir
-cmd = ('%spython3-coverage run '
-   '--omit "%s" %s %s %s -P1' % (prefix, ','.join(glob_list),
+cmd = ('%s run '
+   '--omit "%s" %s %s %s -P1' % (coverage, ','.join(glob_list),
  prog, extra_args or '', test_cmd))
 os.system(cmd)
-stdout = command.output('python3-coverage', 'report')
+stdout = command.output(coverage, 'report')
 lines = stdout.splitlines()
 if required:
 # Convert '/path/to/name.py' just the module name 'name'
@@ -76,13 +78,13 @@ def run_test_coverage(prog, filter_fname, exclude_list, 
build_dir, required=None
 print(stdout)
 ok = False
 
-coverage = lines[-1].split(' ')[-1]
+cov_result = lines[-1].split(' ')[-1]
 ok = True
-print(coverage)
-if coverage != '100%':
+print(cov_result)
+if cov_result != '100%':
 print(stdout)
-print("To get a report in 'htmlcov/index.html', type: python3-coverage 
html")
-print('Coverage error: %s, but should be 100%%' % coverage)
+print("To get a report in 'htmlcov/index.html', type: %s html" % 
coverage)
+print('Coverage error: %s, but should be 100%%' % cov_result)
 ok = False
 if not ok:
 raise ValueError('Test coverage failure')
-- 
2.37.1



[PATCH] clk: rockchip: rk3399: Fix Unknown clock 77 on mmc@fe310000

2022-08-21 Thread Michal Suchanek
Adding some debug prints I can see:

MMC:   mmc@fe32: Got clock clock-controller@ff76 76
mmc@fe31: Got clock clock-controller@ff76 77
Unknown clock 77
rockchip_dwmmc_get_mmc_clk: err=-2
mmc@fe31: 3, mmc@fe32: 1, mmc@fe33: 0

According to kernel code the SDIO clock is identical to SDMMC clock
except for the con 16->15 change.

Add support for the clock to avoid the error.

Signed-off-by: Michal Suchanek 
---
 drivers/clk/rockchip/clk_rk3399.c | 66 ---
 1 file changed, 43 insertions(+), 23 deletions(-)

diff --git a/drivers/clk/rockchip/clk_rk3399.c 
b/drivers/clk/rockchip/clk_rk3399.c
index 7d31a9f22a..97bf1c6e15 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -728,6 +728,12 @@ static ulong rk3399_mmc_get_clk(struct rockchip_cru *cru, 
uint clk_id)
u32 div, con;
 
switch (clk_id) {
+   case HCLK_SDIO:
+   case SCLK_SDIO:
+   con = readl(>clksel_con[15]);
+   /* dwmmc controller have internal div 2 */
+   div = 2;
+   break;
case HCLK_SDMMC:
case SCLK_SDMMC:
con = readl(>clksel_con[16]);
@@ -750,37 +756,46 @@ static ulong rk3399_mmc_get_clk(struct rockchip_cru *cru, 
uint clk_id)
return DIV_TO_RATE(GPLL_HZ, div);
 }
 
+static void rk3399_dwmmc_set_clk(struct rockchip_cru *cru,
+unsigned int con, ulong set_rate)
+{
+   /* Select clk_sdmmc source from GPLL by default */
+   /* mmc clock defaulg div 2 internal, provide double in cru */
+   int src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
+
+   if (src_clk_div > 128) {
+   /* use 24MHz source for 400KHz clock */
+   src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+   assert(src_clk_div - 1 < 128);
+   rk_clrsetreg(>clksel_con[con],
+CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
+CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
+(src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
+   } else {
+   rk_clrsetreg(>clksel_con[con],
+CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
+CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
+(src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
+   }
+}
+
 static ulong rk3399_mmc_set_clk(struct rockchip_cru *cru,
ulong clk_id, ulong set_rate)
 {
-   int src_clk_div;
-   int aclk_emmc = 198 * MHz;
-
switch (clk_id) {
+   case HCLK_SDIO:
+   case SCLK_SDIO:
+   rk3399_dwmmc_set_clk(cru, 15, set_rate);
+   break;
case HCLK_SDMMC:
case SCLK_SDMMC:
-   /* Select clk_sdmmc source from GPLL by default */
-   /* mmc clock defaulg div 2 internal, provide double in cru */
-   src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
-
-   if (src_clk_div > 128) {
-   /* use 24MHz source for 400KHz clock */
-   src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
-   assert(src_clk_div - 1 < 128);
-   rk_clrsetreg(>clksel_con[16],
-CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
-CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT 
|
-(src_clk_div - 1) << 
CLK_EMMC_DIV_CON_SHIFT);
-   } else {
-   rk_clrsetreg(>clksel_con[16],
-CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
-CLK_EMMC_PLL_SEL_GPLL << 
CLK_EMMC_PLL_SHIFT |
-(src_clk_div - 1) << 
CLK_EMMC_DIV_CON_SHIFT);
-   }
+   rk3399_dwmmc_set_clk(cru, 16, set_rate);
break;
-   case SCLK_EMMC:
+   case SCLK_EMMC: {
+   int aclk_emmc = 198 * MHz;
/* Select aclk_emmc source from GPLL */
-   src_clk_div = DIV_ROUND_UP(GPLL_HZ, aclk_emmc);
+   int src_clk_div = DIV_ROUND_UP(GPLL_HZ, aclk_emmc);
+
assert(src_clk_div - 1 < 32);
 
rk_clrsetreg(>clksel_con[21],
@@ -797,6 +812,7 @@ static ulong rk3399_mmc_set_clk(struct rockchip_cru *cru,
 CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
 (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
break;
+   }
default:
return -EINVAL;
}
@@ -918,6 +934,8 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
switch (clk->id) {
case 0 ... 63:
return 0;
+   case HCLK_SDIO:
+   case 

[PATCH v3] dm: core: Do not stop uclass iteration on error

2022-08-19 Thread Michal Suchanek
When probing a device fails NULL pointer is returned, and other devices
cannot be iterated. Skip to next device on error instead.

Fixes: 6494d708bf ("dm: Add base driver model support")
Signed-off-by: Michal Suchanek 
---
v2: - Fix up tests
v3: - Fix up API doc
- Correctly forward error from uclass_get
- Do not return an error when last device fails to probe
- Drop redundant initialization
- Wrap at 80 columns
---
 drivers/core/uclass.c | 32 
 include/dm/uclass.h   | 13 -
 test/dm/test-fdt.c| 20 
 3 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 08d9ed82de..8f4ecad26c 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -574,16 +574,35 @@ int uclass_get_device_by_phandle(enum uclass_id id, 
struct udevice *parent,
 }
 #endif
 
+/*
+ * Starting from the given device return first device in the uclass that
+ * probes successfully.
+ */
+static int _uclass_next_device(struct udevice *dev, int ret,
+  struct udevice **devp)
+{
+   if (!dev) {
+   *devp = dev;
+   return ret;
+   }
+   while ((ret = uclass_get_device_tail(dev, ret, devp))) {
+   ret = uclass_find_next_device();
+   if (!dev) {
+   *devp = dev;
+   return 0;
+   }
+   }
+
+   return 0;
+}
+
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
struct udevice *dev;
int ret;
 
-   *devp = NULL;
ret = uclass_find_first_device(id, );
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   return _uclass_next_device(dev, ret, devp);
 }
 
 int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
@@ -604,11 +623,8 @@ int uclass_next_device(struct udevice **devp)
struct udevice *dev = *devp;
int ret;
 
-   *devp = NULL;
ret = uclass_find_next_device();
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   return _uclass_next_device(dev, ret, devp);
 }
 
 int uclass_next_device_err(struct udevice **devp)
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index f6c0110b06..76caa0d2b9 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -320,14 +320,14 @@ 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.
+ * occurred, or NULL if there is no usable device
  * Return: 0 if OK (found or not found), other -ve on error
  */
 int uclass_first_device(enum uclass_id id, struct udevice **devp);
@@ -336,6 +336,7 @@ int uclass_first_device(enum uclass_id id, 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
+ * Devices that fail to probe are skipped
  *
  * @id: Uclass ID to look up
  * @devp: Returns pointer to the first device in that uclass, or NULL if none
@@ -347,14 +348,15 @@ int uclass_first_device_err(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
+ * Return: 0 if OK (found or not found)
  */
 int uclass_next_device(struct udevice **devp);
 
@@ -362,11 +364,12 @@ int uclass_next_device(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
+ * Devices that fail to probe are skipped
  *
  * @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.
- * Return: 0 if found, -ENODEV if not found, other -ve on error
+ * Return: 0 if found, -ENODEV if not found
  */
 int uclass_next_device_err(struct udevice **devp);
 

[PATCH v2] dm: core: Do not stop uclass iteration on error.

2022-08-17 Thread Michal Suchanek
When probing a device fails NULL pointer is returned, and other devices
cannot be iterated. Skip to next device on error instead.

Fixes: 6494d708bf ("dm: Add base driver model support")
Signed-off-by: Michal Suchanek 
---
v2: Fix up tests

Note: there is seemingly bogus repeated device_remove(parent, DM_REMOVE_NORMAL);
but I have no idea what the intent was, and fixing that is out of the
scope of this patch anyway.

 drivers/core/uclass.c | 30 +-
 test/dm/test-fdt.c| 20 
 2 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 08d9ed82de..ccf7d59141 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -574,16 +574,31 @@ int uclass_get_device_by_phandle(enum uclass_id id, 
struct udevice *parent,
 }
 #endif
 
+/* Starting from the given device return first device in the uclass that 
probes successfully */
+static int __uclass_next_device(struct udevice *dev, int ret, struct udevice 
**devp)
+{
+   if (!dev) {
+   *devp = dev;
+   return 0;
+   }
+   while ((ret = uclass_get_device_tail(dev, ret, devp))) {
+   ret = uclass_find_next_device();
+   if (!dev) {
+   *devp = dev;
+   return 0;
+   }
+   }
+
+   return ret;
+}
+
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
-   struct udevice *dev;
+   struct udevice *dev = NULL;
int ret;
 
-   *devp = NULL;
ret = uclass_find_first_device(id, );
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   return __uclass_next_device(dev, ret, devp);
 }
 
 int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
@@ -604,11 +619,8 @@ int uclass_next_device(struct udevice **devp)
struct udevice *dev = *devp;
int ret;
 
-   *devp = NULL;
ret = uclass_find_next_device();
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   return __uclass_next_device(dev, ret, devp);
 }
 
 int uclass_next_device_err(struct udevice **devp)
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 6118ad42ca..165b4f5554 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -417,16 +417,28 @@ static int dm_test_first_next_device(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, ));
-   ut_asserteq(-ENOMEM, uclass_next_device());
-   ut_asserteq_ptr(dev, NULL);
+   for (ret = uclass_first_device(UCLASS_TEST_PROBE, ), count = 0;
+dev;
+ret = uclass_next_device()) {
+   count++;
+   parent = dev_get_parent(dev);
+   }
+   ut_assertok(ret);
+   ut_asserteq(3, count);
 
/* Now an error on the first one */
ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, ));
pdata = dev_get_plat(dev);
pdata->probe_err = -ENOENT;
device_remove(parent, DM_REMOVE_NORMAL);
-   ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, ));
+   for (ret = uclass_first_device(UCLASS_TEST_PROBE, ), count = 0;
+dev;
+ret = uclass_next_device()) {
+   count++;
+   parent = dev_get_parent(dev);
+   }
+   ut_assertok(ret);
+   ut_asserteq(2, count);
 
return 0;
 }
-- 
2.37.1



[PATCH] power: pmic: rk8xx: Workaround pmic failure when probed before relocation

2022-08-05 Thread Michal Suchanek
When the sysreset is added as child of the pmic the pmic is probed
before relocation. That probe fails, and subsequent attempts to probe
after reloaction fail as well.

As a workaround do not bind the sysreset before relocation.

Signed-off-by: Michal Suchanek 
---
 drivers/power/pmic/rk8xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index a239a18674..d12263c4f2 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -131,7 +131,7 @@ static int rk8xx_read(struct udevice *dev, uint reg, 
uint8_t *buff, int len)
 
 static int rk8xx_bind(struct udevice *dev)
 {
-   if (CONFIG_IS_ENABLED(SYSRESET)) {
+   if (CONFIG_IS_ENABLED(SYSRESET) && (gd->flags & GD_FLG_RELOC)) {
device_bind_driver(dev, "rk8xx_sysreset",
   "rk8xx_sysreset", NULL);
}
-- 
2.37.1



[PATCH] power: pmic: rk8xx: Remove some ifdefs

2022-08-04 Thread Michal Suchanek
After adding the poweroff support there are some incorrectly nested
ifdefs. Move the poweroff code outside of ifdef and convert it to if.

Fixes: ad607512f5 ("power: pmic: rk8xx: Support sysreset shutdown method")
Signed-off-by: Michal Suchanek 
---
 drivers/power/pmic/rk8xx.c | 41 +-
 1 file changed, 18 insertions(+), 23 deletions(-)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index 25ef621f8d..a239a18674 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -129,37 +129,34 @@ static int rk8xx_read(struct udevice *dev, uint reg, 
uint8_t *buff, int len)
return 0;
 }
 
-#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
 static int rk8xx_bind(struct udevice *dev)
 {
-   ofnode regulators_node;
-   int children, ret;
-
-   regulators_node = dev_read_subnode(dev, "regulators");
-   if (!ofnode_valid(regulators_node)) {
-   debug("%s: %s regulators subnode not found!\n", __func__,
- dev->name);
-   return -ENXIO;
+   if (CONFIG_IS_ENABLED(SYSRESET)) {
+   device_bind_driver(dev, "rk8xx_sysreset",
+  "rk8xx_sysreset", NULL);
}
 
-   debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+   if (CONFIG_IS_ENABLED(PMIC_CHILDREN)) {
+   ofnode regulators_node;
+   int children;
 
-   if (CONFIG_IS_ENABLED(SYSRESET)) {
-   ret = device_bind_driver_to_node(dev, "rk8xx_sysreset",
-"rk8xx_sysreset",
-dev_ofnode(dev), NULL);
-   if (ret)
-   return ret;
-   }
+   regulators_node = dev_read_subnode(dev, "regulators");
+   if (!ofnode_valid(regulators_node)) {
+   debug("%s: %s regulators subnode not found!\n", 
__func__,
+ dev->name);
+   return -ENXIO;
+   }
+
+   debug("%s: '%s' - found regulators subnode\n", __func__, 
dev->name);
 
-   children = pmic_bind_children(dev, regulators_node, pmic_children_info);
-   if (!children)
-   debug("%s: %s - no child found\n", __func__, dev->name);
+   children = pmic_bind_children(dev, regulators_node, 
pmic_children_info);
+   if (!children)
+   debug("%s: %s - no child found\n", __func__, dev->name);
+   }
 
/* Always return success for this device */
return 0;
 }
-#endif
 
 static int rk8xx_probe(struct udevice *dev)
 {
@@ -269,9 +266,7 @@ U_BOOT_DRIVER(rockchip_rk805) = {
.name = "rockchip_rk805",
.id = UCLASS_PMIC,
.of_match = rk8xx_ids,
-#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
.bind = rk8xx_bind,
-#endif
.priv_auto= sizeof(struct rk8xx_priv),
.probe = rk8xx_probe,
.ops = _ops,
-- 
2.37.1



[PATCH] dm: core: Do not stop uclass iteration on error.

2022-08-04 Thread Michal Suchanek
When probing a device fails NULL pointer is returned, and other devices
cannot be iterated. Skip to next device on error instead.

Fixes: 6494d708bf ("dm: Add base driver model support")
Signed-off-by: Michal Suchanek 
---
 drivers/core/uclass.c | 30 +-
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 08d9ed82de..ccf7d59141 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -574,16 +574,31 @@ int uclass_get_device_by_phandle(enum uclass_id id, 
struct udevice *parent,
 }
 #endif
 
+/* Starting from the given device return first device in the uclass that 
probes successfully */
+static int __uclass_next_device(struct udevice *dev, int ret, struct udevice 
**devp)
+{
+   if (!dev) {
+   *devp = dev;
+   return 0;
+   }
+   while ((ret = uclass_get_device_tail(dev, ret, devp))) {
+   ret = uclass_find_next_device();
+   if (!dev) {
+   *devp = dev;
+   return 0;
+   }
+   }
+
+   return ret;
+}
+
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
-   struct udevice *dev;
+   struct udevice *dev = NULL;
int ret;
 
-   *devp = NULL;
ret = uclass_find_first_device(id, );
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   return __uclass_next_device(dev, ret, devp);
 }
 
 int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
@@ -604,11 +619,8 @@ int uclass_next_device(struct udevice **devp)
struct udevice *dev = *devp;
int ret;
 
-   *devp = NULL;
ret = uclass_find_next_device();
-   if (!dev)
-   return 0;
-   return uclass_get_device_tail(dev, ret, devp);
+   return __uclass_next_device(dev, ret, devp);
 }
 
 int uclass_next_device_err(struct udevice **devp)
-- 
2.37.1



[PATCH] doc: dm: clarify activation.

2022-08-04 Thread Michal Suchanek
Explain when devices should get activated.

Signed-off-by: Michal Suchanek 
---
 doc/develop/driver-model/design.rst | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/doc/develop/driver-model/design.rst 
b/doc/develop/driver-model/design.rst
index 5f33f9fbb3..c925d21b24 100644
--- a/doc/develop/driver-model/design.rst
+++ b/doc/develop/driver-model/design.rst
@@ -794,8 +794,26 @@ fall afoul of this rule.
 Activation/probe
 
 
-When a device needs to be used, U-Boot activates it, by first reading ofdata
-as above and then following these steps (see device_probe()):
+To save resources devices in U-Boot are probed lazily. U-Boot is a bootloader,
+not an operating system. Many devices are never used during an U-Boot run, and
+probing them takes time, requires memory, may add delays to the main loop, etc.
+
+The device should be probed by the uclass code. Different uclasses are
+different but two common use cases can be seen:
+
+   1. The uclass is asked to look up a specific device, such as SPI bus 0,
+   first chip select - in this case the returned device should be
+   activated.
+
+   2. The uclass is asked to perform a specific function on any device that
+   supports it, eg. reset the board using any sysreset that can be found -
+   for this case the core uclass code provides iterators that activate
+   each device before returning it, and the uclass typically implements a
+   walk function that iterates over all devices of the uclass and tries
+   to perform the requested function on each in turn until succesful.
+
+To activate a device U-Boot first reads ofdata as above and then follows these
+steps (see device_probe()):
 
1. All parent devices are probed. It is not possible to activate a device
unless its predecessors (all the way up to the root device) are activated.
-- 
2.37.1



[PATCH v2] sunxi: dts: Fix SPI NOR campatible on Orange Pi Zero

2022-07-09 Thread Michal Suchanek
The device tree should include generic "jedec,spi-nor" compatible, and a
manufacturer-specific one.
The macronix part is what is shipped on the boards that come with a
flash chip.

Fixes: 280294c5df ("sunxi: boards: Enable SPI flash support in U-Boot proper")
Signed-off-by: Michal Suchanek 
---
v2: cherry-pick from Linux
 arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts 
b/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts
index b08e84c616..80c1e66b38 100644
--- a/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts
+++ b/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -170,7 +170,7 @@
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
-   compatible = "mxicy,mx25l1606e", "winbond,w25q128";
+   compatible = "mxicy,mx25l1606e", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <4000>;
};
-- 
2.36.1



[PATCH] sunxi: dts: OrangePi Zero: Fixup SPI flash device node

2022-07-07 Thread Michal Suchanek
For some reason the flash cannot be probed as is - the u-boot DT lookup
code fails to find the definition, and sf complains about invalid cs.

Fixes: 280294c5df ("sunxi: boards: Enable SPI flash support in U-Boot proper")
Signed-off-by: Michal Suchanek 
---
 arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts 
b/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts
index b08e84c616..034f0f77a0 100644
--- a/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts
+++ b/arch/arm/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -167,10 +167,8 @@
/* Enable SPI NOR by default: it optional on Orange Pi Zero boards */
status = "okay";
 
-   flash@0 {
-   #address-cells = <1>;
-   #size-cells = <1>;
-   compatible = "mxicy,mx25l1606e", "winbond,w25q128";
+   spiflash: flash@0 {
+   compatible = "mxicy,mx25l1606e", "winbond,w25q128", 
"jedec,spi-nor";
reg = <0>;
spi-max-frequency = <4000>;
};
-- 
2.36.1



  1   2   3   >