Merge tag 'dm-pull-29oct22' of https://source.denx.de/u-boot/custodians/u-boot-dm

Fix pylibfdt warnings and use setuptools to build
Various minor changes to core dm and sandbox
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 852a7c8..35508c6 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -13,7 +13,7 @@
 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 @@
 	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/arch/x86/cpu/i386/setjmp.S b/arch/x86/cpu/i386/setjmp.S
index 40b10dc..eceeafa 100644
--- a/arch/x86/cpu/i386/setjmp.S
+++ b/arch/x86/cpu/i386/setjmp.S
@@ -49,12 +49,17 @@
 	xchgl %eax, %edx
 #else
 	movl 4(%esp), %edx	/* jmp_ptr address */
+	movl 8(%esp), %eax	/* Return value */
 #endif
 	movl (%edx), %ebx
 	movl 4(%edx), %esp
 	movl 8(%edx), %ebp
 	movl 12(%edx), %esi
 	movl 16(%edx), %edi
+	test %eax, %eax
+	jnz nz
+	inc %eax
+nz:
 	jmp *20(%edx)
 
 	.size longjmp, .-longjmp
diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h
index 49c36c1..15915d0 100644
--- a/arch/x86/include/asm/setjmp.h
+++ b/arch/x86/include/asm/setjmp.h
@@ -34,7 +34,9 @@
 
 #endif
 
-int setjmp(struct jmp_buf_data *jmp_buf);
-void longjmp(struct jmp_buf_data *jmp_buf, int val);
+typedef struct jmp_buf_data jmp_buf[1];
+
+int setjmp(jmp_buf env);
+void longjmp(jmp_buf env, int val);
 
 #endif
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index ca9a2ca..38cfa08 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -129,7 +129,7 @@
 		snprintf(extension->name, sizeof(extension->name), "extension board %d", i);
 		snprintf(extension->owner, sizeof(extension->owner), "sandbox");
 		snprintf(extension->version, sizeof(extension->version), "1.1");
-		snprintf(extension->other, sizeof(extension->other), "Fictionnal extension board");
+		snprintf(extension->other, sizeof(extension->other), "Fictional extension board");
 		list_add_tail(&extension->list, extension_list);
 	}
 
diff --git a/cmd/virtio.c b/cmd/virtio.c
index ec87d4f..019e317 100644
--- a/cmd/virtio.c
+++ b/cmd/virtio.c
@@ -23,18 +23,15 @@
 		 * device_probe() for children (i.e. virtio devices)
 		 */
 		struct udevice *bus, *child;
-		int ret;
 
-		ret = uclass_first_device(UCLASS_VIRTIO, &bus);
-		if (ret)
+		uclass_first_device(UCLASS_VIRTIO, &bus);
+		if (!bus)
 			return CMD_RET_FAILURE;
 
 		while (bus) {
 			device_foreach_child_probe(child, bus)
 				;
-			ret = uclass_next_device(&bus);
-			if (ret)
-				break;
+			uclass_next_device(&bus);
 		}
 
 		return CMD_RET_SUCCESS;
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 0475672..e28f1e8 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -54,6 +54,7 @@
 CONFIG_CMD_READ=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_TEMPERATURE=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_CAT=y
 CONFIG_CMD_WDT=y
@@ -220,6 +221,7 @@
 CONFIG_SYSINFO_SANDBOX=y
 CONFIG_SYSINFO_GPIO=y
 CONFIG_SYSRESET=y
+CONFIG_DM_THERMAL=y
 CONFIG_TIMER=y
 CONFIG_TIMER_EARLY=y
 CONFIG_SANDBOX_TIMER=y
diff --git a/doc/develop/driver-model/serial-howto.rst b/doc/develop/driver-model/serial-howto.rst
index 9da0e57..5b1d57d 100644
--- a/doc/develop/driver-model/serial-howto.rst
+++ b/doc/develop/driver-model/serial-howto.rst
@@ -62,7 +62,7 @@
 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 @@
        };
 
 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.
 
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 0dc442b..b79e99b 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -350,6 +350,20 @@
 	  used for the address translation. This function is faster and
 	  smaller in size than fdt_translate_address().
 
