Merge tag 'xilinx-for-v2023.01-rc1-v3' of https://source.denx.de/u-boot/custodians/u-boot-microblaze

Xilinx changes for v2023.01-rc1 (round 3)

fpga:
- Create new uclass
- Get rid of FPGA_DEBUG and use logging infrastructure

zynq:
- Enable early EEPROM decoding
- Some DT updates

zynqmp:
- Use OCM_BANK_0 to check config loading permission
- Change config object loading in SPL
- Some DT updates

net:
- emaclite: Enable driver for RISC-V

xilinx:
- Fix static checker warnings
- Fix GCC12 warning

sdhci:
- Read PD id from DT
diff --git a/MAINTAINERS b/MAINTAINERS
index a26b36c..3377866 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -940,6 +940,7 @@
 F:	drivers/fpga/
 F:	cmd/fpga.c
 F:	include/fpga.h
+F:	test/dm/fpga.c
 
 FLATTENED DEVICE TREE
 M:	Simon Glass <sjg@chromium.org>
diff --git a/arch/arm/dts/versal-mini-emmc0.dts b/arch/arm/dts/versal-mini-emmc0.dts
index 7c81a82..d098c2d 100644
--- a/arch/arm/dts/versal-mini-emmc0.dts
+++ b/arch/arm/dts/versal-mini-emmc0.dts
@@ -44,7 +44,6 @@
 			reg = <0x0 0xf1040000 0x0 0x10000>;
 			clock-names = "clk_xin", "clk_ahb";
 			clocks = <&clk200 &clk200>;
-			xlnx,device_id = <0>;
 			no-1-8-v;
 			xlnx,mio-bank = <0>;
 		};
diff --git a/arch/arm/dts/versal-mini-emmc1.dts b/arch/arm/dts/versal-mini-emmc1.dts
index bf7569d..9d4ac28 100644
--- a/arch/arm/dts/versal-mini-emmc1.dts
+++ b/arch/arm/dts/versal-mini-emmc1.dts
@@ -44,7 +44,6 @@
 			reg = <0x0 0xf1050000 0x0 0x10000>;
 			clock-names = "clk_xin", "clk_ahb";
 			clocks = <&clk200 &clk200>;
-			xlnx,device_id = <1>;
 			no-1-8-v;
 			xlnx,mio-bank = <0>;
 		};
diff --git a/arch/arm/dts/zynq-zc702.dts b/arch/arm/dts/zynq-zc702.dts
index 1bd4f8c..f04129f 100644
--- a/arch/arm/dts/zynq-zc702.dts
+++ b/arch/arm/dts/zynq-zc702.dts
@@ -17,6 +17,8 @@
 		spi0 = &qspi;
 		mmc0 = &sdhci0;
 		usb0 = &usb0;
+		nvmem0 = &eeprom;
+		rtc0 = &rtc;
 	};
 
 	memory@0 {
@@ -142,7 +144,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
-			eeprom@54 {
+			eeprom: eeprom@54 {
 				compatible = "atmel,24c08";
 				reg = <0x54>;
 			};
@@ -164,7 +166,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <4>;
-			rtc@51 {
+			rtc: rtc@51 {
 				compatible = "nxp,pcf8563";
 				reg = <0x51>;
 			};
diff --git a/arch/arm/dts/zynq-zc706.dts b/arch/arm/dts/zynq-zc706.dts
index cb919e4..dd3ae83 100644
--- a/arch/arm/dts/zynq-zc706.dts
+++ b/arch/arm/dts/zynq-zc706.dts
@@ -16,6 +16,8 @@
 		serial0 = &uart1;
 		spi0 = &qspi;
 		mmc0 = &sdhci0;
+		nvmem0 = &eeprom;
+		rtc0 = &rtc;
 	};
 
 	memory@0 {
@@ -101,7 +103,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
-			eeprom@54 {
+			eeprom: eeprom@54 {
 				compatible = "atmel,24c08";
 				reg = <0x54>;
 			};
@@ -123,7 +125,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <4>;
-			rtc@51 {
+			rtc: rtc@51 {
 				compatible = "nxp,pcf8563";
 				reg = <0x51>;
 			};
diff --git a/arch/arm/dts/zynqmp-mini-emmc0.dts b/arch/arm/dts/zynqmp-mini-emmc0.dts
index 8467dd8..1cc4ade 100644
--- a/arch/arm/dts/zynqmp-mini-emmc0.dts
+++ b/arch/arm/dts/zynqmp-mini-emmc0.dts
@@ -56,7 +56,6 @@
 			reg = <0x0 0xff160000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
 			clocks = <&clk_xin &clk_xin>;
-			xlnx,device_id = <0>;
 		};
 	};
 };
diff --git a/arch/arm/dts/zynqmp-mini-emmc1.dts b/arch/arm/dts/zynqmp-mini-emmc1.dts
index 2afcc77..96b5dc2 100644
--- a/arch/arm/dts/zynqmp-mini-emmc1.dts
+++ b/arch/arm/dts/zynqmp-mini-emmc1.dts
@@ -56,7 +56,6 @@
 			reg = <0x0 0xff170000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
 			clocks = <&clk_xin &clk_xin>;
-			xlnx,device_id = <1>;
 		};
 	};
 };
diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index f4184f7..b210bc4 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -720,7 +720,6 @@
 			interrupts = <0 48 4>;
 			reg = <0x0 0xff160000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
-			xlnx,device_id = <0>;
 			iommus = <&smmu 0x870>;
 			#clock-cells = <1>;
 			clock-output-names = "clk_out_sd0", "clk_in_sd0";
@@ -736,7 +735,6 @@
 			interrupts = <0 49 4>;
 			reg = <0x0 0xff170000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
-			xlnx,device_id = <1>;
 			iommus = <&smmu 0x871>;
 			#clock-cells = <1>;
 			clock-output-names = "clk_out_sd1", "clk_in_sd1";
