diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index 1b5ccec4b2..af28b43c7b 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -825,6 +825,10 @@ drivers marked with DM_FLAG_PRE_RELOC or the device tree
 'u-boot,dm-pre-reloc' flag are initialised prior to relocation. This helps
 to reduce the driver model overhead.
 
+It is possible to limit this to specific relocation steps, by using
+the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags
+in the devicetree.
+
 Then post relocation we throw that away and re-init driver model again.
 For drivers which require some sort of continuity between pre- and
 post-relocation devices, we can provide access to the pre-relocation
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 76ba91af81..c098efc9f7 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -10,6 +10,7 @@
 #include <dm/device.h>
 #include <dm/lists.h>
 #include <dm/root.h>
+#include <dm/util.h>
 #include "pmc.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -56,7 +57,7 @@ int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
 	     offset > 0;
 	     offset = fdt_next_subnode(fdt, offset)) {
 		if (pre_reloc_only &&
-		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
+		    !dm_fdt_pre_reloc(fdt, offset))
 			continue;
 		/*
 		 * If this node has "compatible" property, this is not
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 9edfc1efb6..45f990ba9e 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -205,7 +205,7 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
 	     offset > 0;
 	     offset = fdt_next_subnode(blob, offset)) {
 		if (pre_reloc_only &&
-		    !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
+		    !dm_fdt_pre_reloc(blob, offset))
 			continue;
 		if (!fdtdec_get_is_enabled(blob, offset)) {
 			dm_dbg("   - ignoring disabled device\n");
diff --git a/drivers/core/util.c b/drivers/core/util.c
index e01dd06d28..a67434b80d 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <libfdt.h>
 #include <vsprintf.h>
 
 void dm_warn(const char *fmt, ...)
@@ -35,3 +36,31 @@ int list_count_items(struct list_head *head)
 
 	return count;
 }
+
+int dm_fdt_pre_reloc(const void *blob, int offset)
+{
+	bool dm_spl, dm_tpl;
+
+	if (fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
+		return 1;
+
+	dm_spl = fdt_getprop(blob, offset, "u-boot,dm-spl", NULL);
+	dm_tpl = fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL);
+
+#ifdef CONFIG_TPL_BUILD
+	if (dm_tpl)
+		return 1;
+#elif defined(CONFIG_SPL_BUILD)
+	if (dm_spl)
+		return 1;
+#else
+	/*
+	 * In regular builds individual spl and tpl handling both
+	 * count as handled pre-relocation for later second init.
+	 */
+	if (dm_spl || dm_tpl)
+		return 1;
+#endif
+
+	return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 02ab9b4afd..9e0122906c 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -12,6 +12,7 @@
 #include <dm/lists.h>
 #include <dm/pinctrl.h>
 #include <dm/uclass.h>
+#include <dm/util.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -131,7 +132,7 @@ static int pinconfig_post_bind(struct udevice *dev)
 	     offset > 0;
 	     offset = fdt_next_subnode(fdt, offset)) {
 		if (pre_reloc_only &&
-		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
+		    !dm_fdt_pre_reloc(fdt, offset))
 			continue;
 		/*
 		 * If this node has "compatible" property, this is not
diff --git a/include/dm/util.h b/include/dm/util.h
index 15daa3d19f..38c023ce66 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -48,4 +48,6 @@ static inline void dm_dump_devres(void)
 }
 #endif
 
+int dm_fdt_pre_reloc(const void *blob, int offset);
+
 #endif
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index c962bbca2c..60bd844e48 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -206,8 +206,13 @@ $(obj)/$(SPL_BIN)-pad.bin: $(obj)/$(SPL_BIN)
 # 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
 # pass removes various unused properties from the remaining nodes.
 # The output is typically a much smaller device tree file.
+ifeq ($(CONFIG_TPL_BUILD),y)
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-tpl
+else
+fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-spl
+endif
 quiet_cmd_fdtgrep = FDTGREP $@
-      cmd_fdtgrep = $(objtree)/tools/fdtgrep -b u-boot,dm-pre-reloc -RT $< \
+      cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
 		-n /chosen -O dtb | \
 	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
 		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py
index 11050b66f7..232f8ff739 100755
--- a/tools/dtoc/dtoc.py
+++ b/tools/dtoc/dtoc.py
@@ -30,6 +30,8 @@ PROP_IGNORE_LIST = [
     "status",
     'phandle',
     'u-boot,dm-pre-reloc',
+    'u-boot,dm-tpl',
+    'u-boot,dm-spl',
 ]
 
 # C type declarations for the tyues we support