+config TPL_OF_TRANSLATE
+	bool "Translate addresses using fdt_translate_address in TPL"
+	depends on TPL_DM && TPL_OF_CONTROL
+	help
+	  If this option is enabled, the reg property will be translated
+	  using the fdt_translate_address() function. This is necessary
+	  on some platforms (e.g. MVEBU) using complex "ranges"
+	  properties in many nodes. As this translation is not handled
+	  correctly in the default simple_bus_translate() function.
+
+	  If this option is not enabled, simple_bus_translate() will be
+	  used for the address translation. This function is faster and
+	  smaller in size than fdt_translate_address()
+
 config VPL_OF_TRANSLATE
 	bool "Translate addresses using fdt_translate_address in SPL"
 	depends on SPL_DM && VPL_OF_CONTROL
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index c49695b..3878957 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -222,6 +222,7 @@
 		log_debug("   - attempt to match compatible string '%s'\n",
 			  compat);
 
+		id = NULL;
 		for (entry = driver; entry != driver + n_ents; entry++) {
 			if (drv) {
 				if (drv != entry)
@@ -250,7 +251,8 @@
 				  entry->name, entry->of_match->compatible,
 				  id->compatible);
 		ret = device_bind_with_driver_data(parent, entry, name,
-						   id->data, node, &dev);
+						   id ? id->data : 0, node,
+						   &dev);
 		if (ret == -ENODEV) {
 			log_debug("Driver '%s' refuses to bind\n", entry->name);
 			continue;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index b7d11bd..1762a07 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -574,28 +574,34 @@
 }
 #endif
 
-int uclass_first_device(enum uclass_id id, struct udevice **devp)
+/*
+ * Starting from the given device @dev, return pointer to the first device in
+ * the uclass that probes successfully in @devp.
+ */
+static void _uclass_next_device(struct udevice *dev, struct udevice **devp)
+{
+	for (; dev; uclass_find_next_device(&dev)) {
+		if (!device_probe(dev))
+			break;
+	}
+	*devp = dev;
+}
+
+void uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
 	struct udevice *dev;
 	int ret;
 
-	*devp = NULL;
 	ret = uclass_find_first_device(id, &dev);
-	if (!dev)
-		return 0;
-	return uclass_get_device_tail(dev, ret, devp);
+	_uclass_next_device(dev, devp);
 }
 
-int uclass_next_device(struct udevice **devp)
+void uclass_next_device(struct udevice **devp)
 {
 	struct udevice *dev = *devp;
-	int ret;
 
-	*devp = NULL;
-	ret = uclass_find_next_device(&dev);
-	if (!dev)
-		return 0;
-	return uclass_get_device_tail(dev, ret, devp);
+	uclass_find_next_device(&dev);
+	_uclass_next_device(dev, devp);
 }
 
 int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 81dbb4d..34f72fa 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -210,10 +210,9 @@
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
 	struct udevice *dev;
-	int ret;
 