diff --git a/arch/arm/mach-zynqmp/mp.c b/arch/arm/mach-zynqmp/mp.c
index 4f1ed44..949456d 100644
--- a/arch/arm/mach-zynqmp/mp.c
+++ b/arch/arm/mach-zynqmp/mp.c
@@ -163,7 +163,7 @@
 
 int cpu_disable(u32 nr)
 {
-	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+	if (nr <= ZYNQMP_CORE_APU3) {
 		u32 val = readl(&crfapb_base->rst_fpd_apu);
 		val |= 1 << nr;
 		writel(val, &crfapb_base->rst_fpd_apu);
@@ -176,7 +176,7 @@
 
 int cpu_status(u32 nr)
 {
-	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+	if (nr <= ZYNQMP_CORE_APU3) {
 		u32 addr_low = readl(((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
 		u32 addr_high = readl(((u8 *)&apu_base->rvbar_addr0_h) +
 				      nr * 8);
@@ -252,7 +252,7 @@
 
 int cpu_release(u32 nr, int argc, char *const argv[])
 {
-	if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+	if (nr <= ZYNQMP_CORE_APU3) {
 		u64 boot_addr = simple_strtoull(argv[0], NULL, 16);
 		/* HIGH */
 		writel((u32)(boot_addr >> 32),
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 4ee4712..a7b49f3 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -652,6 +652,10 @@
 		};
 	};
 
+	fpga {
+		compatible = "sandbox,fpga";
+	};
+
 	pinctrl-gpio {
 		compatible = "sandbox,pinctrl-gpio";
 
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 391ce4d..99fdbac 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -121,7 +121,7 @@
 static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size)
 {
 	int i;
-	char byte;
+	unsigned char byte;
 
 	for (i = 0; i < size; i++) {
 		byte = eeprom[i];
@@ -460,8 +460,8 @@
 							desc->serial);
 
 			if (desc->uuid[0]) {
-				char uuid[UUID_STR_LEN + 1];
-				char *t = desc->uuid;
+				unsigned char uuid[UUID_STR_LEN + 1];
+				unsigned char *t = desc->uuid;
 
 				memset(uuid, 0, UUID_STR_LEN + 1);
 
@@ -476,9 +476,6 @@
 				continue;
 
 			for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
-				if (!desc->mac_addr[i])
-					break;
-
 				if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
 					ret |= eth_env_set_enetaddr_by_index("eth",
 							macid++, desc->mac_addr[i]);
diff --git a/board/xilinx/common/cpu-info.c b/board/xilinx/common/cpu-info.c
index 4a863d0..4eccc7a 100644
--- a/board/xilinx/common/cpu-info.c
+++ b/board/xilinx/common/cpu-info.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <init.h>
 #include <soc.h>
 
 int print_cpuinfo(void)
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
index c96433b..17ee541 100644
--- a/board/xilinx/zynq/board.c
+++ b/board/xilinx/zynq/board.c
@@ -37,6 +37,9 @@
 	if (IS_ENABLED(CONFIG_SPL_BUILD))
 		printf("Silicon version:\t%d\n", zynq_get_silicon_version());
 
+	if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM))
+		xilinx_read_eeprom();
+
 	return 0;
 }
 
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 6253776..5fe0873 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -145,6 +145,14 @@
 	char name[SOC_MAX_STR_SIZE];
 	int ret;
 #endif
+
+#if defined(CONFIG_SPL_BUILD)
+	/* Check *at build time* if the filename is an non-empty string */
+	if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
+		zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
+						zynqmp_pm_cfg_obj_size);
+#endif
+
 #if defined(CONFIG_ZYNQMP_FIRMWARE)
 	struct udevice *dev;
 
@@ -154,10 +162,6 @@
 #endif
 
 #if defined(CONFIG_SPL_BUILD)
-	/* Check *at build time* if the filename is an non-empty string */
-	if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
-		zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
-						zynqmp_pm_cfg_obj_size);
 	printf("Silicon version:\t%d\n", zynqmp_get_silicon_version());
 
 	/* the CSU disables the JTAG interface when secure boot is enabled */
@@ -607,7 +611,7 @@
 
 void set_dfu_alt_info(char *interface, char *devstr)
 {
-	u8 multiboot;
+	int multiboot;
 	int bootseq = 0;
 
 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c
index b2f6206..76fde00 100644
--- a/drivers/clk/clk_versal.c
+++ b/drivers/clk/clk_versal.c
@@ -602,7 +602,7 @@
 	}
 }
 
-int versal_clock_setup(void)
+static int versal_clock_setup(void)
 {
 	int ret;
 
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index d8e0d79..dc8e3ad 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -82,7 +82,7 @@
 	ret = zynqmp_pmufw_load_config_object(xpm_configobject,
 					      sizeof(xpm_configobject));
 
-	if (ret && id == NODE_APU_0)
+	if (ret == XST_PM_NO_ACCESS && id == NODE_OCM_BANK_0)
 		skip_config = true;
 
 	return 0;
@@ -235,6 +235,8 @@
  *
  * @cfg_obj: Pointer to the configuration object
  * @size:    Size of @cfg_obj in bytes
+ * Return:   0 on success otherwise negative errno. If the config object
+ *           is not loadable returns positive errno XST_PM_NO_ACCESS(2002)
  */
 int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size)
 {
@@ -249,7 +251,10 @@
 	err = xilinx_pm_request(PM_SET_CONFIGURATION, (u32)(u64)cfg_obj, 0, 0,
 				0, ret_payload);
 	if (err == XST_PM_NO_ACCESS) {
-		printf("PMUFW no permission to change config object\n");
+		if (((u32 *)cfg_obj)[NODE_ID_LOCATION] == NODE_OCM_BANK_0) {
+			printf("PMUFW:  No permission to change config object\n");
+			return err;
+		}
 		return -EACCES;
 	}
 
@@ -294,7 +299,7 @@
 	       ret & ZYNQMP_PM_VERSION_MINOR_MASK);
 
 	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP))
-		zynqmp_pmufw_node(NODE_APU_0);
+		zynqmp_pmufw_node(NODE_OCM_BANK_0);
 
 	return 0;
 };
diff --git a/drivers/fpga/ACEX1K.c b/drivers/fpga/ACEX1K.c
index aca8049..a1ff470 100644
--- a/drivers/fpga/ACEX1K.c
+++ b/drivers/fpga/ACEX1K.c
@@ -7,18 +7,14 @@
  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  */
 
+#define LOG_CATEGORY UCLASS_FPGA
+
 #include <common.h>		/* core U-Boot definitions */
 #include <console.h>
+#include <log.h>
 #include <ACEX1K.h>		/* ACEX device family */
 #include <linux/delay.h>
 
-/* Define FPGA_DEBUG to get debug printf's */
-#ifdef	FPGA_DEBUG
-#define PRINTF(fmt,args...)	printf (fmt ,##args)
-#else
-#define PRINTF(fmt,args...)
-#endif
-
 /* Note: The assumption is that we cannot possibly run fast enough to
  * overrun the device (the Slave Parallel mode can free run at 50MHz).
  * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
@@ -44,7 +40,7 @@
 
 	switch (desc->iface) {
 	case passive_serial:
-		PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
+		log_debug("Launching Passive Serial Loader\n");
 		ret_val = ACEX1K_ps_load (desc, buf, bsize);
 		break;
 
@@ -64,7 +60,7 @@
 
 	switch (desc->iface) {
 	case passive_serial:
-		PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
+		log_debug("Launching Passive Serial Dump\n");
 		ret_val = ACEX1K_ps_dump (desc, buf, bsize);
 		break;
 
@@ -93,8 +89,7 @@
 	Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
 	int i;
 
-	PRINTF ("%s: start with interface functions @ 0x%p\n",
-			__FUNCTION__, fn);
+	log_debug("start with interface functions @ 0x%p\n", fn);
 
 	if (fn) {
 		size_t bytecount = 0;
@@ -102,16 +97,16 @@
 		int cookie = desc->cookie;	/* make a local copy */
 		unsigned long ts;		/* timestamp */
 
-		PRINTF ("%s: Function Table:\n"
-				"ptr:\t0x%p\n"
-				"struct: 0x%p\n"
-				"config:\t0x%p\n"
-				"status:\t0x%p\n"
-				"clk:\t0x%p\n"
-				"data:\t0x%p\n"
-				"done:\t0x%p\n\n",
-				__FUNCTION__, &fn, fn, fn->config, fn->status,
-				fn->clk, fn->data, fn->done);
+		log_debug("Function Table:\n"
+			  "ptr:\t0x%p\n"
+			  "struct: 0x%p\n"
+			  "config:\t0x%p\n"
+			  "status:\t0x%p\n"
+			  "clk:\t0x%p\n"
+			  "data:\t0x%p\n"
+			  "done:\t0x%p\n\n",
+			  &fn, fn, fn->config, fn->status,
+			  fn->clk, fn->data, fn->done);
 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 		printf ("Loading FPGA Device %d...", cookie);
 #endif
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index e07a9cf..813d6a8 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -27,6 +27,12 @@
 	help
 	  Say Y here to enable the Altera Stratix V FPGA specific driver.
 
+config FPGA_ACEX1K
+	bool "Enable Altera ACEX 1K driver"
+	depends on FPGA_ALTERA
+	help
+	  Say Y here to enable the Altera ACEX 1K FPGA specific driver.
+
 config FPGA_CYCLON2
 	bool "Enable Altera FPGA driver for Cyclone II"
 	depends on FPGA_ALTERA
@@ -71,6 +77,12 @@
 	  Versal. The bitstream will only be generated as PDI for Versal
 	  platform.
 
+config FPGA_SPARTAN2
+	bool "Enable Spartan2 FPGA driver"
+	depends on FPGA_XILINX
+	help
+	  Enable Spartan2 FPGA driver.
+
 config FPGA_SPARTAN3
 	bool "Enable Spartan3 FPGA driver"
 	depends on FPGA_XILINX
@@ -118,4 +130,23 @@
 	  Enables the fpga loads() functions that are used to load secure
 	  (authenticated or encrypted or both) bitstreams on to FPGA.
 
+config DM_FPGA
+	bool "Enable Driver Model for FPGA drivers"
+	depends on DM
+	select FPGA
+	help
+	  Enable driver model for Field-Programmable Gate Array (FPGA) devices.
+	  The devices cover a wide range of applications and are configured at
+	  runtime by loading a bitstream into the FPGA device.
+	  Loading a bitstream from any kind of storage is the main task of the
+	  FPGA drivers.
+	  For now this uclass has no methods yet.
+
+config SANDBOX_FPGA
+	bool "Enable sandbox FPGA driver"
+	depends on SANDBOX && DM_FPGA
+	help
+	  This is a driver model based FPGA driver for sandbox.
+	  Currently it is a stub only, as there are no usable uclass methods yet.
+
 endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 83243fb..610c168 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -4,6 +4,9 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
 obj-y += fpga.o
+obj-$(CONFIG_DM_FPGA) += fpga-uclass.o
+obj-$(CONFIG_SANDBOX_FPGA) += sandbox.o
+
 obj-$(CONFIG_FPGA_SPARTAN2) += spartan2.o
 obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
 obj-$(CONFIG_FPGA_VERSALPL) += versalpl.o
diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c
index 10c0475..6a4f0cb 100644
--- a/drivers/fpga/altera.c
+++ b/drivers/fpga/altera.c
@@ -7,6 +7,8 @@
  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  */
 
+#define LOG_CATEGORY UCLASS_FPGA
+
 /*
  *  Altera FPGA support
  */
@@ -16,9 +18,6 @@
 #include <log.h>
 #include <stratixII.h>
 
-/* Define FPGA_DEBUG to 1 to get debug printf's */
-#define FPGA_DEBUG	0
-
 static const struct altera_fpga {
 	enum altera_family	family;
 	const char		*name;
@@ -106,8 +105,7 @@
 	if (!fpga)
 		return FPGA_FAIL;
 
-	debug_cond(FPGA_DEBUG, "%s: Launching the %s Loader...\n",
-		   __func__, fpga->name);
+	log_debug("Launching the %s Loader...\n", fpga->name);
 	if (fpga->load)
 		return fpga->load(desc, buf, bsize);
 	return 0;
@@ -120,8 +118,7 @@
 	if (!fpga)
 		return FPGA_FAIL;
 
-	debug_cond(FPGA_DEBUG, "%s: Launching the %s Reader...\n",
-		   __func__, fpga->name);
+	log_debug("Launching the %s Reader...\n", fpga->name);
 	if (fpga->dump)
 		return fpga->dump(desc, buf, bsize);
 	return 0;
diff --git a/drivers/fpga/cyclon2.c b/drivers/fpga/cyclon2.c
index 3b008fa..f264ff8 100644
--- a/drivers/fpga/cyclon2.c
+++ b/drivers/fpga/cyclon2.c
@@ -5,18 +5,14 @@
  * Based on ACE1XK.c
  */
 
+#define LOG_CATEGORY UCLASS_FPGA
+
 #include <common.h>		/* core U-Boot definitions */
+#include <log.h>
 #include <altera.h>
 #include <ACEX1K.h>		/* ACEX device family */
 #include <linux/delay.h>
 
-/* Define FPGA_DEBUG to get debug printf's */
-#ifdef	FPGA_DEBUG
-#define PRINTF(fmt, args...)	printf(fmt, ##args)
-#else
-#define PRINTF(fmt, args...)
-#endif
-
 /* Note: The assumption is that we cannot possibly run fast enough to
  * overrun the device (the Slave Parallel mode can free run at 50MHz).
  * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
@@ -42,7 +38,7 @@
 
 	switch (desc->iface) {
 	case passive_serial:
-		PRINTF("%s: Launching Passive Serial Loader\n", __func__);
+		log_debug("Launching Passive Serial Loader\n");
 		ret_val = CYC2_ps_load(desc, buf, bsize);
 		break;
 
@@ -51,8 +47,7 @@
 		 * done in the write() callback. Use the existing PS load
 		 * function for FPP, too.
 		 */
-		PRINTF("%s: Launching Fast Passive Parallel Loader\n",
-		       __func__);
+		log_debug("Launching Fast Passive Parallel Loader\n");
 		ret_val = CYC2_ps_load(desc, buf, bsize);
 		break;
 
@@ -72,7 +67,7 @@
 
 	switch (desc->iface) {
 	case passive_serial:
-		PRINTF("%s: Launching Passive Serial Dump\n", __func__);
+		log_debug("Launching Passive Serial Dump\n");
 		ret_val = CYC2_ps_dump(desc, buf, bsize);
 		break;
 
@@ -99,22 +94,21 @@
 	Altera_CYC2_Passive_Serial_fns *fn = desc->iface_fns;
 	int	ret = 0;
 
-	PRINTF("%s: start with interface functions @ 0x%p\n",
-	       __func__, fn);
+	log_debug("start with interface functions @ 0x%p\n", fn);
 
 	if (fn) {
 		int cookie = desc->cookie;	/* make a local copy */
 		unsigned long ts;		/* timestamp */
 
-		PRINTF("%s: Function Table:\n"
-				"ptr:\t0x%p\n"
-				"struct: 0x%p\n"
-				"config:\t0x%p\n"
-				"status:\t0x%p\n"
-				"write:\t0x%p\n"
-				"done:\t0x%p\n\n",
-				__func__, &fn, fn, fn->config, fn->status,
-				fn->write, fn->done);
+		log_debug("Function Table:\n"
+			  "ptr:\t0x%p\n"
+			  "struct: 0x%p\n"
+			  "config:\t0x%p\n"
+			  "status:\t0x%p\n"
+			  "write:\t0x%p\n"
+			  "done:\t0x%p\n\n",
+			  &fn, fn, fn->config, fn->status,
+			  fn->write, fn->done);
 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 		printf("Loading FPGA Device %d...", cookie);
 #endif
diff --git a/drivers/fpga/fpga-uclass.c b/drivers/fpga/fpga-uclass.c
new file mode 100644
index 0000000..4278ec2
--- /dev/null
+++ b/drivers/fpga/fpga-uclass.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 Alexander Dahl <post@lespocky.de>
+ */
+
+#include <dm.h>
+
+UCLASS_DRIVER(fpga) = {
+	.name	= "fpga",
+	.id	= UCLASS_FPGA,
+};
diff --git a/drivers/fpga/sandbox.c b/drivers/fpga/sandbox.c
new file mode 100644
index 0000000..f17a822
--- /dev/null
+++ b/drivers/fpga/sandbox.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 Alexander Dahl <post@lespocky.de>
+ */
+
+#include <dm.h>
+
+static const struct udevice_id sandbox_fpga_match[] = {
+	{ .compatible = "sandbox,fpga" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_fpga) = {
+	.name	= "sandbox_fpga",
+	.id	= UCLASS_FPGA,
+	.of_match = sandbox_fpga_match,
+};
diff --git a/drivers/fpga/spartan2.c b/drivers/fpga/spartan2.c
index 47692e3..f72dfde 100644
--- a/drivers/fpga/spartan2.c
+++ b/drivers/fpga/spartan2.c
@@ -4,16 +4,12 @@
  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
  */
 
+#define LOG_CATEGORY UCLASS_FPGA
+
 #include <common.h>		/* core U-Boot definitions */
+#include <log.h>
 #include <spartan2.h>		/* Spartan-II device family */
 
-/* Define FPGA_DEBUG to get debug printf's */
-#ifdef	FPGA_DEBUG
-#define PRINTF(fmt,args...)	printf (fmt ,##args)
-#else
-#define PRINTF(fmt,args...)
-#endif
-
 #undef CONFIG_SYS_FPGA_CHECK_BUSY
 
 /* Note: The assumption is that we cannot possibly run fast enough to
@@ -46,12 +42,12 @@
 
 	switch (desc->iface) {
 	case slave_serial:
-		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+		log_debug("Launching Slave Serial Load\n");
 		ret_val = spartan2_ss_load(desc, buf, bsize);
 		break;
 
 	case slave_parallel:
-		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
+		log_debug("Launching Slave Parallel Load\n");
 		ret_val = spartan2_sp_load(desc, buf, bsize);
 		break;
 
@@ -69,12 +65,12 @@
 
 	switch (desc->iface) {
 	case slave_serial:
-		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+		log_debug("Launching Slave Serial Dump\n");
 		ret_val = spartan2_ss_dump(desc, buf, bsize);
 		break;
 
 	case slave_parallel:
-		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
+		log_debug("Launching Slave Parallel Dump\n");
 		ret_val = spartan2_sp_dump(desc, buf, bsize);
 		break;
 
@@ -100,8 +96,7 @@
 	int ret_val = FPGA_FAIL;	/* assume the worst */
 	xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
 
-	PRINTF ("%s: start with interface functions @ 0x%p\n",
-			__FUNCTION__, fn);
+	log_debug("start with interface functions @ 0x%p\n", fn);
 
 	if (fn) {
 		size_t bytecount = 0;
@@ -109,24 +104,24 @@
 		int cookie = desc->cookie;	/* make a local copy */
 		unsigned long ts;		/* timestamp */
 
-		PRINTF ("%s: Function Table:\n"
-				"ptr:\t0x%p\n"
-				"struct: 0x%p\n"
-				"pre: 0x%p\n"
-				"pgm:\t0x%p\n"
-				"init:\t0x%p\n"
-				"err:\t0x%p\n"
-				"clk:\t0x%p\n"
-				"cs:\t0x%p\n"
-				"wr:\t0x%p\n"
-				"read data:\t0x%p\n"
-				"write data:\t0x%p\n"
-				"busy:\t0x%p\n"
-				"abort:\t0x%p\n",
-				"post:\t0x%p\n\n",
-				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
-				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
-				fn->abort, fn->post);
+		log_debug("Function Table:\n"
+			  "ptr:\t0x%p\n"
+			  "struct: 0x%p\n"
+			  "pre: 0x%p\n"
+			  "pgm:\t0x%p\n"
+			  "init:\t0x%p\n"
+			  "err:\t0x%p\n"
+			  "clk:\t0x%p\n"
+			  "cs:\t0x%p\n"
+			  "wr:\t0x%p\n"
+			  "read data:\t0x%p\n"
+			  "write data:\t0x%p\n"
+			  "busy:\t0x%p\n"
+			  "abort:\t0x%p\n"
+			  "post:\t0x%p\n\n",
+			  &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
+			  fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
+			  fn->abort, fn->post);
 
 		/*
 		 * This code is designed to emulate the "Express Style"
@@ -302,8 +297,7 @@
 	int i;
 	unsigned char val;
 
-	PRINTF ("%s: start with interface functions @ 0x%p\n",
-			__FUNCTION__, fn);
+	log_debug("start with interface functions @ 0x%p\n", fn);
 
 	if (fn) {
 		size_t bytecount = 0;
@@ -311,16 +305,16 @@
 		int cookie = desc->cookie;	/* make a local copy */
 		unsigned long ts;		/* timestamp */
 
-		PRINTF ("%s: Function Table:\n"
-				"ptr:\t0x%p\n"
-				"struct: 0x%p\n"
-				"pgm:\t0x%p\n"
-				"init:\t0x%p\n"
-				"clk:\t0x%p\n"
-				"wr:\t0x%p\n"
-				"done:\t0x%p\n\n",
-				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
-				fn->clk, fn->wr, fn->done);
+		log_debug("Function Table:\n"
+			  "ptr:\t0x%p\n"
+			  "struct: 0x%p\n"
+			  "pgm:\t0x%p\n"
+			  "init:\t0x%p\n"
+			  "clk:\t0x%p\n"
+			  "wr:\t0x%p\n"
+			  "done:\t0x%p\n\n",
+			  &fn, fn, fn->pgm, fn->init,
+			  fn->clk, fn->wr, fn->done);
 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 		printf ("Loading FPGA Device %d...\n", cookie);
 #endif
diff --git a/drivers/fpga/spartan3.c b/drivers/fpga/spartan3.c
index 918f6db..b7a063a 100644
--- a/drivers/fpga/spartan3.c
+++ b/drivers/fpga/spartan3.c
@@ -9,16 +9,12 @@
  * on spartan2.c (Rich Ireland, rireland@enterasys.com).
  */
 
+#define LOG_CATEGORY UCLASS_FPGA
+
 #include <common.h>		/* core U-Boot definitions */
+#include <log.h>
 #include <spartan3.h>		/* Spartan-II device family */
 
-/* Define FPGA_DEBUG to get debug printf's */
-#ifdef	FPGA_DEBUG
-#define PRINTF(fmt,args...)	printf (fmt ,##args)
-#else
-#define PRINTF(fmt,args...)
-#endif
-
 #undef CONFIG_SYS_FPGA_CHECK_BUSY
 
 /* Note: The assumption is that we cannot possibly run fast enough to
@@ -51,12 +47,12 @@
 
 	switch (desc->iface) {
 	case slave_serial:
-		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+		log_debug("Launching Slave Serial Load\n");
 		ret_val = spartan3_ss_load(desc, buf, bsize);
 		break;
 
 	case slave_parallel:
-		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
+		log_debug("Launching Slave Parallel Load\n");
 		ret_val = spartan3_sp_load(desc, buf, bsize);
 		break;
 
@@ -74,12 +70,12 @@
 
 	switch (desc->iface) {
 	case slave_serial:
-		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+		log_debug("Launching Slave Serial Dump\n");
 		ret_val = spartan3_ss_dump(desc, buf, bsize);
 		break;
 
 	case slave_parallel:
-		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
+		log_debug("Launching Slave Parallel Dump\n");
 		ret_val = spartan3_sp_dump(desc, buf, bsize);
 		break;
 
@@ -105,8 +101,7 @@
 	int ret_val = FPGA_FAIL;	/* assume the worst */
 	xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
 
-	PRINTF ("%s: start with interface functions @ 0x%p\n",
-			__FUNCTION__, fn);
+	log_debug("start with interface functions @ 0x%p\n", fn);
 
 	if (fn) {
 		size_t bytecount = 0;
@@ -114,24 +109,24 @@
 		int cookie = desc->cookie;	/* make a local copy */
 		unsigned long ts;		/* timestamp */
 
-		PRINTF ("%s: Function Table:\n"
-				"ptr:\t0x%p\n"
-				"struct: 0x%p\n"
-				"pre: 0x%p\n"
-				"pgm:\t0x%p\n"
-				"init:\t0x%p\n"
-				"err:\t0x%p\n"
-				"clk:\t0x%p\n"
-				"cs:\t0x%p\n"
-				"wr:\t0x%p\n"
-				"read data:\t0x%p\n"
-				"write data:\t0x%p\n"
-				"busy:\t0x%p\n"
-				"abort:\t0x%p\n",
-				"post:\t0x%p\n\n",
-				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
-				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
-				fn->abort, fn->post);
+		log_debug("Function Table:\n"
+			  "ptr:\t0x%p\n"
+			  "struct: 0x%p\n"
+			  "pre: 0x%p\n"
+			  "pgm:\t0x%p\n"
+			  "init:\t0x%p\n"
+			  "err:\t0x%p\n"
+			  "clk:\t0x%p\n"
+			  "cs:\t0x%p\n"
+			  "wr:\t0x%p\n"
+			  "read data:\t0x%p\n"
+			  "write data:\t0x%p\n"
+			  "busy:\t0x%p\n"
+			  "abort:\t0x%p\n"
+			  "post:\t0x%p\n\n",
+			  &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
+			  fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
+			  fn->abort, fn->post);
 
 		/*
 		 * This code is designed to emulate the "Express Style"
@@ -309,8 +304,7 @@
 	int i;
 	unsigned char val;
 
-	PRINTF ("%s: start with interface functions @ 0x%p\n",
-			__FUNCTION__, fn);
+	log_debug("start with interface functions @ 0x%p\n", fn);
 
 	if (fn) {
 		size_t bytecount = 0;
@@ -318,16 +312,16 @@
 		int cookie = desc->cookie;	/* make a local copy */
 		unsigned long ts;		/* timestamp */
 
-		PRINTF ("%s: Function Table:\n"
-				"ptr:\t0x%p\n"
-				"struct: 0x%p\n"
-				"pgm:\t0x%p\n"
-				"init:\t0x%p\n"
-				"clk:\t0x%p\n"
-				"wr:\t0x%p\n"
-				"done:\t0x%p\n\n",
-				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
-				fn->clk, fn->wr, fn->done);
+		log_debug("Function Table:\n"
+			  "ptr:\t0x%p\n"
+			  "struct: 0x%p\n"
+			  "pgm:\t0x%p\n"
+			  "init:\t0x%p\n"
+			  "clk:\t0x%p\n"
+			  "wr:\t0x%p\n"
+			  "done:\t0x%p\n\n",
+			  &fn, fn, fn->pgm, fn->init,
+			  fn->clk, fn->wr, fn->done);
 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 		printf ("Loading FPGA Device %d...\n", cookie);
 #endif
diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c
index 51b8d31..0d536f0 100644
--- a/drivers/fpga/virtex2.c
+++ b/drivers/fpga/virtex2.c
@@ -12,21 +12,14 @@
  * on spartan2.c (Rich Ireland, rireland@enterasys.com).
  */
 
+#define LOG_CATEGORY UCLASS_FPGA
+
 #include <common.h>
 #include <console.h>
+#include <log.h>
 #include <virtex2.h>
 #include <linux/delay.h>
 
-#if 0
-#define FPGA_DEBUG
-#endif
-
-#ifdef	FPGA_DEBUG
-#define	PRINTF(fmt, args...)	printf(fmt, ##args)
-#else
-#define PRINTF(fmt, args...)
-#endif
-
 /*
  * If the SelectMap interface can be overrun by the processor, define
  * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board
@@ -89,12 +82,12 @@
 
 	switch (desc->iface) {
 	case slave_serial:
-		PRINTF("%s: Launching Slave Serial Load\n", __func__);
+		log_debug("Launching Slave Serial Load\n");
 		ret_val = virtex2_ss_load(desc, buf, bsize);
 		break;
 
 	case slave_selectmap:
-		PRINTF("%s: Launching Slave Parallel Load\n", __func__);
+		log_debug("Launching Slave Parallel Load\n");
 		ret_val = virtex2_ssm_load(desc, buf, bsize);
 		break;
 
@@ -111,12 +104,12 @@
 
 	switch (desc->iface) {
 	case slave_serial:
-		PRINTF("%s: Launching Slave Serial Dump\n", __func__);
+		log_debug("Launching Slave Serial Dump\n");
 		ret_val = virtex2_ss_dump(desc, buf, bsize);
 		break;
 
 	case slave_parallel:
-		PRINTF("%s: Launching Slave Parallel Dump\n", __func__);
+		log_debug("Launching Slave Parallel Dump\n");
 		ret_val = virtex2_ssm_dump(desc, buf, bsize);
 		break;
 
@@ -150,8 +143,7 @@
 {
 	unsigned long ts;
 
-	PRINTF("%s:%d: Start with interface functions @ 0x%p\n",
-	       __func__, __LINE__, fn);
+	log_debug("Start with interface functions @ 0x%p\n", fn);
 
 	if (!fn) {
 		printf("%s:%d: NULL Interface function table!\n",
@@ -160,25 +152,24 @@
 	}
 
 	/* Gotta split this one up (so the stack won't blow??) */
-	PRINTF("%s:%d: Function Table:\n"
-	       "  base   0x%p\n"
-	       "  struct 0x%p\n"
-	       "  pre    0x%p\n"
-	       "  prog   0x%p\n"
-	       "  init   0x%p\n"
-	       "  error  0x%p\n",
-	       __func__, __LINE__,
-	       &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
-	PRINTF("  clock  0x%p\n"
-	       "  cs     0x%p\n"
-	       "  write  0x%p\n"
-	       "  rdata  0x%p\n"
-	       "  wdata  0x%p\n"
-	       "  busy   0x%p\n"
-	       "  abort  0x%p\n"
-	       "  post   0x%p\n\n",
-	       fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
-	       fn->busy, fn->abort, fn->post);
+	log_debug("Function Table:\n"
+		  "  base   0x%p\n"
+		  "  struct 0x%p\n"
+		  "  pre    0x%p\n"
+		  "  prog   0x%p\n"
+		  "  init   0x%p\n"
+		  "  error  0x%p\n",
+		  &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
+	log_debug("  clock  0x%p\n"
+		  "  cs     0x%p\n"
+		  "  write  0x%p\n"
+		  "  rdata  0x%p\n"
+		  "  wdata  0x%p\n"
+		  "  busy   0x%p\n"
+		  "  abort  0x%p\n"
+		  "  post   0x%p\n\n",
+		  fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
+		  fn->busy, fn->abort, fn->post);
 
 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
 	printf("Initializing FPGA Device %d...\n", cookie);
@@ -330,8 +321,8 @@
 #endif
 
 		if ((*fn->done)(cookie) == FPGA_SUCCESS) {
-			PRINTF("%s:%d:done went active early, bytecount = %d\n",
-			       __func__, __LINE__, bytecount);
+			log_debug("done went active early, bytecount = %zu\n",
+				  bytecount);
 			break;
 		}
 
@@ -465,8 +456,8 @@
 #endif
 
 			if ((*fn->done)(cookie) == FPGA_SUCCESS) {
-				PRINTF("%s:%d:done went active early, bytecount = %d\n",
-				       __func__, __LINE__, bytecount);
+				log_debug("done went active early, bytecount = %zu\n",
+					  bytecount);
 				break;
 			}
 
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 8f4071c..7dcf6ad 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -61,7 +61,7 @@
 struct arasan_sdhci_priv {
 	struct sdhci_host *host;
 	struct arasan_sdhci_clk_data clk_data;
-	u8 deviceid;
+	u32 node_id;
 	u8 bank;
 	u8 no_1p8;
 	struct reset_ctl_bulk resets;
@@ -111,7 +111,7 @@
 	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
-static inline int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay)
+static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay)
 {
 	int ret;
 
@@ -155,7 +155,7 @@
 		if (ret)
 			return ret;
 	} else {
-		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+		return xilinx_pm_request(PM_IOCTL, node_id,
 					 IOCTL_SET_SD_TAPDELAY,
 					 PM_TAPDELAY_INPUT, itap_delay, NULL);
 	}
@@ -163,7 +163,7 @@
 	return 0;
 }
 
-static inline int arasan_zynqmp_set_out_tapdelay(u8 node_id, u32 otap_delay)
+static inline int arasan_zynqmp_set_out_tapdelay(u32 node_id, u32 otap_delay)
 {
 	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
 		if (node_id == NODE_SD_0)
@@ -174,13 +174,13 @@
 		return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
 					 (otap_delay << 16));
 	} else {
-		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+		return xilinx_pm_request(PM_IOCTL, node_id,
 					 IOCTL_SET_SD_TAPDELAY,
 					 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
 	}
 }
 
-static inline int zynqmp_dll_reset(u8 node_id, u32 type)
+static inline int zynqmp_dll_reset(u32 node_id, u32 type)
 {
 	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
 		if (node_id == NODE_SD_0)
@@ -192,12 +192,12 @@
 					 type == PM_DLL_RESET_ASSERT ?
 					 SD1_DLL_RST : 0);
 	} else {
-		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+		return xilinx_pm_request(PM_IOCTL, node_id,
 					 IOCTL_SD_DLL_RESET, type, 0, NULL);
 	}
 }
 
-static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 node_id)
+static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 node_id)
 {
 	struct mmc *mmc = (struct mmc *)host->mmc;
 	struct udevice *dev = mmc->dev;
@@ -250,7 +250,6 @@
 	struct sdhci_host *host;
 	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
 	char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
-	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 
 	dev_dbg(mmc->dev, "%s\n", __func__);
 
@@ -262,7 +261,7 @@
 
 	mdelay(1);
 
-	arasan_zynqmp_dll_reset(host, node_id);
+	arasan_zynqmp_dll_reset(host, priv->node_id);
 
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
@@ -308,7 +307,7 @@
 	}
 
 	udelay(1);
-	arasan_zynqmp_dll_reset(host, node_id);
+	arasan_zynqmp_dll_reset(host, priv->node_id);
 
 	/* Enable only interrupts served by the SD controller */
 	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
@@ -334,7 +333,6 @@
 	struct mmc *mmc = (struct mmc *)host->mmc;
 	struct udevice *dev = mmc->dev;
 	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
-	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	u8 tap_delay, tap_max = 0;
 	int timing = mode2timing[mmc->selected_mode];
 	int ret;
@@ -374,14 +372,14 @@
 	tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
 
 	/* Set the Clock Phase */
-	ret = arasan_zynqmp_set_out_tapdelay(node_id, tap_delay);
+	ret = arasan_zynqmp_set_out_tapdelay(priv->node_id, tap_delay);
 	if (ret) {
 		dev_err(dev, "Error setting output Tap Delay\n");
 		return ret;
 	}
 
 	/* Release DLL Reset */
-	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
+	ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_RELEASE);
 	if (ret) {
 		dev_err(dev, "dll_reset release failed with err: %d\n", ret);
 		return ret;
@@ -405,7 +403,6 @@
 	struct mmc *mmc = (struct mmc *)host->mmc;
 	struct udevice *dev = mmc->dev;
 	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
-	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	u8 tap_delay, tap_max = 0;
 	int timing = mode2timing[mmc->selected_mode];
 	int ret;
@@ -419,7 +416,7 @@
 		return 0;
 
 	/* Assert DLL Reset */
-	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
+	ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_ASSERT);
 	if (ret) {
 		dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
 		return ret;
@@ -451,7 +448,7 @@
 	/* Limit input tap_delay value to 8 bits */
 	tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
 
-	ret = arasan_zynqmp_set_in_tapdelay(node_id, tap_delay);
+	ret = arasan_zynqmp_set_in_tapdelay(priv->node_id, tap_delay);
 	if (ret) {
 		dev_err(dev, "Error setting Input Tap Delay\n");
 		return ret;
@@ -717,14 +714,14 @@
 					   struct udevice *dev)
 {
 	int ret;
-	u32 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	struct clk clk;
 	unsigned long clock, mhz;
 
-	ret = xilinx_pm_request(PM_REQUEST_NODE, node_id, ZYNQMP_PM_CAPABILITY_ACCESS,
-				ZYNQMP_PM_MAX_QOS, ZYNQMP_PM_REQUEST_ACK_NO, NULL);
+	ret = xilinx_pm_request(PM_REQUEST_NODE, priv->node_id,
+				ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS,
+				ZYNQMP_PM_REQUEST_ACK_NO, NULL);
 	if (ret) {
-		dev_err(dev, "Request node failed for %d\n", node_id);
+		dev_err(dev, "Request node failed for %d\n", priv->node_id);
 		return ret;
 	}
 
@@ -743,13 +740,13 @@
 		return ret;
 	}
 
-	ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_FIXED, 0);
+	ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_FIXED, 0);
 	if (ret) {
 		dev_err(dev, "SD_CONFIG_FIXED failed\n");
 		return ret;
 	}
 