-	for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret;
-	     ret = uclass_next_device(&dev)) {
+	for (uclass_first_device(UCLASS_DMA, &dev); dev;
+	     uclass_next_device(&dev)) {
 		struct dma_dev_priv *uc_priv;
 
 		uc_priv = dev_get_uclass_priv(dev);
@@ -229,7 +228,7 @@
 
 	*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 a00880e..3a6ef3b 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -59,11 +59,10 @@
 {
 	struct gpio_dev_priv *uc_priv;
 	struct udevice *dev;
-	int ret;
 
-	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+	for (uclass_first_device(UCLASS_GPIO, &dev);
 	     dev;
-	     ret = uclass_next_device(&dev)) {
+	     uclass_next_device(&dev)) {
 		uc_priv = dev_get_uclass_priv(dev);
 		if (gpio >= uc_priv->gpio_base &&
 		    gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
@@ -73,7 +72,7 @@
 	}
 
 	/* No such GPIO */
-	return ret ? ret : -ENOENT;
+	return -ENOENT;
 }
 
 #if CONFIG_IS_ENABLED(DM_GPIO_LOOKUP_LABEL)
@@ -91,15 +90,13 @@
 static int dm_gpio_lookup_label(const char *name,
 				struct gpio_dev_priv *uc_priv, ulong *offset)
 {
-	int len;
 	int i;
 
 	*offset = -1;
-	len = strlen(name);
 	for (i = 0; i < uc_priv->gpio_count; i++) {
 		if (!uc_priv->name[i])
 			continue;
-		if (!strncmp(name, uc_priv->name[i], len)) {
+		if (!strcmp(name, uc_priv->name[i])) {
 			*offset = i;
 			return 0;
 		}
@@ -121,12 +118,11 @@
 	struct udevice *dev;
 	ulong offset;
 	int numeric;
-	int ret;
 
 	numeric = isdigit(*name) ? dectoul(name, NULL) : -1;
-	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+	for (uclass_first_device(UCLASS_GPIO, &dev);
 	     dev;
-	     ret = uclass_next_device(&dev)) {
+	     uclass_next_device(&dev)) {
 		int len;
 
 		uc_priv = dev_get_uclass_priv(dev);
@@ -154,7 +150,7 @@
 	}
 
 	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 5cff81a..9343cfc 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1211,7 +1211,6 @@
 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 @@
 			*devp = dev;
 			return 0;
 		}
-		ret = uclass_next_device(&bus);
-		if (ret)
-			return ret;
+		uclass_next_device(&bus);
 	}
 
 	return 0;
@@ -1235,7 +1232,6 @@
 {
 	struct udevice *child = *devp;
 	struct udevice *bus = child->parent;
-	int ret;
 
 	/* First try all the siblings */
 	*devp = NULL;
@@ -1248,9 +1244,7 @@
 	}
 
 	/* We ran out of siblings. Try the next bus */
-	ret = uclass_next_device(&bus);
-	if (ret)
-		return ret;
+	uclass_next_device(&bus);
 
 	return bus ? skip_to_next_device(bus, devp) : 0;
 }
@@ -1258,12 +1252,9 @@
 int pci_find_first_device(struct udevice **devp)
 {
 	struct udevice *bus;
-	int ret;
 
 	*devp = NULL;
-	ret = uclass_first_device(UCLASS_PCI, &bus);
-	if (ret)
-		return ret;
+	uclass_first_device(UCLASS_PCI, &bus);
 
 	return skip_to_next_device(bus, devp);
 }
@@ -1777,10 +1768,9 @@
 
 	bdf = dm_pci_get_bdf(pdev);
 
-	pci_get_bus(PCI_BUS(bdf), &bus);
-
-	if (!bus)
-		return -ENODEV;
+	ret = pci_get_bus(PCI_BUS(bdf), &bus);
+	if (ret)
+		return ret;
 
 	bdf += PCI_BDF(0, 0, vf_offset);
 
diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c
index c5cc3cb..10194d0 100644
--- a/drivers/sysinfo/sysinfo-uclass.c
+++ b/drivers/sysinfo/sysinfo-uclass.c
@@ -16,7 +16,15 @@
 
 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/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c
index de4f25b..a4247ec 100644
--- a/drivers/w1/w1-uclass.c
+++ b/drivers/w1/w1-uclass.c
@@ -36,15 +36,10 @@
 {
 	struct udevice *dev;
 	u8 family = id & 0xff;
-	int ret;
 
-	for (ret = uclass_first_device(UCLASS_W1_EEPROM, &dev);
-		!ret && dev;
+	for (uclass_first_device(UCLASS_W1_EEPROM, &dev);
+		dev;
 		uclass_next_device(&dev)) {
-		if (ret || !dev) {
-			debug("cannot find w1 eeprom dev\n");
-			return -ENODEV;
-		}
 
 		if (dev_get_driver_data(dev) == family) {
 			*devp = dev;
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 94844d3..f31c470 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -184,8 +184,8 @@
 /**
  * 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
diff --git a/include/dm/lists.h b/include/dm/lists.h
index fc3b4ae..97236f8 100644
--- a/include/dm/lists.h
+++ b/include/dm/lists.h
@@ -73,6 +73,7 @@
  * @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 @@
  * @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,
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 823a165..ee15c92 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -320,37 +320,37 @@
  * 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
  *
- * 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 +361,8 @@
 /**
  * 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 +374,8 @@
 /**
  * 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 +391,8 @@
 /**
  * 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.
diff --git a/include/fdt_support.h b/include/fdt_support.h
index b838071..5638bd4 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -243,8 +243,6 @@
 
 int fdt_delete_disabled_nodes(void *blob);
 
-int fdt_fixup_nor_flash_size(void *blob);
-
 struct node_info;
 #if defined(CONFIG_FDT_FIXUP_PARTITIONS)
 void fdt_fixup_mtdparts(void *fdt, const struct node_info *node_info,
diff --git a/include/pci.h b/include/pci.h
index d7ed35d..c55d610 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -957,7 +957,7 @@
 /**
  * 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.
  *
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index dad5583..b7598ca 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -22,6 +22,10 @@
 # Return y if the compiler supports <flag>, n otherwise
 cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
 
+# $(cc-define,<macro>)
+# Return y if the compiler defines <macro>, n otherwise
+cc-define = $(success,$(CC) -dM -E -x c /dev/null | grep -q '^#define \<$(1)\>')
+
 # $(ld-option,<flag>)
 # Return y if the linker supports <flag>, n otherwise
 ld-option = $(success,$(LD) -v $(1))
diff --git a/scripts/dtc/README b/scripts/dtc/README
new file mode 100644
index 0000000..a48312a
--- /dev/null
+++ b/scripts/dtc/README
@@ -0,0 +1,106 @@
+The source tree contains the Device Tree Compiler (dtc) toolchain for
+working with device tree source and binary files and also libfdt, a
+utility library for reading and manipulating the binary format.
+
+DTC and LIBFDT are maintained by:
+
+David Gibson <david@gibson.dropbear.id.au>
+Jon Loeliger <loeliger@gmail.com>
+
+
+Python library
+--------------
+
+A Python library is also available. To build this you will need to install
+swig and Python development files. On Debian distributions:
+
+   sudo apt-get install swig python3-dev
+
+The library provides an Fdt class which you can use like this:
+
+$ PYTHONPATH=../pylibfdt python3
+>>> import libfdt
+>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
+>>> node = fdt.path_offset('/subnode@1')
+>>> print(node)
+124
+>>> prop_offset = fdt.first_property_offset(node)
+>>> prop = fdt.get_property_by_offset(prop_offset)
+>>> print('%s=%s' % (prop.name, prop.as_str()))
+compatible=subnode1
+>>> node2 = fdt.path_offset('/')
+>>> print(fdt.getprop(node2, 'compatible').as_str())
+test_tree1
+
+You will find tests in tests/pylibfdt_tests.py showing how to use each
+method. Help is available using the Python help command, e.g.:
+
+    $ cd pylibfdt
+    $ python3 -c "import libfdt; help(libfdt)"
+
+If you add new features, please check code coverage:
+
+    $ sudo apt-get install python3-coverage
+    $ cd tests
+    # It's just 'coverage' on most other distributions
+    $ python3-coverage run pylibfdt_tests.py
+    $ python3-coverage html
+    # Open 'htmlcov/index.html' in your browser
+
+
+The library can be installed with pip from a local source tree:
+
+    pip install . [--user|--prefix=/path/to/install_dir]
+
+Or directly from a remote git repo:
+
+    pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
+
+The install depends on libfdt shared library being installed on the host system
+first. Generally, using --user or --prefix is not necessary and pip will use the
+default location for the Python installation which varies if the user is root or
+not.
+
+You can also install everything via make if you like, but pip is recommended.
+
+To install both libfdt and pylibfdt you can use:
+
+    make install [PREFIX=/path/to/install_dir]
+
+To disable building the python library, even if swig and Python are available,
+use:
+
+    make NO_PYTHON=1
+
+
+More work remains to support all of libfdt, including access to numeric
+values.
+
+
+Adding a new function to libfdt.h
+---------------------------------
+
+The shared library uses libfdt/version.lds to list the exported functions, so
+add your new function there. Check that your function works with pylibfdt. If
+it cannot be supported, put the declaration in libfdt.h behind #ifndef SWIG so
+that swig ignores it.
+
+
+Tests
+-----
+
+Test files are kept in the tests/ directory. Use 'make check' to build and run
+all tests.
+
+If you want to adjust a test file, be aware that tree_tree1.dts is compiled
+and checked against a binary tree from assembler macros in trees.S. So
+if you change that file you must change tree.S also.
+
+
+Mailing list
+------------
+The following list is for discussion about dtc and libfdt implementation
+mailto:devicetree-compiler@vger.kernel.org
+
+Core device tree bindings are discussed on the devicetree-spec list:
+mailto:devicetree-spec@vger.kernel.org
diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile
index 493995e..e442d5c 100644
--- a/scripts/dtc/pylibfdt/Makefile
+++ b/scripts/dtc/pylibfdt/Makefile
@@ -13,11 +13,14 @@
 PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \
 		$(obj)/libfdt.i
 
+# create a version string compliant with PEP 440
+PEP_VERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(subst -,,$(EXTRAVERSION))
+
 quiet_cmd_pymod = PYMOD   $@
       cmd_pymod = unset CROSS_COMPILE; unset CFLAGS; \
 		CC="$(HOSTCC)" LDSHARED="$(HOSTCC) -shared " \
 		LDFLAGS="$(HOSTLDFLAGS)" \
-		VERSION="u-boot-$(UBOOTVERSION)" \
+		VERSION="$(PEP_VERSION)" \
 		CPPFLAGS="$(HOSTCFLAGS) -I$(LIBFDT_srcdir)" OBJDIR=$(obj) \
 		SOURCES="$(PYLIBFDT_srcs)" \
 		SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \
diff --git a/scripts/dtc/pylibfdt/libfdt.i_shipped b/scripts/dtc/pylibfdt/libfdt.i_shipped
index 27c29ea..56cc5d4 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 <stdint.i>
 
 %{
diff --git a/scripts/dtc/pylibfdt/setup.py b/scripts/dtc/pylibfdt/setup.py
index 992cdec..ec1fc50 100755
--- a/scripts/dtc/pylibfdt/setup.py
+++ b/scripts/dtc/pylibfdt/setup.py
@@ -1,11 +1,13 @@
 #!/usr/bin/env python3
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 
 """
 setup.py file for SWIG libfdt
 Copyright (C) 2017 Google, Inc.
 Written by Simon Glass <sjg@chromium.org>
 
-SPDX-License-Identifier:	GPL-2.0+ BSD-2-Clause
+This script is modified from the upstream version, to fit in with the U-Boot
+build system.
 
 Files to be built into the extension are provided in SOURCES
 C flags to use are provided in CPPFLAGS
@@ -18,14 +20,29 @@
     ./pylibfdt/setup.py install [--prefix=...]
 """
 
-from distutils.core import setup, Extension
+from setuptools import setup, Extension
+from setuptools.command.build_py import build_py as _build_py
 import os
 import re
 import sys
 
+srcdir = os.path.dirname(__file__)
+
+with open(os.path.join(srcdir, "../README"), "r") as fh:
+    long_description = fh.read()
+
 # Decodes a Makefile assignment line into key and value (and plus for +=)
 RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')
 
+def get_top_builddir():
+    if '--top-builddir' in sys.argv:
+        index = sys.argv.index('--top-builddir')
+        sys.argv.pop(index)
+        return sys.argv.pop(index)
+    else:
+        return os.path.join(srcdir, '..')
+
+top_builddir = get_top_builddir()
 
 def ParseMakefile(fname):
     """Parse a Makefile to obtain its variables.
@@ -86,7 +103,7 @@
     makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
     files = makevars['LIBFDT_SRCS'].split()
     files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
-    files.append('pylibfdt/libfdt.i')
+    files.append('libfdt.i')
     cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
     objdir = ''
     return swig_opts, version, files, cflags, objdir
@@ -107,17 +124,39 @@
 
 libfdt_module = Extension(
     '_libfdt',
-    sources = files,
-    extra_compile_args = cflags,
-    swig_opts = swig_opts,
+    sources=files,
+    include_dirs=[os.path.join(srcdir, 'libfdt')],
+    library_dirs=[os.path.join(top_builddir, 'libfdt')],
+    swig_opts=swig_opts,
 )
 
+class build_py(_build_py):
+    def run(self):
+        self.run_command("build_ext")
+        return super().run()
+
 setup(
     name='libfdt',
-    version= version,
-    author='Simon Glass <sjg@chromium.org>',
+    version=version,
+    cmdclass = {'build_py' : build_py},
+    author='Simon Glass',
+    author_email='sjg@chromium.org',
     description='Python binding for libfdt',
     ext_modules=[libfdt_module],
     package_dir={'': objdir},
-    py_modules=['pylibfdt/libfdt'],
+    py_modules=['libfdt'],
+
+    long_description=long_description,
+    long_description_content_type="text/plain",
+    url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git",
+    license="BSD",
+    license_files=["GPL", "BSD-2-Clause"],
+
+    classifiers=[
+        "Programming Language :: Python :: 3",
+        "License :: OSI Approved :: BSD License",
+        "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
+        "Operating System :: OS Independent",
+    ],
+
 )
diff --git a/scripts/event_dump.py b/scripts/event_dump.py
index 6aadddf..d87823f 100755
--- a/scripts/event_dump.py
+++ b/scripts/event_dump.py
@@ -108,8 +108,6 @@
     parser.add_argument('elf', type=str, help='ELF file to decode')
     parser.add_argument('-e', '--endian', type=str, default='auto',
                         help='Big-endian image')
-    parser.add_argument('-t', '--test', action='store_true',
-                        help='Big-endian image')
     args = parser.parse_args(argv)
     show_event_spy_list(args.elf, args.endian)
 
diff --git a/test/dm/core.c b/test/dm/core.c
index 84eb76e..7f3f8d1 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -1078,11 +1078,10 @@
 	struct udevice *dev;
 	int ret;
 
-	for (ret = uclass_first_device(UCLASS_TEST, &dev);
+	for (ret = uclass_first_device_check(UCLASS_TEST, &dev);
 	     dev;
-	     ret = uclass_next_device(&dev)) {
+	     ret = uclass_next_device_check(&dev)) {
 		ut_assert(!ret);
-		ut_assert(dev);
 		ut_assert(device_active(dev));
 	}
 
@@ -1112,11 +1111,10 @@
 	 * this will fail on checking condition: testdev == finddev, since the
 	 * uclass_get_device_by_name(), returns the first device by given name.
 	*/
-	for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev);
+	for (ret = uclass_first_device_check(UCLASS_TEST_FDT, &testdev);
 	     testdev;
-	     ret = uclass_next_device(&testdev)) {
+	     ret = uclass_next_device_check(&testdev)) {
 		ut_assertok(ret);
-		ut_assert(testdev);
 		ut_assert(device_active(testdev));
 
 		findret = uclass_get_device_by_name(UCLASS_TEST_FDT,
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 1f14513..8bb868b 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -403,13 +403,12 @@
 	int ret;
 
 	/* There should be 4 devices */
-	for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
+	for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
 	     dev;
-	     ret = uclass_next_device(&dev)) {
+	     uclass_next_device(&dev)) {
 		count++;
 		parent = dev_get_parent(dev);
 		}
-	ut_assertok(ret);
 	ut_asserteq(4, count);
 
 	/* Remove them and try again, with an error on the second one */
@@ -417,16 +416,30 @@
 	pdata = dev_get_plat(dev);
 	pdata->probe_err = -ENOMEM;
 	device_remove(parent, DM_REMOVE_NORMAL);
-	ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev));
-	ut_asserteq(-ENOMEM, uclass_next_device(&dev));
-	ut_asserteq_ptr(dev, NULL);
+	for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev),
+		count = 0;
+	     dev;
+	     ret = uclass_next_device_check(&dev)) {
+		if (!ret)
+			count++;
+		else
+			ut_asserteq(-ENOMEM, ret);
+		parent = dev_get_parent(dev);
+		}
+	ut_asserteq(3, count);
 
 	/* Now an error on the first one */
 	ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev));
 	pdata = dev_get_plat(dev);
 	pdata->probe_err = -ENOENT;
 	device_remove(parent, DM_REMOVE_NORMAL);
-	ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev));
+	for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
+	     dev;
+	     uclass_next_device(&dev)) {
+		count++;
+		parent = dev_get_parent(dev);
+		}
+	ut_asserteq(2, count);
 
 	/* Now that broken devices are set up test probe_all */
 	device_remove(parent, DM_REMOVE_NORMAL);
diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
index e63c25d..674df2e 100644
--- a/test/py/tests/test_event_dump.py
+++ b/test/py/tests/test_event_dump.py
@@ -16,7 +16,7 @@
     out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
     expect = '''.*Event type            Id                              Source location
 --------------------  ------------------------------  ------------------------------
-EVT_FT_FIXUP          bootmeth_vbe_ft_fixup           .*boot/vbe_fixup.c:.*
-EVT_FT_FIXUP          bootmeth_vbe_simple_ft_fixup    .*boot/vbe_simple.c:.*
-EVT_MISC_INIT_F       sandbox_misc_init_f             .*arch/sandbox/cpu/start.c:'''
+EVT_FT_FIXUP          bootmeth_vbe_ft_fixup           .*vbe_fixup.c:.*
+EVT_FT_FIXUP          bootmeth_vbe_simple_ft_fixup    .*vbe_simple.c:.*
+EVT_MISC_INIT_F       sandbox_misc_init_f             .*start.c:'''
     assert re.match(expect, out, re.MULTILINE) is not None
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 4ee6f41..d8a3d77 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -780,6 +780,9 @@
     This means that each section must specify its own default alignment, if
     required.
 
+symlink:
+    Adds a symlink to the image with string given in the symlink property.
+
 Examples of the above options can be found in the tests. See the
 tools/binman/test directory.
 
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 261107b..232ac2c 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -5995,6 +5995,15 @@
         self.assertIn('Expected __bss_size symbol in vpl/u-boot-vpl',
                       str(e.exception))
 
+    def testSymlink(self):
+        """Test that image files can be named"""
+        retcode = self._DoTestFile('259_symlink.dts', debug=True, map=True)
+        self.assertEqual(0, retcode)
+        image = control.images['test_image']
+        fname = tools.get_output_filename('test_image.bin')
+        sname = tools.get_output_filename('symlink_to_test.bin')
+        self.assertTrue(os.path.islink(sname))
+        self.assertEqual(os.readlink(sname), fname)
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index afc4b4d..6d4bff5 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -38,6 +38,7 @@
             repacked later
         test_section_timeout: Use a zero timeout for section multi-threading
             (for testing)
+        symlink: Name of symlink to image
 
     Args:
         copy_to_orig: Copy offset/size to orig_offset/orig_size after reading
@@ -97,6 +98,7 @@
         if filename:
             self._filename = filename
         self.allow_repack = fdt_util.GetBool(self._node, 'allow-repack')
+        self._symlink = fdt_util.GetString(self._node, 'symlink')
 
     @classmethod
     def FromFile(cls, fname):
@@ -180,6 +182,10 @@
             data = self.GetPaddedData()
             fd.write(data)
         tout.info("Wrote %#x bytes" % len(data))
+        # Create symlink to file if symlink given
+        if self._symlink is not None:
+            sname = tools.get_output_filename(self._symlink)
+            os.symlink(fname, sname)
 
     def WriteMap(self):
         """Write a map of the image to a .map file
diff --git a/tools/binman/test/259_symlink.dts b/tools/binman/test/259_symlink.dts
new file mode 100644
index 0000000..2ee1f7f
--- /dev/null
+++ b/tools/binman/test/259_symlink.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		multiple-images;
+		test_image {
+			filename = "test_image.bin";
+			symlink = "symlink_to_test.bin";
+			u-boot {
+			};
+		};
+	};
+};