-	ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_EMMC_SEL,
+	ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_EMMC_SEL,
 				      dev_read_bool(dev, "non-removable"));
 	if (ret) {
 		dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
@@ -779,13 +776,13 @@
 	else
 		mhz = 25;
 
-	ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_BASECLK, mhz);
+	ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_BASECLK, mhz);
 	if (ret) {
 		dev_err(dev, "SD_CONFIG_BASECLK failed\n");
 		return ret;
 	}
 
-	ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_8BIT,
+	ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_8BIT,
 				      (dev_read_u32_default(dev, "bus-width", 1) == 8));
 	if (ret) {
 		dev_err(dev, "SD_CONFIG_8BIT failed\n");
@@ -900,6 +897,7 @@
 static int arasan_sdhci_of_to_plat(struct udevice *dev)
 {
 	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	u32 pm_info[2];
 
 	priv->host = calloc(1, sizeof(struct sdhci_host));
 	if (!priv->host)
@@ -916,10 +914,13 @@
 	if (IS_ERR(priv->host->ioaddr))
 		return PTR_ERR(priv->host->ioaddr);
 
-	priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1);
 	priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
 	priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
 
+	priv->node_id = 0;
+	if (!dev_read_u32_array(dev, "power-domains", pm_info, ARRAY_SIZE(pm_info)))
+		priv->node_id = pm_info[1];
+
 	return 0;
 }
 
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index d48e342..5f5bc65 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -11,6 +11,7 @@
 #include <cpu_func.h>
 #include <display_options.h>
 #include <dm.h>
+#include <dm/device_compat.h>
 #include <log.h>
 #include <net.h>
 #include <malloc.h>
@@ -317,6 +318,10 @@
 
 	/* Interface - look at tsec */
 	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
+	if (IS_ERR_OR_NULL(phydev)) {
+		dev_err(dev, "phy_connect() failed\n");
+		return -ENODEV;
+	}
 
 	phydev->supported &= supported;
 	phydev->advertising = phydev->supported;
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 6c9f1f7..16ba915 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -14,14 +14,13 @@
 #include <console.h>
 #include <malloc.h>
 #include <asm/global_data.h>
-#include <asm/io.h>
 #include <phy.h>
 #include <miiphy.h>
 #include <fdtdec.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
-#include <asm/io.h>
 #include <eth_phy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -113,12 +112,12 @@
 	/* Word aligned buffer, no correction needed. */
 	to32ptr = (u32 *) destptr;
 	while (bytecount > 3) {
-		*to32ptr++ = *from32ptr++;
+		*to32ptr++ = __raw_readl(from32ptr++);
 		bytecount -= 4;
 	}
 	to8ptr = (u8 *) to32ptr;
 
-	alignbuffer = *from32ptr++;
+	alignbuffer = __raw_readl(from32ptr++);
 	from8ptr = (u8 *) &alignbuffer;
 
 	for (i = 0; i < bytecount; i++)
@@ -136,8 +135,7 @@
 
 	from32ptr = (u32 *) srcptr;
 	while (bytecount > 3) {
-
-		*to32ptr++ = *from32ptr++;
+		__raw_writel(*from32ptr++, to32ptr++);
 		bytecount -= 4;
 	}
 
@@ -148,7 +146,7 @@
 	for (i = 0; i < bytecount; i++)
 		*to8ptr++ = *from8ptr++;
 
-	*to32ptr++ = alignbuffer;
+	__raw_writel(alignbuffer, to32ptr++);
 }
 
 static int wait_for_bit(const char *func, u32 *reg, const u32 mask,
@@ -519,6 +517,8 @@
 		length = ntohs(ip->ip_len);
 		length += ETHER_HDR_SIZE + ETH_FCS_LEN;
 		debug("IP Packet %x\n", length);
+		if (length > PKTSIZE)
+			length = PKTSIZE;
 		break;
 	default:
 		debug("Other Packet\n");
@@ -527,7 +527,7 @@
 	}
 
 	/* Read the rest of the packet which is longer then first read */
-	if (length != first_read)
+	if (length > first_read)
 		xemaclite_alignedread(addr + first_read,
 				      etherrxbuff + first_read,
 				      length - first_read);
@@ -615,8 +615,8 @@
 	int offset = 0;
 
 	pdata->iobase = dev_read_addr(dev);
-	emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
-								 0x10000);
+	emaclite->regs = (struct emaclite_regs *)ioremap(pdata->iobase,
+							 0x10000);
 
 	emaclite->phyaddr = -1;
 
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 61a6c83..3f4357e 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -328,7 +328,7 @@
 
 	priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev,
 				   priv->interface);
-	if (!priv->phydev)
+	if (IS_ERR_OR_NULL(priv->phydev))
 		return -ENODEV;
 
 	if (priv->max_speed) {
diff --git a/drivers/soc/soc_xilinx_zynqmp.c b/drivers/soc/soc_xilinx_zynqmp.c
index c10fc7d..a51bcdb 100644
--- a/drivers/soc/soc_xilinx_zynqmp.c
+++ b/drivers/soc/soc_xilinx_zynqmp.c
@@ -285,7 +285,7 @@
 	return snprintf(buf, size, "%s", priv->family);
 }
 
-int soc_xilinx_zynqmp_get_machine(struct udevice *dev, char *buf, int size)
+static int soc_xilinx_zynqmp_get_machine(struct udevice *dev, char *buf, int size)
 {
 	struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
 	const char *machine = priv->machine;
diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index d3cc855..49facc4 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -294,7 +294,7 @@
 	zynqmp_qspi_fill_gen_fifo(priv, gqspi_fifo_reg);
 }
 
-void zynqmp_qspi_set_tapdelay(struct udevice *bus, u32 baudrateval)
+static void zynqmp_qspi_set_tapdelay(struct udevice *bus, u32 baudrateval)
 {
 	struct zynqmp_qspi_plat *plat = dev_get_plat(bus);
 	struct zynqmp_qspi_priv *priv = dev_get_priv(bus);
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43..c2b1588 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -56,6 +56,7 @@
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_FIRMWARE,	/* Firmware */
+	UCLASS_FPGA,		/* FPGA device */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 5178daa..499e769 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -47,6 +47,7 @@
 obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o
 endif
 obj-$(CONFIG_FIRMWARE) += firmware.o
+obj-$(CONFIG_DM_FPGA) += fpga.o
 obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_SOUND) += i2s.o
diff --git a/test/dm/fpga.c b/test/dm/fpga.c
new file mode 100644
index 0000000..8bb3535
--- /dev/null
+++ b/test/dm/fpga.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 Alexander Dahl <post@lespocky.de>
+ */
+
+#include <dm.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static int dm_test_fpga(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_FPGA, &dev));
+
+	return 0;
+}
+
+DM_TEST(dm_test_fpga, UT_TESTF_SCAN_FDT);