Merge tag 'pull-30nov18' of git://git.denx.de/u-boot-dm

Fix sound on sandbox
Convert TPM fully to DM
Tidy up sandbox I2C emulation
Add a 'make qcheck' target for faster testing
A few other misc things
(dropped the final patch which breaks clang for some reason)
diff --git a/Makefile b/Makefile
index a4b1d1d..2c607d5 100644
--- a/Makefile
+++ b/Makefile
@@ -443,7 +443,7 @@
 
 no-dot-config-targets := clean clobber mrproper distclean \
 			 help %docs check% coccicheck \
-			 ubootversion backup tests
+			 ubootversion backup tests check qcheck
 
 config-targets := 0
 mixed-targets  := 0
@@ -1727,6 +1727,7 @@
 	@echo  'Test targets:'
 	@echo  ''
 	@echo  '  check           - Run all automated tests that use sandbox'
+	@echo  '  qcheck          - Run quick automated tests that use sandbox'
 	@echo  ''
 	@echo  'Other generic targets:'
 	@echo  '  all		  - Build all necessary images depending on configuration'
@@ -1769,6 +1770,9 @@
 tests check:
 	$(srctree)/test/run
 
+qcheck:
+	$(srctree)/test/run quick
+
 # Documentation targets
 # ---------------------------------------------------------------------------
 DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index aa92694..62e05c5 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -735,9 +735,10 @@
 	}
 
 	/* Look for 'u-boot' in the parent directory of spl/ */
-	p = strstr(fname, "/spl/");
+	p = strstr(fname, "spl/");
 	if (p) {
-		strcpy(p, p + 4);
+		/* Remove the "spl" characters */
+		memmove(p, p + 4, strlen(p + 4) + 1);
 		fd = os_open(fname, O_RDONLY);
 		if (fd >= 0) {
 			close(fd);
diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index adcb738..c7a8d94 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -9,6 +9,10 @@
 #include <sound.h>
 #include <asm/state.h>
 
+enum {
+	SAMPLE_RATE	= 22050,
+};
+
 static struct sdl_info {
 	SDL_Surface *screen;
 	int width;
@@ -18,6 +22,7 @@
 	uint frequency;
 	uint audio_pos;
 	uint audio_size;
+	uint sample_rate;
 	uint8_t *audio_data;
 	bool audio_active;
 	bool inited;
@@ -263,27 +268,8 @@
 	if (sdl.audio_active)
 		return 0;
 
-	/*
-	 * At present all sandbox sounds crash. This is probably due to
-	 * symbol name conflicts with U-Boot. We can remove the malloc()
-	 * probles with:
-	 *
-	 * #define USE_DL_PREFIX
-	 *
-	 * and get this:
-	 *
-	 * Assertion 'e->pollfd->fd == e->fd' failed at pulse/mainloop.c:676,
-	 *		function dispatch_pollfds(). Aborting.
-	 *
-	 * The right solution is probably to make U-Boot's names private or
-	 * link os.c and sdl.c against their libraries before liking with
-	 * U-Boot. TBD. For now sound is disabled.
-	 */
-	printf("(Warning: sandbox sound disabled)\n");
-	return 0;
-
 	/* Set the audio format */
-	wanted.freq = 22050;
+	wanted.freq = SAMPLE_RATE;
 	wanted.format = AUDIO_S16;
 	wanted.channels = 1;    /* 1 = mono, 2 = stereo */
 	wanted.samples = 1024;  /* Good low-latency value for callback */
@@ -309,6 +295,7 @@
 		goto err;
 	}
 	sdl.audio_active = true;
+	sdl.sample_rate = wanted.freq;
 
 	return 0;
 
@@ -322,7 +309,8 @@
 	if (!sdl.audio_active)
 		return -1;
 	sdl.frequency = frequency;
-	sound_create_square_wave((unsigned short *)sdl.audio_data,
+	sound_create_square_wave(sdl.sample_rate,
+				 (unsigned short *)sdl.audio_data,
 				 sdl.audio_size, frequency);
 	sdl.audio_pos = 0;
 	SDL_PauseAudio(0);
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 1cda911..ce3c88c 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -95,19 +95,11 @@
 		eeprom@2c {
 			reg = <0x2c>;
 			compatible = "i2c-eeprom";
-			emul {
-				compatible = "sandbox,i2c-eeprom";
-				sandbox,filename = "i2c.bin";
-				sandbox,size = <128>;
-			};
 		};
 
 		rtc_0: rtc@43 {
 			reg = <0x43>;
 			compatible = "sandbox-rtc";
-			emul {
-				compatible = "sandbox,i2c-rtc";
-			};
 		};
 		sandbox_pmic: sandbox_pmic {
 			reg = <0x40>;
@@ -116,6 +108,23 @@
 		mc34708: pmic@41 {
 			reg = <0x41>;
 		};
+
+		i2c_emul: emul {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xff>;
+			compatible = "sandbox,i2c-emul-parent";
+			emul-eeprom {
+				reg = <0x2c>;
+				compatible = "sandbox,i2c-eeprom";
+				sandbox,filename = "i2c.bin";
+				sandbox,size = <256>;
+			};
+			emul0 {
+				reg = <0x43>;
+				compatible = "sandbox,i2c-rtc";
+			};
+		};
 	};
 
 	lcd {
diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts
index 2c6d351..d30fd62 100644
--- a/arch/sandbox/dts/sandbox64.dts
+++ b/arch/sandbox/dts/sandbox64.dts
@@ -90,19 +90,11 @@
 		eeprom@2c {
 			reg = <0x2c>;
 			compatible = "i2c-eeprom";
-			emul {
-				compatible = "sandbox,i2c-eeprom";
-				sandbox,filename = "i2c.bin";
-				sandbox,size = <128>;
-			};
 		};
 
 		rtc_0: rtc@43 {
 			reg = <0x43>;
 			compatible = "sandbox-rtc";
-			emul {
-				compatible = "sandbox,i2c-rtc";
-			};
 		};
 		sandbox_pmic: sandbox_pmic {
 			reg = <0x40>;
@@ -111,6 +103,19 @@
 		mc34708: pmic@41 {
 			reg = <0x41>;
 		};
+
+		i2c_emul: emul {
+			reg = <0xff>;
+			compatible = "sandbox,i2c-emul-parent";
+			emul-eeprom {
+				compatible = "sandbox,i2c-eeprom";
+				sandbox,filename = "i2c.bin";
+				sandbox,size = <256>;
+			};
+			emul0 {
+				compatible = "sandbox,i2c-rtc";
+			};
+		};
 	};
 
 	lcd {
diff --git a/arch/sandbox/dts/sandbox_pmic.dtsi b/arch/sandbox/dts/sandbox_pmic.dtsi
index 5ecafaa..565c382 100644
--- a/arch/sandbox/dts/sandbox_pmic.dtsi
+++ b/arch/sandbox/dts/sandbox_pmic.dtsi
@@ -11,40 +11,6 @@
 &sandbox_pmic {
 	compatible = "sandbox,pmic";
 
-	pmic_emul {
-		compatible = "sandbox,i2c-pmic";
-
-		/*
-		 * Default PMICs register values are set by macro
-		 * VAL2REG(min, step, value) [uV/uA]
-		 * VAL2OMREG(mode id)
-		 * reg-defaults - byte array
-		 */
-		reg-defaults = /bits/ 8 <
-			/* BUCK1 */
-			VAL2REG(800000, 25000, 1000000)
-			VAL2REG(150000, 25000, 150000)
-			VAL2OMREG(BUCK_OM_OFF)
-			/* BUCK2 */
-			VAL2REG(750000, 50000, 3000000)
-			VAL2REG(150000, 25000, 150000)
-			VAL2OMREG(0)
-			/* LDO1 */
-			VAL2REG(800000, 25000, 1600000)
-			VAL2REG(100000, 50000, 150000)
-			VAL2OMREG(LDO_OM_OFF)
-			/* LDO2 */
-			VAL2REG(750000, 50000, 3000000)
-			VAL2REG(150000, 25000, 150000)
-			VAL2OMREG(0)
-			/* reg[12:15] - not used */
-			0x00
-			0x00
-			0x00
-			0x00
-		>;
-	};
-
 	buck1 {
 		regulator-name = "SUPPLY_1.2V";
 		regulator-min-microvolt = <1200000>;
@@ -84,10 +50,45 @@
 
 &mc34708 {
 	compatible = "fsl,mc34708";
+};
 
-	pmic_emul {
+&i2c_emul {
+	emul_pmic0: pmic-emul0 {
 		compatible = "sandbox,i2c-pmic";
 
+		/*
+		 * Default PMICs register values are set by macro
+		 * VAL2REG(min, step, value) [uV/uA]
+		 * VAL2OMREG(mode id)
+		 * reg-defaults - byte array
+		 */
+		reg-defaults = /bits/ 8 <
+			/* BUCK1 */
+			VAL2REG(800000, 25000, 1000000)
+			VAL2REG(150000, 25000, 150000)
+			VAL2OMREG(BUCK_OM_OFF)
+			/* BUCK2 */
+			VAL2REG(750000, 50000, 3000000)
+			VAL2REG(150000, 25000, 150000)
+			VAL2OMREG(0)
+			/* LDO1 */
+			VAL2REG(800000, 25000, 1600000)
+			VAL2REG(100000, 50000, 150000)
+			VAL2OMREG(LDO_OM_OFF)
+			/* LDO2 */
+			VAL2REG(750000, 50000, 3000000)
+			VAL2REG(150000, 25000, 150000)
+			VAL2OMREG(0)
+			/* reg[12:15] - not used */
+			0x00
+			0x00
+			0x00
+			0x00
+		>;
+	};
+
+	emul_pmic1: pmic-emul1 {
+		compatible = "sandbox,i2c-pmic";
 		reg-defaults = /bits/ 8 <
 			0x00 0x80 0x08 0xff 0xff 0xff 0x2e 0x01 0x08
 			0x40 0x80 0x81 0x5f 0xff 0xfb 0x1e 0x80 0x18
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2c6b422..252aa7b 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -266,35 +266,45 @@
 		eeprom@2c {
 			reg = <0x2c>;
 			compatible = "i2c-eeprom";
-			emul {
-				compatible = "sandbox,i2c-eeprom";
-				sandbox,filename = "i2c.bin";
-				sandbox,size = <256>;
-			};
+			sandbox,emul = <&emul_eeprom>;
 		};
 
 		rtc_0: rtc@43 {
 			reg = <0x43>;
 			compatible = "sandbox-rtc";
-			emul {
-				compatible = "sandbox,i2c-rtc";
-			};
+			sandbox,emul = <&emul0>;
 		};
 
 		rtc_1: rtc@61 {
 			reg = <0x61>;
 			compatible = "sandbox-rtc";
-			emul {
+			sandbox,emul = <&emul1>;
+		};
+
+		i2c_emul: emul {
+			reg = <0xff>;
+			compatible = "sandbox,i2c-emul-parent";
+			emul_eeprom: emul-eeprom {
+				compatible = "sandbox,i2c-eeprom";
+				sandbox,filename = "i2c.bin";
+				sandbox,size = <256>;
+			};
+			emul0: emul0 {
+				compatible = "sandbox,i2c-rtc";
+			};
+			emul1: emull {
 				compatible = "sandbox,i2c-rtc";
 			};
 		};
 
 		sandbox_pmic: sandbox_pmic {
 			reg = <0x40>;
+			sandbox,emul = <&emul_pmic0>;
 		};
 
 		mc34708: pmic@41 {
 			reg = <0x41>;
+			sandbox,emul = <&emul_pmic1>;
 		};
 	};
 
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index 824a08f..dd4c083 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -34,6 +34,19 @@
 #define DB_GP_88F68XX_GPP_POL_LOW	0x0
 #define DB_GP_88F68XX_GPP_POL_MID	0x0
 
+static int get_tpm(struct udevice **devp)
+{
+	int rc;
+
+	rc = uclass_first_device_err(UCLASS_TPM, devp);
+	if (rc) {
+		printf("Could not find TPM (ret=%d)\n", rc);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
 /*
  * Define the DDR layout / topology here in the board file. This will
  * be used by the DDR3 init code in the SPL U-Boot version to configure
@@ -266,18 +279,22 @@
 
 int last_stage_init(void)
 {
+	struct udevice *tpm;
+	int ret;
+
 #ifndef CONFIG_SPL_BUILD
 	ccdc_eth_init();
 #endif
-	if (tpm_init() || tpm_startup(TPM_ST_CLEAR) ||
-	    tpm_continue_self_test()) {
+	ret = get_tpm(&tpm);
+	if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) ||
+	    tpm_continue_self_test(tpm)) {
 		return 1;
 	}
 
 	mdelay(37);
 
-	flush_keys();
-	load_and_run_keyprog();
+	flush_keys(tpm);
+	load_and_run_keyprog(tpm);
 
 	return 0;
 }
diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c
index 34c4df7..82b8428 100644
--- a/board/gdsys/a38x/hre.c
+++ b/board/gdsys/a38x/hre.c
@@ -93,19 +93,20 @@
 
 /**
  * @brief get the size of a given (TPM) NV area
+ * @param tpm		TPM device
  * @param index	NV index of the area to get size for
  * @param size	pointer to the size
  * @return 0 on success, != 0 on error
  */
-static int get_tpm_nv_size(uint32_t index, uint32_t *size)
+static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
 {
 	uint32_t err;
 	uint8_t info[72];
 	uint8_t *ptr;
 	uint16_t v16;
 
-	err = tpm_get_capability(TPM_CAP_NV_INDEX, index,
-		info, sizeof(info));
+	err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
+				 info, sizeof(info));
 	if (err) {
 		printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
 		       index, err);
@@ -128,13 +129,14 @@
 
 /**
  * @brief search for a key by usage auth and pub key hash.
+ * @param tpm		TPM device
  * @param auth	usage auth of the key to search for
  * @param pubkey_digest	(SHA1) hash of the pub key structure of the key
  * @param[out] handle	the handle of the key iff found
  * @return 0 if key was found in TPM; != 0 if not.
  */
-static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
-		uint32_t *handle)
+static int find_key(struct udevice *tpm, const uint8_t auth[20],
+		    const uint8_t pubkey_digest[20], uint32_t *handle)
 {
 	uint16_t key_count;
 	uint32_t key_handles[10];
@@ -146,7 +148,8 @@
 	unsigned int i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				 sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
@@ -157,7 +160,8 @@
 	/* now search a(/ the) key which we can access with the given auth */
 	for (i = 0; i < key_count; ++i) {
 		buf_len = sizeof(buf);
-		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+		err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+					   &buf_len);
 		if (err && err != TPM_AUTHFAIL)
 			return -1;
 		if (err)
@@ -173,20 +177,21 @@
 
 /**
  * @brief read CCDM common data from TPM NV
+ * @param tpm		TPM device
  * @return 0 if CCDM common data was found and read, !=0 if something failed.
  */
-static int read_common_data(void)
+static int read_common_data(struct udevice *tpm)
 {
 	uint32_t size = 0;
 	uint32_t err;
 	uint8_t buf[256];
 	sha1_context ctx;
 
-	if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) ||
+	if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
 	    size < NV_COMMON_DATA_MIN_SIZE)
 		return 1;
-	err = tpm_nv_read_value(NV_COMMON_DATA_INDEX,
-		buf, min(sizeof(buf), size));
+	err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
+				buf, min(sizeof(buf), size));
 	if (err) {
 		printf("tpm_nv_read_value() failed: %u\n", err);
 		return 1;
@@ -235,6 +240,7 @@
 
 /**
  * @brief get pointer of a hash register by specification and usage.
+ * @param tpm		TPM device
  * @param spec	specification of a hash register
  * @param mode	access mode (read or write or read/write)
  * @return pointer to hash register if found and valid; NULL else.
@@ -244,7 +250,8 @@
  * The value of automatic registers (PCR register and fixed registers) is
  * loaded or computed on read access.
  */
-static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
+static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
+				 enum access_mode mode)
 {
 	struct h_reg *result;
 
@@ -261,13 +268,13 @@
 	if (mode & HREG_RD) {
 		if (!result->valid) {
 			if (IS_PCR_HREG(spec)) {
-				hre_tpm_err = tpm_pcr_read(HREG_IDX(spec),
+				hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
 					result->digest, 20);
 				result->valid = (hre_tpm_err == TPM_SUCCESS);
 			} else if (IS_FIX_HREG(spec)) {
 				switch (HREG_IDX(spec)) {
 				case FIX_HREG_DEVICE_ID_HASH:
-					read_common_data();
+					read_common_data(tpm);
 					break;
 				case FIX_HREG_VENDOR:
 					memcpy(result->digest, vendor, 20);
@@ -337,18 +344,19 @@
 	return _dst;
 }
 
-static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
-		const void *key, size_t key_size)
+static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
+			  struct h_reg *dst_reg, const void *key,
+			  size_t key_size)
 {
 	uint32_t parent_handle;
 	uint32_t key_handle;
 
 	if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
 		return -1;
-	if (find_key(src_reg->digest, dst_reg->digest, &parent_handle))
+	if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
 		return -1;
-	hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size,
-		src_reg->digest, &key_handle);
+	hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
+					 src_reg->digest, &key_handle);
 	if (hre_tpm_err) {
 		hre_err = HRE_E_TPM_FAILURE;
 		return -1;
@@ -359,11 +367,13 @@
 
 /**
  * @brief executes the next opcode on the hash register engine.
+ * @param tpm		TPM device
  * @param[in,out] ip	pointer to the opcode (instruction pointer)
  * @param[in,out] code_size	(remaining) size of the code
  * @return new instruction pointer on success, NULL on error.
  */
-static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
+static const uint8_t *hre_execute_op(struct udevice *tpm, const uint8_t **ip,
+				     size_t *code_size)
 {
 	bool dst_modified = false;
 	uint32_t ins;
@@ -394,10 +404,11 @@
 	if ((opcode & 0x80) && (data_size + 4) > *code_size)
 		return NULL;
 
-	src_reg = access_hreg(src_spec, HREG_RD);
+	src_reg = access_hreg(tpm, src_spec, HREG_RD);
 	if (hre_err || hre_tpm_err)
 		return NULL;
-	dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR);
+	dst_reg = access_hreg(tpm, dst_spec,
+			      (opcode & 0x40) ? HREG_RDWR : HREG_WR);
 	if (hre_err || hre_tpm_err)
 		return NULL;
 
@@ -453,7 +464,7 @@
 		dst_modified = true;
 		break;
 	case HRE_LOADKEY:
-		if (hre_op_loadkey(src_reg, dst_reg, data, data_size))
+		if (hre_op_loadkey(tpm, src_reg, dst_reg, data, data_size))
 			return NULL;
 		break;
 	default:
@@ -461,8 +472,8 @@
 	}
 
 	if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
-		hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest,
-			dst_reg->digest);
+		hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
+					 dst_reg->digest, dst_reg->digest);
 		if (hre_tpm_err) {
 			hre_err = HRE_E_TPM_FAILURE;
 			return NULL;
@@ -481,11 +492,12 @@
 
 /**
  * @brief runs a program on the hash register engine.
+ * @param tpm		TPM device
  * @param code		pointer to the (HRE) code.
  * @param code_size	size of the code (in bytes).
  * @return 0 on success, != 0 on failure.
  */
-int hre_run_program(const uint8_t *code, size_t code_size)
+int hre_run_program(struct udevice *tpm, const uint8_t *code, size_t code_size)
 {
 	size_t code_left;
 	const uint8_t *ip = code;
@@ -494,7 +506,7 @@
 	hre_tpm_err = 0;
 	hre_err = HRE_E_OK;
 	while (code_left > 0)
-		if (!hre_execute_op(&ip, &code_left))
+		if (!hre_execute_op(tpm, &ip, &code_left))
 			return -1;
 
 	return hre_err;
diff --git a/board/gdsys/a38x/hre.h b/board/gdsys/a38x/hre.h
index b562928..da983aa 100644
--- a/board/gdsys/a38x/hre.h
+++ b/board/gdsys/a38x/hre.h
@@ -32,6 +32,6 @@
 };
 
 int hre_verify_program(struct key_program *prg);
-int hre_run_program(const uint8_t *code, size_t code_size);
+int hre_run_program(struct udevice *tpm, const uint8_t *code, size_t code_size);
 
 #endif /* __HRE_H */
diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c
index 1fb5306..291edc3 100644
--- a/board/gdsys/a38x/keyprogram.c
+++ b/board/gdsys/a38x/keyprogram.c
@@ -12,7 +12,7 @@
 
 #include "hre.h"
 
-int flush_keys(void)
+int flush_keys(struct udevice *tpm)
 {
 	u16 key_count;
 	u8 buf[288];
@@ -21,13 +21,15 @@
 	uint i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				 sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
 	ptr = buf + 2;
 	for (i = 0; i < key_count; ++i, ptr += 4) {
-		err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
+		err = tpm_flush_specific(tpm, get_unaligned_be32(ptr),
+					 TPM_RT_KEY);
 		if (err && err != TPM_KEY_OWNER_CONTROL)
 			return err;
 	}
@@ -121,7 +123,7 @@
 	return result;
 }
 
-int load_and_run_keyprog(void)
+int load_and_run_keyprog(struct udevice *tpm)
 {
 	char *cmd = NULL;
 	u8 *binprog = NULL;
@@ -144,7 +146,7 @@
 	if (!prog)
 		return 1;
 
-	if (hre_run_program(prog->code, prog->code_size)) {
+	if (hre_run_program(tpm, prog->code, prog->code_size)) {
 		free(prog);
 		return 1;
 	}
diff --git a/board/gdsys/a38x/keyprogram.h b/board/gdsys/a38x/keyprogram.h
index a4877c7..06889c6 100644
--- a/board/gdsys/a38x/keyprogram.h
+++ b/board/gdsys/a38x/keyprogram.h
@@ -7,7 +7,7 @@
 #ifndef __KEYPROGRAM_H
 #define __KEYPROGRAM_H
 
-int load_and_run_keyprog(void);
-int flush_keys(void);
+int load_and_run_keyprog(struct udevice *tpm);
+int flush_keys(struct udevice *tpm);
 
 #endif /* __KEYPROGRAM_H */
diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c
index 7e082df..6ac956c 100644
--- a/board/gdsys/p1022/controlcenterd-id.c
+++ b/board/gdsys/p1022/controlcenterd-id.c
@@ -11,6 +11,7 @@
 #endif
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <fs.h>
 #include <i2c.h>
@@ -141,6 +142,19 @@
 #define IS_VAR_HREG(spec) (((spec) & 0x38) == 0x10)
 #define HREG_IDX(spec) ((spec) & (IS_PCR_HREG(spec) ? 0x1f : 0x7))
 
+static int get_tpm(struct udevice **devp)
+{
+	int rc;
+
+	rc = uclass_first_device_err(UCLASS_TPM, devp);
+	if (rc) {
+		printf("Could not find TPM (ret=%d)\n", rc);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+}
+
 static const uint8_t vendor[] = "Guntermann & Drunck";
 
 /**
@@ -245,15 +259,15 @@
  * @param size	pointer to the size
  * @return 0 on success, != 0 on error
  */
-static int get_tpm_nv_size(uint32_t index, uint32_t *size)
+static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
 {
 	uint32_t err;
 	uint8_t info[72];
 	uint8_t *ptr;
 	uint16_t v16;
 
-	err = tpm_get_capability(TPM_CAP_NV_INDEX, index,
-		info, sizeof(info));
+	err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
+				 info, sizeof(info));
 	if (err) {
 		printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
 		       index, err);
@@ -281,8 +295,8 @@
  * @param[out] handle	the handle of the key iff found
  * @return 0 if key was found in TPM; != 0 if not.
  */
-static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
-		uint32_t *handle)
+static int find_key(struct udevice *tpm, const uint8_t auth[20],
+		    const uint8_t pubkey_digest[20], uint32_t *handle)
 {
 	uint16_t key_count;
 	uint32_t key_handles[10];
@@ -294,7 +308,8 @@
 	unsigned int i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				 sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
@@ -305,7 +320,8 @@
 	/* now search a(/ the) key which we can access with the given auth */
 	for (i = 0; i < key_count; ++i) {
 		buf_len = sizeof(buf);
-		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+		err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+					   &buf_len);
 		if (err && err != TPM_AUTHFAIL)
 			return -1;
 		if (err)
@@ -323,18 +339,18 @@
  * @brief read CCDM common data from TPM NV
  * @return 0 if CCDM common data was found and read, !=0 if something failed.
  */
-static int read_common_data(void)
+static int read_common_data(struct udevice *tpm)
 {
 	uint32_t size;
 	uint32_t err;
 	uint8_t buf[256];
 	sha1_context ctx;
 
-	if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) ||
+	if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
 	    size < NV_COMMON_DATA_MIN_SIZE)
 		return 1;
-	err = tpm_nv_read_value(NV_COMMON_DATA_INDEX,
-		buf, min(sizeof(buf), size));
+	err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
+				buf, min(sizeof(buf), size));
 	if (err) {
 		printf("tpm_nv_read_value() failed: %u\n", err);
 		return 1;
@@ -467,7 +483,8 @@
  * The value of automatic registers (PCR register and fixed registers) is
  * loaded or computed on read access.
  */
-static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
+static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
+				 enum access_mode mode)
 {
 	struct h_reg *result;
 
@@ -484,13 +501,13 @@
 	if (mode & HREG_RD) {
 		if (!result->valid) {
 			if (IS_PCR_HREG(spec)) {
-				hre_tpm_err = tpm_pcr_read(HREG_IDX(spec),
+				hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
 					result->digest, 20);
 				result->valid = (hre_tpm_err == TPM_SUCCESS);
 			} else if (IS_FIX_HREG(spec)) {
 				switch (HREG_IDX(spec)) {
 				case FIX_HREG_DEVICE_ID_HASH:
-					read_common_data();
+					read_common_data(tpm);
 					break;
 				case FIX_HREG_SELF_HASH:
 					ccdm_compute_self_hash();
@@ -566,18 +583,19 @@
 	return _dst;
 }
 
-static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
-		const void *key, size_t key_size)
+static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
+			  struct h_reg *dst_reg, const void *key,
+			  size_t key_size)
 {
 	uint32_t parent_handle;
 	uint32_t key_handle;
 
 	if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
 		return -1;
-	if (find_key(src_reg->digest, dst_reg->digest, &parent_handle))
+	if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
 		return -1;
-	hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size,
-		src_reg->digest, &key_handle);
+	hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
+					 src_reg->digest, &key_handle);
 	if (hre_tpm_err) {
 		hre_err = HRE_E_TPM_FAILURE;
 		return -1;
@@ -593,7 +611,8 @@
  * @param[in,out] code_size	(remaining) size of the code
  * @return new instruction pointer on success, NULL on error.
  */
-static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
+static const uint8_t *hre_execute_op(struct udevice *tpm, const uint8_t **ip,
+				     size_t *code_size)
 {
 	bool dst_modified = false;
 	uint32_t ins;
@@ -624,10 +643,11 @@
 	if ((opcode & 0x80) && (data_size + 4) > *code_size)
 		return NULL;
 
-	src_reg = access_hreg(src_spec, HREG_RD);
+	src_reg = access_hreg(tpm, src_spec, HREG_RD);
 	if (hre_err || hre_tpm_err)
 		return NULL;
-	dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR);
+	dst_reg = access_hreg(tpm, dst_spec,
+			      (opcode & 0x40) ? HREG_RDWR : HREG_WR);
 	if (hre_err || hre_tpm_err)
 		return NULL;
 
@@ -683,7 +703,7 @@
 		dst_modified = true;
 		break;
 	case HRE_LOADKEY:
-		if (hre_op_loadkey(src_reg, dst_reg, data, data_size))
+		if (hre_op_loadkey(tpm, src_reg, dst_reg, data, data_size))
 			return NULL;
 		break;
 	default:
@@ -691,8 +711,8 @@
 	}
 
 	if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
-		hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest,
-			dst_reg->digest);
+		hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
+					 dst_reg->digest, dst_reg->digest);
 		if (hre_tpm_err) {
 			hre_err = HRE_E_TPM_FAILURE;
 			return NULL;
@@ -715,7 +735,8 @@
  * @param code_size	size of the code (in bytes).
  * @return 0 on success, != 0 on failure.
  */
-static int hre_run_program(const uint8_t *code, size_t code_size)
+static int hre_run_program(struct udevice *tpm, const uint8_t *code,
+			   size_t code_size)
 {
 	size_t code_left;
 	const uint8_t *ip = code;
@@ -724,7 +745,7 @@
 	hre_tpm_err = 0;
 	hre_err = HRE_E_OK;
 	while (code_left > 0)
-		if (!hre_execute_op(&ip, &code_left))
+		if (!hre_execute_op(tpm, &ip, &code_left))
 			return -1;
 
 	return hre_err;
@@ -929,26 +950,27 @@
 	0x81, 0x2e, 0x30, 0x00, /* opcode: LOAD PCR3, f3 */
 };
 
-static int first_stage_actions(void)
+static int first_stage_actions(struct udevice *tpm)
 {
 	int result = 0;
 	struct key_program *sd_prg = NULL;
 
 	puts("CCDM S1: start actions\n");
 #ifndef CCDM_SECOND_STAGE
-	if (tpm_continue_self_test())
+	if (tpm_continue_self_test(tpm))
 		goto failure;
 #else
-	tpm_continue_self_test();
+	tpm_continue_self_test(tpm);
 #endif
 	mdelay(37);
 
-	if (hre_run_program(prg_stage1_prepare, sizeof(prg_stage1_prepare)))
+	if (hre_run_program(tpm, prg_stage1_prepare,
+			    sizeof(prg_stage1_prepare)))
 		goto failure;
 
 	sd_prg = load_sd_key_program();
 	if (sd_prg) {
-		if (hre_run_program(sd_prg->code, sd_prg->code_size))
+		if (hre_run_program(tpm, sd_prg->code, sd_prg->code_size))
 			goto failure;
 		puts("SD code run successfully\n");
 	} else {
@@ -969,19 +991,22 @@
 #ifdef CCDM_FIRST_STAGE
 static int first_stage_init(void)
 {
-	int res = 0;
+	struct udevice *tpm;
+	int ret;
+
 	puts("CCDM S1\n");
-	if (tpm_init() || tpm_startup(TPM_ST_CLEAR))
+	ret = get_tpm(&tpm);
+	if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR))
 		return 1;
-	res = first_stage_actions();
+	ret = first_stage_actions(tpm);
 #ifndef CCDM_SECOND_STAGE
-	if (!res) {
+	if (!ret) {
 		if (bl2_entry)
 			(*bl2_entry)();
-		res = 1;
+		ret = 1;
 	}
 #endif
-	return res;
+	return ret;
 }
 #endif
 
@@ -1021,24 +1046,28 @@
 	char *mac_path = NULL;
 	ulong image_addr;
 	loff_t image_size;
+	struct udevice *tpm;
 	uint32_t err;
+	int ret;
 
 	printf("CCDM S2\n");
-	if (tpm_init())
+	ret = get_tpm(&tpm);
+	if (ret || tpm_init(tpm))
 		return 1;
-	err = tpm_startup(TPM_ST_CLEAR);
+	err = tpm_startup(tpm, TPM_ST_CLEAR);
 	if (err != TPM_INVALID_POSTINIT)
 		did_first_stage_run = false;
 
 #ifdef CCDM_AUTO_FIRST_STAGE
-	if (!did_first_stage_run && first_stage_actions())
+	if (!did_first_stage_run && first_stage_actions(tpm))
 		goto failure;
 #else
 	if (!did_first_stage_run)
 		goto failure;
 #endif
 
-	if (hre_run_program(prg_stage2_prepare, sizeof(prg_stage2_prepare)))
+	if (hre_run_program(tpm, prg_stage2_prepare,
+			    sizeof(prg_stage2_prepare)))
 		goto failure;
 
 	/* run "prepboot" from env to get "mmcdev" set */
@@ -1083,12 +1112,12 @@
 	}
 	puts("CCDM image OK\n");
 
-	hre_run_program(prg_stage2_success, sizeof(prg_stage2_success));
+	hre_run_program(tpm, prg_stage2_success, sizeof(prg_stage2_success));
 
 	goto end;
 failure:
 	result = 1;
-	hre_run_program(prg_stage_fail, sizeof(prg_stage_fail));
+	hre_run_program(tpm, prg_stage_fail, sizeof(prg_stage_fail));
 end:
 	if (hmac_blob)
 		free(hmac_blob);
diff --git a/cmd/fdt.c b/cmd/fdt.c
index 84be26f..10d8f32 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -73,6 +73,40 @@
 	return 0;
 }
 
+static const char * const fdt_member_table[] = {
+	"magic",
+	"totalsize",
+	"off_dt_struct",
+	"off_dt_strings",
+	"off_mem_rsvmap",
+	"version",
+	"last_comp_version",
+	"boot_cpuid_phys",
+	"size_dt_strings",
+	"size_dt_struct",
+};
+
+static int fdt_get_header_value(int argc, char * const argv[])
+{
+	fdt32_t *fdtp = (fdt32_t *)working_fdt;
+	ulong val;
+	int i;
+
+	if (argv[2][0] != 'g')
+		return CMD_RET_FAILURE;
+
+	for (i = 0; i < ARRAY_SIZE(fdt_member_table); i++) {
+		if (strcmp(fdt_member_table[i], argv[4]))
+			continue;
+
+		val = fdt32_to_cpu(fdtp[i]);
+		env_set_hex(argv[3], val);
+		return CMD_RET_SUCCESS;
+	}
+
+	return CMD_RET_FAILURE;
+}
+
 /*
  * Flattened Device Tree command, see the help for parameter definitions.
  */
@@ -491,6 +525,9 @@
 	 * Display header info
 	 */
 	} else if (argv[1][0] == 'h') {
+		if (argc == 5)
+			return fdt_get_header_value(argc, argv);
+
 		u32 version = fdt_version(working_fdt);
 		printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
 		printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
@@ -1090,7 +1127,8 @@
 	"fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n"
 	"fdt mknode <path> <node>            - Create a new node after <path>\n"
 	"fdt rm     <path> [<prop>]          - Delete the node or <property>\n"
-	"fdt header                          - Display header info\n"
+	"fdt header [get <var> <member>]     - Display header info\n"
+	"                                      get - get header member <member> and store it in <var>\n"
 	"fdt bootcpu <id>                    - Set boot cpuid\n"
 	"fdt memory <addr> <size>            - Add/Update memory node\n"
 	"fdt rsvmem print                    - Show current mem reserves\n"
diff --git a/cmd/tpm-common.c b/cmd/tpm-common.c
index 5644386..89f2aa0 100644
--- a/cmd/tpm-common.c
+++ b/cmd/tpm-common.c
@@ -264,10 +264,16 @@
 
 int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
+	struct udevice *dev;
+	int rc;
+
 	if (argc != 1)
 		return CMD_RET_USAGE;
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
-	return report_return_code(tpm_init());
+	return report_return_code(tpm_init(dev));
 }
 
 int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
diff --git a/cmd/tpm-v1.c b/cmd/tpm-v1.c
index 6987000..b75e093 100644
--- a/cmd/tpm-v1.c
+++ b/cmd/tpm-v1.c
@@ -14,7 +14,12 @@
 			  char * const argv[])
 {
 	enum tpm_startup_type mode;
+	struct udevice *dev;
+	int rc;
 
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 	if (argc != 2)
 		return CMD_RET_USAGE;
 	if (!strcasecmp("TPM_ST_CLEAR", argv[1])) {
@@ -28,13 +33,19 @@
 		return CMD_RET_FAILURE;
 	}
 
-	return report_return_code(tpm_startup(mode));
+	return report_return_code(tpm_startup(dev, mode));
 }
 
 static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, int argc,
 				  char * const argv[])
 {
 	u32 index, perm, size;
+	struct udevice *dev;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 4)
 		return CMD_RET_USAGE;
@@ -42,22 +53,27 @@
 	perm = simple_strtoul(argv[2], NULL, 0);
 	size = simple_strtoul(argv[3], NULL, 0);
 
-	return report_return_code(tpm_nv_define_space(index, perm, size));
+	return report_return_code(tpm_nv_define_space(dev, index, perm, size));
 }
 
 static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, int argc,
 				char * const argv[])
 {
 	u32 index, count, rc;
+	struct udevice *dev;
 	void *data;
 
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
+
 	if (argc != 4)
 		return CMD_RET_USAGE;
 	index = simple_strtoul(argv[1], NULL, 0);
 	data = (void *)simple_strtoul(argv[2], NULL, 0);
 	count = simple_strtoul(argv[3], NULL, 0);
 
-	rc = tpm_nv_read_value(index, data, count);
+	rc = tpm_nv_read_value(dev, index, data, count);
 	if (!rc) {
 		puts("area content:\n");
 		print_byte_string(data, count);
@@ -69,10 +85,15 @@
 static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, int argc,
 				 char * const argv[])
 {
+	struct udevice *dev;
 	u32 index, rc;
 	size_t count;
 	void *data;
 
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
+
 	if (argc != 3)
 		return CMD_RET_USAGE;
 	index = simple_strtoul(argv[1], NULL, 0);
@@ -82,7 +103,7 @@
 		return CMD_RET_FAILURE;
 	}
 
-	rc = tpm_nv_write_value(index, data, count);
+	rc = tpm_nv_write_value(dev, index, data, count);
 	free(data);
 
 	return report_return_code(rc);
@@ -91,8 +112,13 @@
 static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, int argc,
 			 char * const argv[])
 {
-	u32 index, rc;
 	u8 in_digest[20], out_digest[20];
+	struct udevice *dev;
+	u32 index, rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 3)
 		return CMD_RET_USAGE;
@@ -102,7 +128,7 @@
 		return CMD_RET_FAILURE;
 	}
 
-	rc = tpm_extend(index, in_digest, out_digest);
+	rc = tpm_extend(dev, index, in_digest, out_digest);
 	if (!rc) {
 		puts("PCR value after execution of the command:\n");
 		print_byte_string(out_digest, sizeof(out_digest));
@@ -115,15 +141,20 @@
 			   char * const argv[])
 {
 	u32 index, count, rc;
+	struct udevice *dev;
 	void *data;
 
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
+
 	if (argc != 4)
 		return CMD_RET_USAGE;
 	index = simple_strtoul(argv[1], NULL, 0);
 	data = (void *)simple_strtoul(argv[2], NULL, 0);
 	count = simple_strtoul(argv[3], NULL, 0);
 
-	rc = tpm_pcr_read(index, data, count);
+	rc = tpm_pcr_read(dev, index, data, count);
 	if (!rc) {
 		puts("Named PCR content:\n");
 		print_byte_string(data, count);
@@ -135,27 +166,38 @@
 static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, int argc,
 					char * const argv[])
 {
+	struct udevice *dev;
 	u16 presence;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 2)
 		return CMD_RET_USAGE;
 	presence = (u16)simple_strtoul(argv[1], NULL, 0);
 
-	return report_return_code(tpm_tsc_physical_presence(presence));
+	return report_return_code(tpm_tsc_physical_presence(dev, presence));
 }
 
 static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, int argc,
 			     char * const argv[])
 {
+	struct udevice *dev;
 	u32 count, rc;
 	void *data;
 
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
+
 	if (argc != 3)
 		return CMD_RET_USAGE;
 	data = (void *)simple_strtoul(argv[1], NULL, 0);
 	count = simple_strtoul(argv[2], NULL, 0);
 
-	rc = tpm_read_pubek(data, count);
+	rc = tpm_read_pubek(dev, data, count);
 	if (!rc) {
 		puts("pubek value:\n");
 		print_byte_string(data, count);
@@ -167,13 +209,19 @@
 static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, int argc,
 					   char * const argv[])
 {
+	struct udevice *dev;
 	u8 state;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 2)
 		return CMD_RET_USAGE;
 	state = (u8)simple_strtoul(argv[1], NULL, 0);
 
-	return report_return_code(tpm_physical_set_deactivated(state));
+	return report_return_code(tpm_physical_set_deactivated(dev, state));
 }
 
 static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -182,6 +230,11 @@
 	u32 cap_area, sub_cap, rc;
 	void *cap;
 	size_t count;
+	struct udevice *dev;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 5)
 		return CMD_RET_USAGE;
@@ -190,7 +243,7 @@
 	cap = (void *)simple_strtoul(argv[3], NULL, 0);
 	count = simple_strtoul(argv[4], NULL, 0);
 
-	rc = tpm_get_capability(cap_area, sub_cap, cap, count);
+	rc = tpm_get_capability(dev, cap_area, sub_cap, cap, count);
 	if (!rc) {
 		puts("capability information:\n");
 		print_byte_string(cap, count);
@@ -232,6 +285,12 @@
 			    char * const argv[])
 {
 	u32 index, perm, size;
+	struct udevice *dev;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 4)
 		return CMD_RET_USAGE;
@@ -243,14 +302,20 @@
 	index = simple_strtoul(argv[2], NULL, 0);
 	perm = simple_strtoul(argv[3], NULL, 0);
 
-	return report_return_code(tpm_nv_define_space(index, perm, size));
+	return report_return_code(tpm_nv_define_space(dev, index, perm, size));
 }
 
 static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, int argc,
 			  char * const argv[])
 {
 	u32 index, count, err;
+	struct udevice *dev;
 	void *data;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc < 3)
 		return CMD_RET_USAGE;
@@ -263,7 +328,7 @@
 		return CMD_RET_USAGE;
 	}
 
-	err = tpm_nv_read_value(index, data, count);
+	err = tpm_nv_read_value(dev, index, data, count);
 	if (!err) {
 		if (type_string_write_vars(argv[1], data, argv + 3)) {
 			printf("Couldn't write to variables\n");
@@ -279,7 +344,13 @@
 			   char * const argv[])
 {
 	u32 index, count, err;
+	struct udevice *dev;
 	void *data;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc < 3)
 		return CMD_RET_USAGE;
@@ -297,7 +368,7 @@
 		return CMD_RET_USAGE;
 	}
 
-	err = tpm_nv_write_value(index, data, count);
+	err = tpm_nv_write_value(dev, index, data, count);
 	free(data);
 
 	return report_return_code(err);
@@ -309,8 +380,14 @@
 		       char * const argv[])
 {
 	u32 auth_handle, err;
+	struct udevice *dev;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
-	err = tpm_oiap(&auth_handle);
+	err = tpm_oiap(dev, &auth_handle);
 
 	return report_return_code(err);
 }
@@ -324,6 +401,11 @@
 	u8 usage_auth[DIGEST_LENGTH];
 	u8 parent_hash[DIGEST_LENGTH];
 	void *key;
+	struct udevice *dev;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc < 5)
 		return CMD_RET_USAGE;
@@ -360,6 +442,12 @@
 	u32 parent_handle, key_len, key_handle, err;
 	u8 usage_auth[DIGEST_LENGTH];
 	void *key;
+	struct udevice *dev;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc < 5)
 		return CMD_RET_USAGE;
@@ -371,7 +459,7 @@
 		return CMD_RET_FAILURE;
 	parse_byte_string(argv[4], usage_auth, NULL);
 
-	err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
+	err = tpm_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth,
 				 &key_handle);
 	if (!err)
 		printf("Key handle is 0x%x\n", key_handle);
@@ -386,6 +474,12 @@
 	u8 usage_auth[DIGEST_LENGTH];
 	u8 pub_key_buffer[TPM_PUBKEY_MAX_LENGTH];
 	size_t pub_key_len = sizeof(pub_key_buffer);
+	struct udevice *dev;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc < 3)
 		return CMD_RET_USAGE;
@@ -395,7 +489,7 @@
 		return CMD_RET_FAILURE;
 	parse_byte_string(argv[2], usage_auth, NULL);
 
-	err = tpm_get_pub_key_oiap(key_handle, usage_auth, pub_key_buffer,
+	err = tpm_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer,
 				   &pub_key_len);
 	if (!err) {
 		printf("dump of received pub key structure:\n");
@@ -412,7 +506,13 @@
 static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
 			char * const argv[])
 {
+	struct udevice *dev;
 	int type = 0;
+	int rc;
+
+	rc = get_tpm(&dev);
+	if (rc)
+		return rc;
 
 	if (argc != 3)
 		return CMD_RET_USAGE;
@@ -451,7 +551,7 @@
 		uint i;
 
 		/* fetch list of already loaded resources in the TPM */
-		err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
+		err = tpm_get_capability(dev, TPM_CAP_HANDLE, type, buf,
 					 sizeof(buf));
 		if (err) {
 			printf("tpm_get_capability returned error %d.\n", err);
@@ -460,7 +560,7 @@
 		res_count = get_unaligned_be16(buf);
 		ptr = buf + 2;
 		for (i = 0; i < res_count; ++i, ptr += 4)
-			tpm_flush_specific(get_unaligned_be32(ptr), type);
+			tpm_flush_specific(dev, get_unaligned_be32(ptr), type);
 	} else {
 		u32 handle = simple_strtoul(argv[2], NULL, 0);
 
@@ -468,7 +568,7 @@
 			printf("Illegal resource handle %s\n", argv[2]);
 			return -1;
 		}
-		tpm_flush_specific(cpu_to_be32(handle), type);
+		tpm_flush_specific(dev, cpu_to_be32(handle), type);
 	}
 
 	return 0;
diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
index ffbf35a..bb51834 100644
--- a/cmd/tpm-v2.c
+++ b/cmd/tpm-v2.c
@@ -16,7 +16,12 @@
 			   char * const argv[])
 {
 	enum tpm2_startup_types mode;
+	struct udevice *dev;
+	int ret;
 
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 	if (argc != 2)
 		return CMD_RET_USAGE;
 
@@ -29,14 +34,19 @@
 		return CMD_RET_FAILURE;
 	}
 
-	return report_return_code(tpm2_startup(mode));
+	return report_return_code(tpm2_startup(dev, mode));
 }
 
 static int do_tpm2_self_test(cmd_tbl_t *cmdtp, int flag, int argc,
 			     char * const argv[])
 {
 	enum tpm2_yes_no full_test;
+	struct udevice *dev;
+	int ret;
 
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 	if (argc != 2)
 		return CMD_RET_USAGE;
 
@@ -49,7 +59,7 @@
 		return CMD_RET_FAILURE;
 	}
 
-	return report_return_code(tpm2_self_test(full_test));
+	return report_return_code(tpm2_self_test(dev, full_test));
 }
 
 static int do_tpm2_clear(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -58,6 +68,12 @@
 	u32 handle = 0;
 	const char *pw = (argc < 3) ? NULL : argv[2];
 	const ssize_t pw_sz = pw ? strlen(pw) : 0;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (argc < 2 || argc > 3)
 		return CMD_RET_USAGE;
@@ -72,7 +88,7 @@
 	else
 		return CMD_RET_USAGE;
 
-	return report_return_code(tpm2_clear(handle, pw, pw_sz));
+	return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
 }
 
 static int do_tpm2_pcr_extend(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -88,7 +104,7 @@
 	if (argc != 3)
 		return CMD_RET_USAGE;
 
-	ret = uclass_first_device_err(UCLASS_TPM, &dev);
+	ret = get_tpm(&dev);
 	if (ret)
 		return ret;
 
@@ -99,7 +115,7 @@
 	if (index >= priv->pcr_count)
 		return -EINVAL;
 
-	rc = tpm2_pcr_extend(index, digest);
+	rc = tpm2_pcr_extend(dev, index, digest);
 
 	unmap_sysmem(digest);
 
@@ -119,7 +135,7 @@
 	if (argc != 3)
 		return CMD_RET_USAGE;
 
-	ret = uclass_first_device_err(UCLASS_TPM, &dev);
+	ret = get_tpm(&dev);
 	if (ret)
 		return ret;
 
@@ -133,7 +149,7 @@
 
 	data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
 
-	rc = tpm2_pcr_read(index, priv->pcr_select_min, data, &updates);
+	rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates);
 	if (!rc) {
 		printf("PCR #%u content (%d known updates):\n", index, updates);
 		print_byte_string(data, TPM2_DIGEST_LEN);
@@ -151,6 +167,12 @@
 	u8 *data;
 	size_t count;
 	int i, j;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (argc != 5)
 		return CMD_RET_USAGE;
@@ -160,7 +182,7 @@
 	data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
 	count = simple_strtoul(argv[4], NULL, 0);
 
-	rc = tpm2_get_capability(capability, property, data, count);
+	rc = tpm2_get_capability(dev, capability, property, data, count);
 	if (rc)
 		goto unmap_data;
 
@@ -186,6 +208,12 @@
 {
 	const char *pw = (argc < 2) ? NULL : argv[1];
 	const ssize_t pw_sz = pw ? strlen(pw) : 0;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (argc > 2)
 		return CMD_RET_USAGE;
@@ -193,7 +221,7 @@
 	if (pw_sz > TPM2_DIGEST_LEN)
 		return -EINVAL;
 
-	return report_return_code(tpm2_dam_reset(pw, pw_sz));
+	return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
 }
 
 static int do_tpm_dam_parameters(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -208,6 +236,12 @@
 	unsigned long int max_tries;
 	unsigned long int recovery_time;
 	unsigned long int lockout_recovery;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (argc < 4 || argc > 5)
 		return CMD_RET_USAGE;
@@ -229,7 +263,7 @@
 	log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
 	log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
 
-	return report_return_code(tpm2_dam_parameters(pw, pw_sz, max_tries,
+	return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
 						      recovery_time,
 						      lockout_recovery));
 }
@@ -242,6 +276,12 @@
 	const char *oldpw = (argc == 3) ? NULL : argv[3];
 	const ssize_t newpw_sz = strlen(newpw);
 	const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (argc < 3 || argc > 4)
 		return CMD_RET_USAGE;
@@ -260,7 +300,7 @@
 	else
 		return CMD_RET_USAGE;
 
-	return report_return_code(tpm2_change_auth(handle, newpw, newpw_sz,
+	return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
 						   oldpw, oldpw_sz));
 }
 
@@ -271,6 +311,12 @@
 	char *key = argv[2];
 	const char *pw = (argc < 4) ? NULL : argv[3];
 	const ssize_t pw_sz = pw ? strlen(pw) : 0;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (strlen(key) != TPM2_DIGEST_LEN)
 		return -EINVAL;
@@ -278,7 +324,7 @@
 	if (argc < 3 || argc > 4)
 		return CMD_RET_USAGE;
 
-	return report_return_code(tpm2_pcr_setauthpolicy(pw, pw_sz, index,
+	return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
 							 key));
 }
 
@@ -290,6 +336,12 @@
 	const ssize_t key_sz = strlen(key);
 	const char *pw = (argc < 4) ? NULL : argv[3];
 	const ssize_t pw_sz = pw ? strlen(pw) : 0;
+	struct udevice *dev;
+	int ret;
+
+	ret = get_tpm(&dev);
+	if (ret)
+		return ret;
 
 	if (strlen(key) != TPM2_DIGEST_LEN)
 		return -EINVAL;
@@ -297,7 +349,7 @@
 	if (argc < 3 || argc > 4)
 		return CMD_RET_USAGE;
 
-	return report_return_code(tpm2_pcr_setauthvalue(pw, pw_sz, index,
+	return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
 							key, key_sz));
 }
 
diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
index f21ad5d..56a5aa4 100644
--- a/cmd/tpm_test.c
+++ b/cmd/tpm_test.c
@@ -7,6 +7,7 @@
 #include <command.h>
 #include <environment.h>
 #include <tpm-v1.h>
+#include "tpm-user-utils.h"
 
 /* Prints error and returns on failure */
 #define TPM_CHECK(tpm_command) do { \
@@ -28,26 +29,26 @@
 #define PHYS_PRESENCE		4
 #define PRESENCE		8
 
-static uint32_t TlclStartupIfNeeded(void)
+static uint32_t TlclStartupIfNeeded(struct udevice *dev)
 {
-	uint32_t result = tpm_startup(TPM_ST_CLEAR);
+	uint32_t result = tpm_startup(dev, TPM_ST_CLEAR);
 
 	return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
 }
 
-static int test_timer(void)
+static int test_timer(struct udevice *dev)
 {
 	printf("get_timer(0) = %lu\n", get_timer(0));
 	return 0;
 }
 
-static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated,
-			      uint8_t *nvlocked)
+static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable,
+			      uint8_t *deactivated, uint8_t *nvlocked)
 {
 	struct tpm_permanent_flags pflags;
 	uint32_t result;
 
-	result = tpm_get_permanent_flags(&pflags);
+	result = tpm_get_permanent_flags(dev, &pflags);
 	if (result)
 		return result;
 	if (disable)
@@ -62,79 +63,79 @@
 	return 0;
 }
 
-static uint32_t tpm_nv_write_value_lock(uint32_t index)
+static uint32_t tpm_nv_write_value_lock(struct udevice *dev, uint32_t index)
 {
 	debug("TPM: Write lock 0x%x\n", index);
 
-	return tpm_nv_write_value(index, NULL, 0);
+	return tpm_nv_write_value(dev, index, NULL, 0);
 }
 
-static int tpm_is_owned(void)
+static int tpm_is_owned(struct udevice *dev)
 {
 	uint8_t response[TPM_PUBEK_SIZE];
 	uint32_t result;
 
-	result = tpm_read_pubek(response, sizeof(response));
+	result = tpm_read_pubek(dev, response, sizeof(response));
 
 	return result != TPM_SUCCESS;
 }
 
-static int test_early_extend(void)
+static int test_early_extend(struct udevice *dev)
 {
 	uint8_t value_in[20];
 	uint8_t value_out[20];
 
 	printf("Testing earlyextend ...");
-	tpm_init();
-	TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
-	TPM_CHECK(tpm_continue_self_test());
-	TPM_CHECK(tpm_extend(1, value_in, value_out));
+	tpm_init(dev);
+	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
+	TPM_CHECK(tpm_continue_self_test(dev));
+	TPM_CHECK(tpm_extend(dev, 1, value_in, value_out));
 	printf("done\n");
 	return 0;
 }
 
-static int test_early_nvram(void)
+static int test_early_nvram(struct udevice *dev)
 {
 	uint32_t x;
 
 	printf("Testing earlynvram ...");
-	tpm_init();
-	TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
-	TPM_CHECK(tpm_continue_self_test());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
+	tpm_init(dev);
+	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
+	TPM_CHECK(tpm_continue_self_test(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 	printf("done\n");
 	return 0;
 }
 
-static int test_early_nvram2(void)
+static int test_early_nvram2(struct udevice *dev)
 {
 	uint32_t x;
 
 	printf("Testing earlynvram2 ...");
-	tpm_init();
-	TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
-	TPM_CHECK(tpm_continue_self_test());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)));
+	tpm_init(dev);
+	TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
+	TPM_CHECK(tpm_continue_self_test(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 	printf("done\n");
 	return 0;
 }
 
-static int test_enable(void)
+static int test_enable(struct udevice *dev)
 {
 	uint8_t disable = 0, deactivated = 0;
 
 	printf("Testing enable ...\n");
-	tpm_init();
-	TPM_CHECK(TlclStartupIfNeeded());
-	TPM_CHECK(tpm_self_test_full());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
+	tpm_init(dev);
+	TPM_CHECK(TlclStartupIfNeeded(dev));
+	TPM_CHECK(tpm_self_test_full(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
-	TPM_CHECK(tpm_physical_enable());
-	TPM_CHECK(tpm_physical_set_deactivated(0));
-	TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
+	TPM_CHECK(tpm_physical_enable(dev));
+	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
+	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
 	if (disable == 1 || deactivated == 1)
 		printf("\tfailed to enable or activate\n");
@@ -147,27 +148,27 @@
 	reset_cpu(0); \
 } while (0)
 
-static int test_fast_enable(void)
+static int test_fast_enable(struct udevice *dev)
 {
 	uint8_t disable = 0, deactivated = 0;
 	int i;
 
 	printf("Testing fastenable ...\n");
-	tpm_init();
-	TPM_CHECK(TlclStartupIfNeeded());
-	TPM_CHECK(tpm_self_test_full());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
+	tpm_init(dev);
+	TPM_CHECK(TlclStartupIfNeeded(dev));
+	TPM_CHECK(tpm_self_test_full(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 	printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
 	for (i = 0; i < 2; i++) {
-		TPM_CHECK(tpm_force_clear());
-		TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
+		TPM_CHECK(tpm_force_clear(dev));
+		TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 		printf("\tdisable is %d, deactivated is %d\n", disable,
 		       deactivated);
 		assert(disable == 1 && deactivated == 1);
-		TPM_CHECK(tpm_physical_enable());
-		TPM_CHECK(tpm_physical_set_deactivated(0));
-		TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
+		TPM_CHECK(tpm_physical_enable(dev));
+		TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
+		TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
 		printf("\tdisable is %d, deactivated is %d\n", disable,
 		       deactivated);
 		assert(disable == 0 && deactivated == 0);
@@ -176,105 +177,109 @@
 	return 0;
 }
 
-static int test_global_lock(void)
+static int test_global_lock(struct udevice *dev)
 {
 	uint32_t zero = 0;
 	uint32_t result;
 	uint32_t x;
 
 	printf("Testing globallock ...\n");
-	tpm_init();
-	TPM_CHECK(TlclStartupIfNeeded());
-	TPM_CHECK(tpm_self_test_full());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
-	TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero,
+	tpm_init(dev);
+	TPM_CHECK(TlclStartupIfNeeded(dev));
+	TPM_CHECK(tpm_self_test_full(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero,
 				     sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
-	TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero,
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero,
 				     sizeof(uint32_t)));
-	TPM_CHECK(tpm_set_global_lock());
+	TPM_CHECK(tpm_set_global_lock(dev));
 	/* Verifies that write to index0 fails */
 	x = 1;
-	result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x));
+	result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x));
 	assert(result == TPM_AREA_LOCKED);
-	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
 	assert(x == 0);
 	/* Verifies that write to index1 is still possible */
 	x = 2;
-	TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)));
-	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 	assert(x == 2);
 	/* Turns off PP */
-	tpm_tsc_physical_presence(PHYS_PRESENCE);
+	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
 	/* Verifies that write to index1 fails */
 	x = 3;
-	result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x));
+	result = tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x));
 	assert(result == TPM_BAD_PRESENCE);
-	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 	assert(x == 2);
 	printf("\tdone\n");
 	return 0;
 }
 
-static int test_lock(void)
+static int test_lock(struct udevice *dev)
 {
 	printf("Testing lock ...\n");
-	tpm_init();
-	tpm_startup(TPM_ST_CLEAR);
-	tpm_self_test_full();
-	tpm_tsc_physical_presence(PRESENCE);
-	tpm_nv_write_value_lock(INDEX0);
+	tpm_init(dev);
+	tpm_startup(dev, TPM_ST_CLEAR);
+	tpm_self_test_full(dev);
+	tpm_tsc_physical_presence(dev, PRESENCE);
+	tpm_nv_write_value_lock(dev, INDEX0);
 	printf("\tLocked 0x%x\n", INDEX0);
 	printf("\tdone\n");
 	return 0;
 }
 
-static void initialise_spaces(void)
+static void initialise_spaces(struct udevice *dev)
 {
 	uint32_t zero = 0;
 	uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
 
 	printf("\tInitialising spaces\n");
-	tpm_nv_set_locked();  /* useful only the first time */
-	tpm_nv_define_space(INDEX0, perm, 4);
-	tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4);
-	tpm_nv_define_space(INDEX1, perm, 4);
-	tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4);
-	tpm_nv_define_space(INDEX2, perm, 4);
-	tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4);
-	tpm_nv_define_space(INDEX3, perm, 4);
-	tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4);
+	tpm_nv_set_locked(dev);  /* useful only the first time */
+	tpm_nv_define_space(dev, INDEX0, perm, 4);
+	tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
+	tpm_nv_define_space(dev, INDEX1, perm, 4);
+	tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
+	tpm_nv_define_space(dev, INDEX2, perm, 4);
+	tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
+	tpm_nv_define_space(dev, INDEX3, perm, 4);
+	tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
 	perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
 		TPM_NV_PER_PPWRITE;
-	tpm_nv_define_space(INDEX_INITIALISED, perm, 1);
+	tpm_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
 }
 
-static int test_readonly(void)
+static int test_readonly(struct udevice *dev)
 {
 	uint8_t c;
 	uint32_t index_0, index_1, index_2, index_3;
 	int read0, read1, read2, read3;
 
 	printf("Testing readonly ...\n");
-	tpm_init();
-	tpm_startup(TPM_ST_CLEAR);
-	tpm_self_test_full();
-	tpm_tsc_physical_presence(PRESENCE);
+	tpm_init(dev);
+	tpm_startup(dev, TPM_ST_CLEAR);
+	tpm_self_test_full(dev);
+	tpm_tsc_physical_presence(dev, PRESENCE);
 	/*
 	 * Checks if initialisation has completed by trying to read-lock a
 	 * space that's created at the end of initialisation
 	 */
-	if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
+	if (tpm_nv_read_value(dev, INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
 		/* The initialisation did not complete */
-		initialise_spaces();
+		initialise_spaces(dev);
 	}
 
 	/* Checks if spaces are OK or messed up */
-	read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0));
-	read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1));
-	read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2));
-	read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3));
+	read0 = tpm_nv_read_value(dev, INDEX0, (uint8_t *)&index_0,
+				  sizeof(index_0));
+	read1 = tpm_nv_read_value(dev, INDEX1, (uint8_t *)&index_1,
+				  sizeof(index_1));
+	read2 = tpm_nv_read_value(dev, INDEX2, (uint8_t *)&index_2,
+				  sizeof(index_2));
+	read3 = tpm_nv_read_value(dev, INDEX3, (uint8_t *)&index_3,
+				  sizeof(index_3));
 	if (read0 || read1 || read2 || read3) {
 		printf("Invalid contents\n");
 		return 0;
@@ -285,12 +290,14 @@
 	 * I really wish I could use the imperative.
 	 */
 	index_0 += 1;
-	if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
+	if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
+			       sizeof(index_0) !=
 		TPM_SUCCESS)) {
 		pr_err("\tcould not write index 0\n");
 	}
-	tpm_nv_write_value_lock(INDEX0);
-	if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
+	tpm_nv_write_value_lock(dev, INDEX0);
+	if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
+			       sizeof(index_0)) ==
 			TPM_SUCCESS)
 		pr_err("\tindex 0 is not locked\n");
 
@@ -298,49 +305,49 @@
 	return 0;
 }
 
-static int test_redefine_unowned(void)
+static int test_redefine_unowned(struct udevice *dev)
 {
 	uint32_t perm;
 	uint32_t result;
 	uint32_t x;
 
 	printf("Testing redefine_unowned ...");
-	tpm_init();
-	TPM_CHECK(TlclStartupIfNeeded());
-	TPM_CHECK(tpm_self_test_full());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	assert(!tpm_is_owned());
+	tpm_init(dev);
+	TPM_CHECK(TlclStartupIfNeeded(dev));
+	TPM_CHECK(tpm_self_test_full(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	assert(!tpm_is_owned(dev));
 
 	/* Ensures spaces exist. */
-	TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
-	TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+	TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
 
 	/* Redefines spaces a couple of times. */
 	perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
-	TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)));
+	TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, 2 * sizeof(uint32_t)));
+	TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
 	perm = TPM_NV_PER_PPWRITE;
-	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
+	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
+	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 
 	/* Sets the global lock */
-	tpm_set_global_lock();
+	tpm_set_global_lock(dev);
 
 	/* Verifies that index0 cannot be redefined */
-	result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
+	result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
 	assert(result == TPM_AREA_LOCKED);
 
 	/* Checks that index1 can */
-	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
-	TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
+	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t)));
+	TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
 
 	/* Turns off PP */
-	tpm_tsc_physical_presence(PHYS_PRESENCE);
+	tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
 
 	/* Verifies that neither index0 nor index1 can be redefined */
-	result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
+	result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
 	assert(result == TPM_BAD_PRESENCE);
-	result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t));
+	result = tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
 	assert(result == TPM_BAD_PRESENCE);
 
 	printf("done\n");
@@ -350,38 +357,39 @@
 #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
 #define PERMPP TPM_NV_PER_PPWRITE
 
-static int test_space_perm(void)
+static int test_space_perm(struct udevice *dev)
 {
 	uint32_t perm;
 
 	printf("Testing spaceperm ...");
-	tpm_init();
-	TPM_CHECK(TlclStartupIfNeeded());
-	TPM_CHECK(tpm_continue_self_test());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_get_permissions(INDEX0, &perm));
+	tpm_init(dev);
+	TPM_CHECK(TlclStartupIfNeeded(dev));
+	TPM_CHECK(tpm_continue_self_test(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_get_permissions(dev, INDEX0, &perm));
 	assert((perm & PERMPPGL) == PERMPPGL);
-	TPM_CHECK(tpm_get_permissions(INDEX1, &perm));
+	TPM_CHECK(tpm_get_permissions(dev, INDEX1, &perm));
 	assert((perm & PERMPP) == PERMPP);
 	printf("done\n");
 	return 0;
 }
 
-static int test_startup(void)
+static int test_startup(struct udevice *dev)
 {
 	uint32_t result;
+
 	printf("Testing startup ...\n");
 
-	tpm_init();
-	result = tpm_startup(TPM_ST_CLEAR);
+	tpm_init(dev);
+	result = tpm_startup(dev, TPM_ST_CLEAR);
 	if (result != 0 && result != TPM_INVALID_POSTINIT)
 		printf("\ttpm startup failed with 0x%x\n", result);
-	result = tpm_get_flags(NULL, NULL, NULL);
+	result = tpm_get_flags(dev, NULL, NULL, NULL);
 	if (result != 0)
 		printf("\ttpm getflags failed with 0x%x\n", result);
 	printf("\texecuting SelfTestFull\n");
-	tpm_self_test_full();
-	result = tpm_get_flags(NULL, NULL, NULL);
+	tpm_self_test_full(dev);
+	result = tpm_get_flags(dev, NULL, NULL, NULL);
 	if (result != 0)
 		printf("\ttpm getflags failed with 0x%x\n", result);
 	printf("\tdone\n");
@@ -410,45 +418,48 @@
 } while (0)
 
 
-static int test_timing(void)
+static int test_timing(struct udevice *dev)
 {
-	uint32_t x;
 	uint8_t in[20], out[20];
+	uint32_t x;
 
 	printf("Testing timing ...");
-	tpm_init();
-	TTPM_CHECK(TlclStartupIfNeeded(), 50);
-	TTPM_CHECK(tpm_continue_self_test(), 100);
-	TTPM_CHECK(tpm_self_test_full(), 1000);
-	TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100);
-	TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
-	TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
-	TTPM_CHECK(tpm_extend(0, in, out), 200);
-	TTPM_CHECK(tpm_set_global_lock(), 50);
-	TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100);
+	tpm_init(dev);
+	TTPM_CHECK(TlclStartupIfNeeded(dev), 50);
+	TTPM_CHECK(tpm_continue_self_test(dev), 100);
+	TTPM_CHECK(tpm_self_test_full(dev), 1000);
+	TTPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE), 100);
+	TTPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
+		   100);
+	TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
+		   100);
+	TTPM_CHECK(tpm_extend(dev, 0, in, out), 200);
+	TTPM_CHECK(tpm_set_global_lock(dev), 50);
+	TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
 	printf("done\n");
 	return 0;
 }
 
 #define TPM_MAX_NV_WRITES_NOOWNER 64
 
-static int test_write_limit(void)
+static int test_write_limit(struct udevice *dev)
 {
-	printf("Testing writelimit ...\n");
-	int i;
 	uint32_t result;
+	int i;
 
-	tpm_init();
-	TPM_CHECK(TlclStartupIfNeeded());
-	TPM_CHECK(tpm_self_test_full());
-	TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
-	TPM_CHECK(tpm_force_clear());
-	TPM_CHECK(tpm_physical_enable());
-	TPM_CHECK(tpm_physical_set_deactivated(0));
+	printf("Testing writelimit ...\n");
+	tpm_init(dev);
+	TPM_CHECK(TlclStartupIfNeeded(dev));
+	TPM_CHECK(tpm_self_test_full(dev));
+	TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+	TPM_CHECK(tpm_force_clear(dev));
+	TPM_CHECK(tpm_physical_enable(dev));
+	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
 
 	for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
 		printf("\twriting %d\n", i);
-		result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i));
+		result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i,
+					    sizeof(i));
 		switch (result) {
 		case TPM_SUCCESS:
 			break;
@@ -461,12 +472,12 @@
 	}
 
 	/* Reset write count */
-	TPM_CHECK(tpm_force_clear());
-	TPM_CHECK(tpm_physical_enable());
-	TPM_CHECK(tpm_physical_set_deactivated(0));
+	TPM_CHECK(tpm_force_clear(dev));
+	TPM_CHECK(tpm_physical_enable(dev));
+	TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
 
 	/* Try writing again. */
-	TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)));
+	TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i, sizeof(i)));
 	printf("\tdone\n");
 	return 0;
 }
@@ -475,7 +486,13 @@
 	int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
 	char * const argv[]) \
 	{ \
-		return test_##XFUNC(); \
+		struct udevice *dev; \
+		int ret; \
+\
+		ret = get_tpm(&dev); \
+		if (ret) \
+			return ret; \
+		return test_##XFUNC(dev); \
 	}
 
 #define VOIDENT(XNAME) \
diff --git a/common/malloc_simple.c b/common/malloc_simple.c
index 871b544..eabbb70 100644
--- a/common/malloc_simple.c
+++ b/common/malloc_simple.c
@@ -5,6 +5,8 @@
  * Copyright (c) 2014 Google, Inc
  */
 
+#define LOG_CATEGORY LOGC_ALLOC
+
 #include <common.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -12,40 +14,47 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-void *malloc_simple(size_t bytes)
+static void *alloc_simple(size_t bytes, int align)
 {
-	ulong new_ptr;
+	ulong addr, new_ptr;
 	void *ptr;
 
-	new_ptr = gd->malloc_ptr + bytes;
-	debug("%s: size=%zx, ptr=%lx, limit=%lx: ", __func__, bytes, new_ptr,
-	      gd->malloc_limit);
+	addr = ALIGN(gd->malloc_base + gd->malloc_ptr, align);
+	new_ptr = addr + bytes - gd->malloc_base;
+	log_debug("size=%zx, ptr=%lx, limit=%lx: ", bytes, new_ptr,
+		  gd->malloc_limit);
 	if (new_ptr > gd->malloc_limit) {
-		debug("space exhausted\n");
+		log_err("alloc space exhausted\n");
 		return NULL;
 	}
-	ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
+
+	ptr = map_sysmem(addr, bytes);
 	gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
-	debug("%lx\n", (ulong)ptr);
 
 	return ptr;
 }
 
-void *memalign_simple(size_t align, size_t bytes)
+void *malloc_simple(size_t bytes)
 {
-	ulong addr, new_ptr;
 	void *ptr;
 
-	addr = ALIGN(gd->malloc_base + gd->malloc_ptr, align);
-	new_ptr = addr + bytes - gd->malloc_base;
-	if (new_ptr > gd->malloc_limit) {
-		debug("space exhausted\n");
-		return NULL;
-	}
+	ptr = alloc_simple(bytes, 1);
+	if (!ptr)
+		return ptr;
 
-	ptr = map_sysmem(addr, bytes);
-	gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
-	debug("%lx\n", (ulong)ptr);
+	log_debug("%lx\n", (ulong)ptr);
+
+	return ptr;
+}
+
+void *memalign_simple(size_t align, size_t bytes)
+{
+	void *ptr;
+
+	ptr = alloc_simple(bytes, align);
+	if (!ptr)
+		return ptr;
+	log_debug("aligned to %lx\n", (ulong)ptr);
 
 	return ptr;
 }
@@ -57,9 +66,16 @@
 	void *ptr;
 
 	ptr = malloc(size);
-	if (ptr)
-		memset(ptr, '\0', size);
+	if (!ptr)
+		return ptr;
+	memset(ptr, '\0', size);
 
 	return ptr;
 }
 #endif
+
+void malloc_simple_info(void)
+{
+	log_info("malloc_simple: %lx bytes used, %lx remain\n", gd->malloc_ptr,
+		 CONFIG_VAL(SYS_MALLOC_F_LEN) - gd->malloc_ptr);
+}
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 47a697f..836bcad 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -699,6 +699,40 @@
 	return -ENODEV;
 }
 
+int device_find_first_child_by_uclass(struct udevice *parent,
+				      enum uclass_id uclass_id,
+				      struct udevice **devp)
+{
+	struct udevice *dev;
+
+	*devp = NULL;
+	list_for_each_entry(dev, &parent->child_head, sibling_node) {
+		if (device_get_uclass_id(dev) == uclass_id) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+int device_find_child_by_name(struct udevice *parent, const char *name,
+			      struct udevice **devp)
+{
+	struct udevice *dev;
+
+	*devp = NULL;
+
+	list_for_each_entry(dev, &parent->child_head, sibling_node) {
+		if (!strcmp(dev->name, name)) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
 struct udevice *dev_get_parent(const struct udevice *child)
 {
 	return child->parent;
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index d9b5280..0e584c1 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -253,15 +253,15 @@
 
 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
 {
+	int na, ns;
+	fdt_size_t size;
+
 	if (ofnode_is_np(node)) {
 		const __be32 *prop_val;
 		uint flags;
-		u64 size;
-		int na;
-		int ns;
 
-		prop_val = of_get_address(ofnode_to_np(node), index, &size,
-					  &flags);
+		prop_val = of_get_address(ofnode_to_np(node), index,
+					  (u64 *)&size, &flags);
 		if (!prop_val)
 			return FDT_ADDR_T_NONE;
 
@@ -274,8 +274,11 @@
 			return of_read_number(prop_val, na);
 		}
 	} else {
-		return fdt_get_base_address(gd->fdt_blob,
-					    ofnode_to_offset(node));
+		na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
+		ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
+		return fdtdec_get_addr_size_fixed(gd->fdt_blob,
+						  ofnode_to_offset(node), "reg",
+						  index, na, ns, &size, true);
 	}
 
 	return FDT_ADDR_T_NONE;
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index d9c5719..9766aea 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -354,10 +354,8 @@
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
-static int uclass_find_device_by_phandle(enum uclass_id id,
-					 struct udevice *parent,
-					 const char *name,
-					 struct udevice **devp)
+int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
+				  const char *name, struct udevice **devp)
 {
 	struct udevice *dev;
 	struct uclass *uc;
diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c
index a2bdd5a..ae5aae0 100644
--- a/drivers/i2c/i2c-emul-uclass.c
+++ b/drivers/i2c/i2c-emul-uclass.c
@@ -6,8 +6,85 @@
 #include <common.h>
 #include <dm.h>
 #include <i2c.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/*
+ * i2c emulation works using an 'emul' node at the bus level. Each device in
+ * that node is in the UCLASS_I2C_EMUL uclass, and emulates one i2c device. A
+ * pointer to the device it emulates is in the 'dev' property of the emul device
+ * uclass platdata (struct i2c_emul_platdata), put there by i2c_emul_find().
+ * When sandbox wants an emulator for a device, it calls i2c_emul_find() which
+ * searches for the emulator with the correct address. To find the device for an
+ * emulator, call i2c_emul_get_device().
+ *
+ * The 'emul' node is in the UCLASS_I2C_EMUL_PARENT uclass. We use a separate
+ * uclass so avoid having strange devices on the I2C bus.
+ */
+
+/**
+ * struct i2c_emul_uc_platdata - information about the emulator for this device
+ *
+ * This is used by devices in UCLASS_I2C_EMUL to record information about the
+ * device being emulated. It is accessible with dev_get_uclass_platdata()
+ *
+ * @dev: Device being emulated
+ */
+struct i2c_emul_uc_platdata {
+	struct udevice *dev;
+};
+
+struct udevice *i2c_emul_get_device(struct udevice *emul)
+{
+	struct i2c_emul_uc_platdata *uc_plat = dev_get_uclass_platdata(emul);
+
+	return uc_plat->dev;
+}
+
+int i2c_emul_find(struct udevice *dev, struct udevice **emulp)
+{
+	struct i2c_emul_uc_platdata *uc_plat;
+	struct udevice *emul;
+	int ret;
+
+	ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev,
+					    "sandbox,emul", &emul);
+	if (ret) {
+		log_err("No emulators for device '%s'\n", dev->name);
+		return ret;
+	}
+	uc_plat = dev_get_uclass_platdata(emul);
+	uc_plat->dev = dev;
+	*emulp = emul;
+
+	return device_probe(emul);
+}
 
 UCLASS_DRIVER(i2c_emul) = {
 	.id		= UCLASS_I2C_EMUL,
 	.name		= "i2c_emul",
+	.per_device_platdata_auto_alloc_size =
+		 sizeof(struct i2c_emul_uc_platdata),
+};
+
+/*
+ * This uclass is a child of the i2c bus. Its platdata is not defined here so
+ * is defined by its parent, UCLASS_I2C, which uses struct dm_i2c_chip. See
+ * per_child_platdata_auto_alloc_size in UCLASS_DRIVER(i2c).
+ */
+UCLASS_DRIVER(i2c_emul_parent) = {
+	.id		= UCLASS_I2C_EMUL_PARENT,
+	.name		= "i2c_emul_parent",
+	.post_bind	= dm_scan_fdt_dev,
+};
+
+static const struct udevice_id i2c_emul_parent_ids[] = {
+	{ .compatible = "sandbox,i2c-emul-parent" },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_emul_parent_drv) = {
+	.name		= "i2c_emul_parent_drv",
+	.id		= UCLASS_I2C_EMUL_PARENT,
+	.of_match	= i2c_emul_parent_ids,
 };
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index 6657851..0dbbaa0 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -21,33 +21,15 @@
 		    struct dm_i2c_ops **opsp)
 {
 	struct dm_i2c_chip *plat;
-	struct udevice *child;
 	int ret;
 
 	*devp = NULL;
 	*opsp = NULL;
 	plat = dev_get_parent_platdata(dev);
 	if (!plat->emul) {
-		ret = dm_scan_fdt_dev(dev);
+		ret = i2c_emul_find(dev, &plat->emul);
 		if (ret)
 			return ret;
-
-		for (device_find_first_child(dev, &child); child;
-		     device_find_next_child(&child)) {
-			if (device_get_uclass_id(child) != UCLASS_I2C_EMUL)
-				continue;
-
-			ret = device_probe(child);
-			if (ret)
-				return ret;
-
-			break;
-		}
-
-		if (child)
-			plat->emul = child;
-		else
-			return -ENODEV;
 	}
 	*devp = plat->emul;
 	*opsp = i2c_get_ops(plat->emul);
diff --git a/drivers/power/pmic/act8846.c b/drivers/power/pmic/act8846.c
index b0c759c..186fa90 100644
--- a/drivers/power/pmic/act8846.c
+++ b/drivers/power/pmic/act8846.c
@@ -50,7 +50,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/as3722.c b/drivers/power/pmic/as3722.c
index 63df613..54adcbf 100644
--- a/drivers/power/pmic/as3722.c
+++ b/drivers/power/pmic/as3722.c
@@ -45,14 +45,14 @@
 
 	ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
 	if (ret < 0) {
-		pr_err("failed to read ID1 register: %d", ret);
+		pr_err("failed to read ID1 register: %d\n", ret);
 		return ret;
 	}
 	*idp = ret;
 
 	ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
 	if (ret < 0) {
-		pr_err("failed to read ID2 register: %d", ret);
+		pr_err("failed to read ID2 register: %d\n", ret);
 		return ret;
 	}
 	*revisionp = ret;
@@ -70,7 +70,7 @@
 
 	ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
 	if (ret < 0) {
-		pr_err("failed to write SD%u voltage register: %d", sd, ret);
+		pr_err("failed to write SD%u voltage register: %d\n", sd, ret);
 		return ret;
 	}
 
@@ -86,8 +86,8 @@
 
 	ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
 	if (ret < 0) {
-		pr_err("failed to write LDO%u voltage register: %d", ldo,
-		      ret);
+		pr_err("failed to write LDO%u voltage register: %d\n", ldo,
+		       ret);
 		return ret;
 	}
 
@@ -101,12 +101,12 @@
 
 	ret = as3722_read_id(dev, &id, &revision);
 	if (ret < 0) {
-		pr_err("failed to read ID: %d", ret);
+		pr_err("failed to read ID: %d\n", ret);
 		return ret;
 	}
 
 	if (id != AS3722_DEVICE_ID) {
-		pr_err("unknown device");
+		pr_err("unknown device\n");
 		return -ENOENT;
 	}
 
diff --git a/drivers/power/pmic/as3722_gpio.c b/drivers/power/pmic/as3722_gpio.c
index 36f4fbf..96943bc 100644
--- a/drivers/power/pmic/as3722_gpio.c
+++ b/drivers/power/pmic/as3722_gpio.c
@@ -25,7 +25,7 @@
 
 	err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
 	if (err) {
-		pr_err("failed to configure GPIO#%u: %d", gpio, err);
+		pr_err("failed to configure GPIO#%u: %d\n", gpio, err);
 		return err;
 	}
 
@@ -45,7 +45,7 @@
 
 	err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
 	if (err < 0) {
-		pr_err("failed to read GPIO signal out register: %d", err);
+		pr_err("failed to read GPIO signal out register: %d\n", err);
 		return err;
 	}
 	value = err;
@@ -60,7 +60,7 @@
 
 	err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
 	if (err) {
-		pr_err("failed to set GPIO#%u %s: %d", gpio, l, err);
+		pr_err("failed to set GPIO#%u %s: %d\n", gpio, l, err);
 		return err;
 	}
 
@@ -83,13 +83,14 @@
 
 	err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
 	if (err) {
-		pr_err("failed to configure GPIO#%u as output: %d", gpio, err);
+		pr_err("failed to configure GPIO#%u as output: %d\n", gpio,
+		       err);
 		return err;
 	}
 
 	err = as3722_gpio_set_value(pmic, gpio, value);
 	if (err < 0) {
-		pr_err("failed to set GPIO#%u high: %d", gpio, err);
+		pr_err("failed to set GPIO#%u high: %d\n", gpio, err);
 		return err;
 	}
 
diff --git a/drivers/power/pmic/i2c_pmic_emul.c b/drivers/power/pmic/i2c_pmic_emul.c
index 61fa76a..80efc02 100644
--- a/drivers/power/pmic/i2c_pmic_emul.c
+++ b/drivers/power/pmic/i2c_pmic_emul.c
@@ -104,7 +104,7 @@
 static int sandbox_i2c_pmic_ofdata_to_platdata(struct udevice *emul)
 {
 	struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
-	struct udevice *pmic_dev = dev_get_parent(emul);
+	struct udevice *pmic_dev = i2c_emul_get_device(emul);
 	struct uc_pmic_priv *priv = dev_get_uclass_priv(pmic_dev);
 	const u8 *reg_defaults;
 
diff --git a/drivers/power/pmic/lp873x.c b/drivers/power/pmic/lp873x.c
index 432ad4c..4ae4043 100644
--- a/drivers/power/pmic/lp873x.c
+++ b/drivers/power/pmic/lp873x.c
@@ -24,7 +24,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -34,7 +34,7 @@
 static int lp873x_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -48,7 +48,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/lp87565.c b/drivers/power/pmic/lp87565.c
index 450dbb8..3e5fc60 100644
--- a/drivers/power/pmic/lp87565.c
+++ b/drivers/power/pmic/lp87565.c
@@ -26,7 +26,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -37,7 +37,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -49,7 +49,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/max77686.c b/drivers/power/pmic/max77686.c
index 834713a..8e3a8cf 100644
--- a/drivers/power/pmic/max77686.c
+++ b/drivers/power/pmic/max77686.c
@@ -28,7 +28,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -38,7 +38,7 @@
 static int max77686_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -52,8 +52,8 @@
 
 	regulators_node = dev_read_subnode(dev, "voltage-regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
-							     dev->name);
+		debug("%s: %s regulators subnode not found!\n", __func__,
+		      dev->name);
 		return -ENXIO;
 	}
 
diff --git a/drivers/power/pmic/max8997.c b/drivers/power/pmic/max8997.c
index 0dcdbad..dbae155 100644
--- a/drivers/power/pmic/max8997.c
+++ b/drivers/power/pmic/max8997.c
@@ -23,7 +23,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -34,7 +34,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
diff --git a/drivers/power/pmic/max8998.c b/drivers/power/pmic/max8998.c
index f571add..f58d9f2 100644
--- a/drivers/power/pmic/max8998.c
+++ b/drivers/power/pmic/max8998.c
@@ -23,7 +23,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -34,7 +34,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
diff --git a/drivers/power/pmic/mc34708.c b/drivers/power/pmic/mc34708.c
index 2b2fc72..66253a4 100644
--- a/drivers/power/pmic/mc34708.c
+++ b/drivers/power/pmic/mc34708.c
@@ -38,7 +38,7 @@
 
 	ret = dm_i2c_write(dev, reg, buf, len);
 	if (ret)
-		printf("write error to device: %p register: %#x!", dev, reg);
+		printf("write error to device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -53,7 +53,7 @@
 
 	ret = dm_i2c_read(dev, reg, buf, len);
 	if (ret)
-		printf("read error from device: %p register: %#x!", dev, reg);
+		printf("read error from device: %p register: %#x!\n", dev, reg);
 
 	buff[0] = buf[2];
 	buff[1] = buf[1];
diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c
index 250a5d3..36be119 100644
--- a/drivers/power/pmic/palmas.c
+++ b/drivers/power/pmic/palmas.c
@@ -24,7 +24,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -34,7 +34,7 @@
 static int palmas_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -60,14 +60,14 @@
 	}
 
 	if (!ofnode_valid(pmic_node)) {
-		debug("%s: %s pmic subnode not found!", __func__, dev->name);
+		debug("%s: %s pmic subnode not found!\n", __func__, dev->name);
 		return -ENXIO;
 	}
 
 	regulators_node = ofnode_find_subnode(pmic_node, "regulators");
 
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s reg subnode not found!", __func__, dev->name);
+		debug("%s: %s reg subnode not found!\n", __func__, dev->name);
 		return -ENXIO;
 	}
 
diff --git a/drivers/power/pmic/pfuze100.c b/drivers/power/pmic/pfuze100.c
index 8a5a899..6cf5f35 100644
--- a/drivers/power/pmic/pfuze100.c
+++ b/drivers/power/pmic/pfuze100.c
@@ -31,7 +31,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -41,7 +41,7 @@
 static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -55,7 +55,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index c60dfff..25c339a 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -29,7 +29,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret) {
-		debug("write error to device: %p register: %#x!", dev, reg);
+		debug("write error to device: %p register: %#x!\n", dev, reg);
 		return ret;
 	}
 
@@ -42,7 +42,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret) {
-		debug("read error from device: %p register: %#x!", dev, reg);
+		debug("read error from device: %p register: %#x!\n", dev, reg);
 		return ret;
 	}
 
@@ -57,7 +57,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/rn5t567.c b/drivers/power/pmic/rn5t567.c
index c3be3fe..f238396 100644
--- a/drivers/power/pmic/rn5t567.c
+++ b/drivers/power/pmic/rn5t567.c
@@ -24,7 +24,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret) {
-		debug("write error to device: %p register: %#x!", dev, reg);
+		debug("write error to device: %p register: %#x!\n", dev, reg);
 		return ret;
 	}
 
@@ -37,7 +37,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret) {
-		debug("read error from device: %p register: %#x!", dev, reg);
+		debug("read error from device: %p register: %#x!\n", dev, reg);
 		return ret;
 	}
 
diff --git a/drivers/power/pmic/s2mps11.c b/drivers/power/pmic/s2mps11.c
index e45d4bc..f2aab6c 100644
--- a/drivers/power/pmic/s2mps11.c
+++ b/drivers/power/pmic/s2mps11.c
@@ -30,7 +30,7 @@
 
 	ret = dm_i2c_write(dev, reg, buff, len);
 	if (ret)
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -41,7 +41,7 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret)
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 
 	return ret;
 }
@@ -53,8 +53,8 @@
 
 	regulators_node = dev_read_subnode(dev, "voltage-regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
-							     dev->name);
+		debug("%s: %s regulators subnode not found!\n", __func__,
+		      dev->name);
 		return -ENXIO;
 	}
 
diff --git a/drivers/power/pmic/s5m8767.c b/drivers/power/pmic/s5m8767.c
index 54e44ce..b5ddd49 100644
--- a/drivers/power/pmic/s5m8767.c
+++ b/drivers/power/pmic/s5m8767.c
@@ -27,7 +27,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -37,7 +37,7 @@
 static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -56,7 +56,7 @@
 
 	node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/power/pmic/sandbox.c b/drivers/power/pmic/sandbox.c
index 64e2f27..d787091 100644
--- a/drivers/power/pmic/sandbox.c
+++ b/drivers/power/pmic/sandbox.c
@@ -28,7 +28,7 @@
 			      const uint8_t *buff, int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -39,7 +39,7 @@
 			     uint8_t *buff, int len)
 {
 	if (dm_i2c_read(dev, reg, buff, len)) {
-		pr_err("read error from device: %p register: %#x!", dev, reg);
+		pr_err("read error from device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
diff --git a/drivers/power/pmic/stpmu1.c b/drivers/power/pmic/stpmu1.c
index 82351b6..47af012 100644
--- a/drivers/power/pmic/stpmu1.c
+++ b/drivers/power/pmic/stpmu1.c
@@ -61,7 +61,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		dev_dbg(dev, "regulators subnode not found!");
+		dev_dbg(dev, "regulators subnode not found!\n");
 		return -ENXIO;
 	}
 	dev_dbg(dev, "found regulators subnode\n");
diff --git a/drivers/power/pmic/tps65090.c b/drivers/power/pmic/tps65090.c
index 1d3bf00..5b1d19f 100644
--- a/drivers/power/pmic/tps65090.c
+++ b/drivers/power/pmic/tps65090.c
@@ -26,7 +26,7 @@
 			  int len)
 {
 	if (dm_i2c_write(dev, reg, buff, len)) {
-		pr_err("write error to device: %p register: %#x!", dev, reg);
+		pr_err("write error to device: %p register: %#x!\n", dev, reg);
 		return -EIO;
 	}
 
@@ -39,8 +39,8 @@
 
 	ret = dm_i2c_read(dev, reg, buff, len);
 	if (ret) {
-		pr_err("read error %d from device: %p register: %#x!", ret, dev,
-		      reg);
+		pr_err("read error %d from device: %p register: %#x!\n", ret,
+		       dev, reg);
 		return -EIO;
 	}
 
@@ -54,7 +54,7 @@
 
 	regulators_node = dev_read_subnode(dev, "regulators");
 	if (!ofnode_valid(regulators_node)) {
-		debug("%s: %s regulators subnode not found!", __func__,
+		debug("%s: %s regulators subnode not found!\n", __func__,
 		      dev->name);
 		return -ENXIO;
 	}
diff --git a/drivers/rtc/rtc-uclass.c b/drivers/rtc/rtc-uclass.c
index c676f0f..a0a238a 100644
--- a/drivers/rtc/rtc-uclass.c
+++ b/drivers/rtc/rtc-uclass.c
@@ -122,4 +122,5 @@
 UCLASS_DRIVER(rtc) = {
 	.name		= "rtc",
 	.id		= UCLASS_RTC,
+	.post_bind	= dm_scan_fdt_dev,
 };
diff --git a/drivers/sound/sound-i2s.c b/drivers/sound/sound-i2s.c
index 9f09e3b..f0f0b79 100644
--- a/drivers/sound/sound-i2s.c
+++ b/drivers/sound/sound-i2s.c
@@ -185,7 +185,8 @@
 		return -1;
 	}
 
-	sound_create_square_wave((unsigned short *)data,
+	sound_create_square_wave(g_i2stx_pri.samplingrate,
+				 (unsigned short *)data,
 				 data_size / sizeof(unsigned short),
 				 frequency);
 
diff --git a/drivers/sound/sound.c b/drivers/sound/sound.c
index 9694081..4f0ad0d 100644
--- a/drivers/sound/sound.c
+++ b/drivers/sound/sound.c
@@ -7,11 +7,11 @@
 #include <common.h>
 #include <sound.h>
 
-void sound_create_square_wave(unsigned short *data, int size, uint32_t freq)
+void sound_create_square_wave(uint sample_rate, unsigned short *data, int size,
+			      uint freq)
 {
-	const int sample = 48000;
 	const unsigned short amplitude = 16000; /* between 1 and 32767 */
-	const int period = freq ? sample / freq : 0;
+	const int period = freq ? sample_rate / freq : 0;
 	const int half = period / 2;
 
 	assert(freq);
@@ -25,12 +25,10 @@
 		for (i = 0; size && i < half; i++) {
 			size -= 2;
 			*data++ = amplitude;
-			*data++ = amplitude;
 		}
 		for (i = 0; size && i < period - half; i++) {
 			size -= 2;
 			*data++ = -amplitude;
-			*data++ = -amplitude;
 		}
 	}
 }
diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c
index e993fd9..30194bc 100644
--- a/drivers/tpm/tpm_tis_lpc.c
+++ b/drivers/tpm/tpm_tis_lpc.c
@@ -388,6 +388,27 @@
 	return offset;
 }
 
+static int tpm_tis_lpc_close(struct udevice *dev)
+{
+	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
+	struct tpm_locality *regs = priv->regs;
+	u8 locality = 0;
+
+	if (tpm_read_word(priv, &regs[locality].access) &
+	    TIS_ACCESS_ACTIVE_LOCALITY) {
+		tpm_write_word(priv, TIS_ACCESS_ACTIVE_LOCALITY,
+			       &regs[locality].access);
+
+		if (tis_wait_reg(priv, &regs[locality].access,
+				 TIS_ACCESS_ACTIVE_LOCALITY, 0) == -ETIMEDOUT) {
+			printf("%s:%d - failed to release locality %d\n",
+			       __FILE__, __LINE__, locality);
+			return -ETIMEDOUT;
+		}
+	}
+	return 0;
+}
+
 static int tpm_tis_lpc_open(struct udevice *dev)
 {
 	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
@@ -395,6 +416,12 @@
 	u8 locality = 0; /* we use locality zero for everything. */
 	int ret;
 
+	ret = tpm_tis_lpc_close(dev);
+	if (ret) {
+		printf("%s: Failed to close TPM\n", __func__);
+		return ret;
+	}
+
 	/* now request access to locality. */
 	tpm_write_word(priv, TIS_ACCESS_REQUEST_USE, &regs[locality].access);
 
@@ -410,27 +437,7 @@
 
 	tpm_write_word(priv, TIS_STS_COMMAND_READY,
 		       &regs[locality].tpm_status);
-	return 0;
-}
-
-static int tpm_tis_lpc_close(struct udevice *dev)
-{
-	struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
-	struct tpm_locality *regs = priv->regs;
-	u8 locality = 0;
-
-	if (tpm_read_word(priv, &regs[locality].access) &
-	    TIS_ACCESS_ACTIVE_LOCALITY) {
-		tpm_write_word(priv, TIS_ACCESS_ACTIVE_LOCALITY,
-			       &regs[locality].access);
 
-		if (tis_wait_reg(priv, &regs[locality].access,
-				 TIS_ACCESS_ACTIVE_LOCALITY, 0) == -ETIMEDOUT) {
-			printf("%s:%d - failed to release locality %d\n",
-			       __FILE__, __LINE__, locality);
-			return -ETIMEDOUT;
-		}
-	}
 	return 0;
 }
 
diff --git a/include/dm/device.h b/include/dm/device.h
index 8479344..27a6d7b 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -525,6 +525,8 @@
  * This is used to locate an existing child of a device which is of a given
  * uclass.
  *
+ * The device is NOT probed
+ *
  * @parent:	Parent device to search
  * @uclass_id:	Uclass to look for
  * @devp:	Returns device found, if any
@@ -535,6 +537,29 @@
 				     struct udevice **devp);
 
 /**
+ * device_find_first_child_by_uclass() - Find the first child of a device in uc
+ *
+ * @parent: Parent device to search
+ * @uclass_id:	Uclass to look for
+ * @devp: Returns first child device in that uclass, if any
+ * @return 0 if found, else -ENODEV
+ */
+int device_find_first_child_by_uclass(struct udevice *parent,
+				      enum uclass_id uclass_id,
+				      struct udevice **devp);
+
+/**
+ * device_find_child_by_name() - Find a child by device name
+ *
+ * @parent:	Parent device to search
+ * @name:	Name to look for
+ * @devp:	Returns device found, if any
+ * @return 0 if found, else -ENODEV
+ */
+int device_find_child_by_name(struct udevice *parent, const char *name,
+			      struct udevice **devp);
+
+/**
  * device_has_children() - check if a device has any children
  *
  * @dev:	Device to check
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 92539b8..d206ee2 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -333,7 +333,7 @@
  * ofnode_get_name() - get the name of a node
  *
  * @node: valid node to look up
- * @return name or node
+ * @return name of node
  */
 const char *ofnode_get_name(ofnode node);
 
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index c91dca1..a5fcb69 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -21,10 +21,10 @@
 	UCLASS_TEST_DUMMY,
 	UCLASS_SPI_EMUL,	/* sandbox SPI device emulator */
 	UCLASS_I2C_EMUL,	/* sandbox I2C device emulator */
+	UCLASS_I2C_EMUL_PARENT,	/* parent for I2C device emulators */
 	UCLASS_PCI_EMUL,	/* sandbox PCI device emulator */
 	UCLASS_USB_EMUL,	/* sandbox USB bus device emulator */
 	UCLASS_AXI_EMUL,	/* sandbox AXI bus device emulator */
-	UCLASS_SIMPLE_BUS,	/* bus with child devices */
 
 	/* U-Boot uclasses start here - in alphabetical order */
 	UCLASS_ADC,		/* Analog-to-digital converter */
@@ -78,6 +78,7 @@
 	UCLASS_RTC,		/* Real time clock device */
 	UCLASS_SCSI,		/* SCSI device */
 	UCLASS_SERIAL,		/* Serial UART */
+	UCLASS_SIMPLE_BUS,	/* Bus with child devices */
 	UCLASS_SMEM,		/* Shared memory interface */
 	UCLASS_SPI,		/* SPI bus */
 	UCLASS_SPMI,		/* System Power Management Interface bus */
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index 30d5a4f..8a4839e 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -143,6 +143,23 @@
 				 struct udevice **devp);
 
 /**
+ * uclass_find_device_by_phandle() - Find a uclass device by phandle
+ *
+ * This searches the devices in the uclass for one with the given phandle.
+ *
+ * The device is NOT probed, it is merely returned.
+ *
+ * @id: ID to look up
+ * @parent: Parent device containing the phandle pointer
+ * @name: Name of property in the parent device node
+ * @devp: Returns pointer to device (there is only one for each node)
+ * @return 0 if OK, -ENOENT if there is no @name present in the node, other
+ *	-ve on error
+ */
+int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
+				  const char *name, struct udevice **devp);
+
+/**
  * uclass_bind_device() - Associate device with a uclass
  *
  * Connect the device into uclass's list of devices.
diff --git a/include/i2c.h b/include/i2c.h
index d33f827..ccffc19 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -536,6 +536,27 @@
  */
 void i2c_dump_msgs(struct i2c_msg *msg, int nmsgs);
 
+/**
+ * i2c_emul_find() - Find an emulator for an i2c sandbox device
+ *
+ * This looks at the device's 'emul' phandle
+ *
+ * @dev: Device to find an emulator for
+ * @emulp: Returns the associated emulator, if found *
+ * @return 0 if OK, -ENOENT or -ENODEV if not found
+ */
+int i2c_emul_find(struct udevice *dev, struct udevice **emulp);
+
+/**
+ * i2c_emul_get_device() - Find the device being emulated
+ *
+ * Given an emulator this returns the associated device
+ *
+ * @emul: Emulator for the device
+ * @return device that @emul is emulating
+ */
+struct udevice *i2c_emul_get_device(struct udevice *emul);
+
 #ifndef CONFIG_DM_I2C
 
 /*
diff --git a/include/log.h b/include/log.h
index c88a1b5..0f2bc19 100644
--- a/include/log.h
+++ b/include/log.h
@@ -114,7 +114,7 @@
 /* Emit a log record if the level is less that the maximum */
 #define log(_cat, _level, _fmt, _args...) ({ \
 	int _l = _level; \
-	if (_l <= _LOG_MAX_LEVEL) \
+	if (CONFIG_IS_ENABLED(LOG) && _l <= _LOG_MAX_LEVEL) \
 		_log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \
 		      __func__, \
 		      pr_fmt(_fmt), ##_args); \
diff --git a/include/malloc.h b/include/malloc.h
index 8175c75..b714fed 100644
--- a/include/malloc.h
+++ b/include/malloc.h
@@ -880,6 +880,7 @@
 void *calloc(size_t nmemb, size_t size);
 void *memalign_simple(size_t alignment, size_t bytes);
 void *realloc_simple(void *ptr, size_t size);
+void malloc_simple_info(void);
 #else
 
 # ifdef USE_DL_PREFIX
diff --git a/include/sound.h b/include/sound.h
index 3269f23..77bfe6a 100644
--- a/include/sound.h
+++ b/include/sound.h
@@ -31,11 +31,13 @@
 /*
  * Generates square wave sound data for 1 second
  *
+ * @param sample_rate   Sample rate in Hz
  * @param data          data buffer pointer
  * @param size          size of the buffer
  * @param freq          frequency of the wave
  */
-void sound_create_square_wave(unsigned short *data, int size, uint32_t freq);
+void sound_create_square_wave(uint sample_rate, unsigned short *data, int size,
+			      uint freq);
 
 /*
  * Initialises audio sub system
diff --git a/include/tpm-common.h b/include/tpm-common.h
index 5f8bc6b..3d88b44 100644
--- a/include/tpm-common.h
+++ b/include/tpm-common.h
@@ -26,6 +26,8 @@
 /* Max buffer size supported by our tpm */
 #define TPM_DEV_BUFSIZE		1260
 
+#define TPM_PCR_MINIMUM_DIGEST_SIZE 20
+
 /**
  * enum tpm_version - The version of the TPM stack to be used
  * @TPM_V1:		Use TPM v1.x stack
@@ -174,12 +176,40 @@
 int do_##cmd(cmd_tbl_t *cmdtp, int flag,		\
 	     int argc, char * const argv[])		\
 {							\
+	struct udevice *dev;				\
+	int rc;						\
+							\
+	rc = get_tpm(&dev);				\
+	if (rc)						\
+		return rc;				\
 	if (argc != 1)					\
 		return CMD_RET_USAGE;			\
-	return report_return_code(cmd());		\
+	return report_return_code(cmd(dev));		\
 }
 
 /**
+ * tpm_open() - Request access to locality 0 for the caller
+ *
+ * After all commands have been completed the caller is supposed to
+ * call tpm_close().
+ *
+ * @dev - TPM device
+ * Returns 0 on success, -ve on failure.
+ */
+int tpm_open(struct udevice *dev);
+
+/**
+ * tpm_close() - Close the current session
+ *
+ * Releasing the locked locality. Returns 0 on success, -ve 1 on
+ * failure (in case lock removal did not succeed).
+ *
+ * @dev - TPM device
+ * Returns 0 on success, -ve on failure.
+ */
+int tpm_close(struct udevice *dev);
+
+/**
  * tpm_get_desc() - Get a text description of the TPM
  *
  * @dev:	Device to check
@@ -202,6 +232,7 @@
  * Note that the outgoing data is inspected to determine command type
  * (ordinal) and a timeout is used for that command type.
  *
+ * @dev - TPM device
  * @sendbuf - buffer of the data to send
  * @send_size size of the data to send
  * @recvbuf - memory to save the response to
@@ -216,9 +247,10 @@
 /**
  * Initialize TPM device.  It must be called before any TPM commands.
  *
+ * @dev - TPM device
  * @return 0 on success, non-0 on error.
  */
-int tpm_init(void);
+int tpm_init(struct udevice *dev);
 
 /**
  * Retrieve the array containing all the v1 (resp. v2) commands.
diff --git a/include/tpm-v1.h b/include/tpm-v1.h
index be2eca9..45b7a48 100644
--- a/include/tpm-v1.h
+++ b/include/tpm-v1.h
@@ -282,64 +282,72 @@
 /**
  * Issue a TPM_Startup command.
  *
+ * @param dev		TPM device
  * @param mode		TPM startup mode
  * @return return code of the operation
  */
-u32 tpm_startup(enum tpm_startup_type mode);
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode);
 
 /**
  * Issue a TPM_SelfTestFull command.
  *
+ * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_self_test_full(void);
+u32 tpm_self_test_full(struct udevice *dev);
 
 /**
  * Issue a TPM_ContinueSelfTest command.
  *
+ * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_continue_self_test(void);
+u32 tpm_continue_self_test(struct udevice *dev);
 
 /**
  * Issue a TPM_NV_DefineSpace command.  The implementation is limited
  * to specify TPM_NV_ATTRIBUTES and size of the area.  The area index
  * could be one of the special value listed in enum tpm_nv_index.
  *
+ * @param dev		TPM device
  * @param index		index of the area
  * @param perm		TPM_NV_ATTRIBUTES of the area
  * @param size		size of the area
  * @return return code of the operation
  */
-u32 tpm_nv_define_space(u32 index, u32 perm, u32 size);
+u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size);
 
 /**
  * Issue a TPM_NV_ReadValue command.  This implementation is limited
  * to read the area from offset 0.  The area index could be one of
  * the special value listed in enum tpm_nv_index.
  *
+ * @param dev		TPM device
  * @param index		index of the area
  * @param data		output buffer of the area contents
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_nv_read_value(u32 index, void *data, u32 count);
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
 
 /**
  * Issue a TPM_NV_WriteValue command.  This implementation is limited
  * to write the area from offset 0.  The area index could be one of
  * the special value listed in enum tpm_nv_index.
  *
+ * @param dev		TPM device
  * @param index		index of the area
  * @param data		input buffer to be wrote to the area
  * @param length	length of data bytes of input buffer
  * @return return code of the operation
  */
-u32 tpm_nv_write_value(u32 index, const void *data, u32 length);
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+		       u32 length);
 
 /**
  * Issue a TPM_Extend command.
  *
+ * @param dev		TPM device
  * @param index		index of the PCR
  * @param in_digest	160-bit value representing the event to be
  *			recorded
@@ -347,69 +355,78 @@
  *			command
  * @return return code of the operation
  */
-u32 tpm_extend(u32 index, const void *in_digest, void *out_digest);
+u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
+	       void *out_digest);
 
 /**
  * Issue a TPM_PCRRead command.
  *
+ * @param dev		TPM device
  * @param index		index of the PCR
  * @param data		output buffer for contents of the named PCR
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_pcr_read(u32 index, void *data, size_t count);
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count);
 
 /**
  * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
  * is bit-wise OR'ed of flags listed in enum tpm_physical_presence.
  *
+ * @param dev		TPM device
  * @param presence	TPM physical presence flag
  * @return return code of the operation
  */
-u32 tpm_tsc_physical_presence(u16 presence);
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence);
 
 /**
  * Issue a TPM_ReadPubek command.
  *
+ * @param dev		TPM device
  * @param data		output buffer for the public endorsement key
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_read_pubek(void *data, size_t count);
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count);
 
 /**
  * Issue a TPM_ForceClear command.
  *
+ * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_force_clear(void);
+u32 tpm_force_clear(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalEnable command.
  *
+ * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_physical_enable(void);
+u32 tpm_physical_enable(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalDisable command.
  *
+ * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_physical_disable(void);
+u32 tpm_physical_disable(struct udevice *dev);
 
 /**
  * Issue a TPM_PhysicalSetDeactivated command.
  *
+ * @param dev		TPM device
  * @param state		boolean state of the deactivated flag
  * @return return code of the operation
  */
-u32 tpm_physical_set_deactivated(u8 state);
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state);
 
 /**
  * Issue a TPM_GetCapability command.  This implementation is limited
  * to query sub_cap index that is 4-byte wide.
  *
+ * @param dev		TPM device
  * @param cap_area	partition of capabilities
  * @param sub_cap	further definition of capability, which is
  *			limited to be 4-byte wide
@@ -417,15 +434,17 @@
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count);
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+		       void *cap, size_t count);
 
 /**
  * Issue a TPM_FlushSpecific command for a AUTH resource.
  *
+ * @param dev		TPM device
  * @param auth_handle	handle of the auth session
  * @return return code of the operation
  */
-u32 tpm_terminate_auth_session(u32 auth_handle);
+u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle);
 
 /**
  * Issue a TPM_OIAP command to setup an object independent authorization
@@ -434,22 +453,25 @@
  * If there was already an OIAP session active it is terminated and a new
  * session is set up.
  *
+ * @param dev		TPM device
  * @param auth_handle	pointer to the (new) auth handle or NULL.
  * @return return code of the operation
  */
-u32 tpm_oiap(u32 *auth_handle);
+u32 tpm_oiap(struct udevice *dev, u32 *auth_handle);
 
 /**
  * Ends an active OIAP session.
  *
+ * @param dev		TPM device
  * @return return code of the operation
  */
-u32 tpm_end_oiap(void);
+u32 tpm_end_oiap(struct udevice *dev);
 
 /**
  * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
  * the usage of the parent key.
  *
+ * @param dev		TPM device
  * @param parent_handle	handle of the parent key.
  * @param key		pointer to the key structure (TPM_KEY or TPM_KEY12).
  * @param key_length	size of the key structure
@@ -457,13 +479,15 @@
  * @param key_handle	pointer to the key handle
  * @return return code of the operation
  */
-u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
-		       const void *parent_key_usage_auth, u32 *key_handle);
+u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+		       size_t key_length, const void *parent_key_usage_auth,
+		       u32 *key_handle);
 
 /**
  * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
  * authenticating the usage of the key.
  *
+ * @param dev		TPM device
  * @param key_handle	handle of the key
  * @param usage_auth	usage auth for the key
  * @param pubkey	pointer to the pub key buffer; may be NULL if the pubkey
@@ -473,45 +497,51 @@
  *			of the stored TPM_PUBKEY structure (iff pubkey != NULL).
  * @return return code of the operation
  */
-u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
+u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+			 const void *usage_auth, void *pubkey,
 			 size_t *pubkey_len);
 
 /**
  * Get the TPM permanent flags value
  *
+ * @param dev		TPM device
  * @param pflags	Place to put permanent flags
  * @return return code of the operation
  */
-u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags);
+u32 tpm_get_permanent_flags(struct udevice *dev,
+			    struct tpm_permanent_flags *pflags);
 
 /**
  * Get the TPM permissions
  *
+ * @param dev		TPM device
  * @param perm		Returns permissions value
  * @return return code of the operation
  */
-u32 tpm_get_permissions(u32 index, u32 *perm);
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm);
 
 /**
  * Flush a resource with a given handle and type from the TPM
  *
+ * @param dev		TPM device
  * @param key_handle           handle of the resource
  * @param resource_type                type of the resource
  * @return return code of the operation
  */
-u32 tpm_flush_specific(u32 key_handle, u32 resource_type);
+u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type);
 
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
 /**
  * Search for a key by usage AuthData and the hash of the parent's pub key.
  *
+ * @param dev		TPM device
  * @param auth	        Usage auth of the key to search for
  * @param pubkey_digest	SHA1 hash of the pub key structure of the key
  * @param[out] handle	The handle of the key (Non-null iff found)
  * @return 0 if key was found in TPM; != 0 if not.
  */
-u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
-		      u32 *handle);
+u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
+		      const u8 pubkey_digest[20], u32 *handle);
 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
 
 /**
@@ -519,38 +549,43 @@
  * that the TPM may legally return fewer bytes than requested by retrying
  * until @p count bytes have been received.
  *
+ * @param dev		TPM device
  * @param data		output buffer for the random bytes
  * @param count		size of output buffer
  * @return return code of the operation
  */
-u32 tpm_get_random(void *data, u32 count);
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count);
 
 /**
  * tpm_finalise_physical_presence() - Finalise physical presence
  *
+ * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_finalise_physical_presence(void);
+u32 tpm_finalise_physical_presence(struct udevice *dev);
 
 /**
  * tpm_nv_set_locked() - lock the non-volatile space
  *
+ * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_nv_set_locked(void);
+u32 tpm_nv_set_locked(struct udevice *dev);
 
 /**
  * tpm_set_global_lock() - set the global lock
  *
+ * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_set_global_lock(void);
+u32 tpm_set_global_lock(struct udevice *dev);
 
 /**
  * tpm_resume() - start up the TPM from resume (after suspend)
  *
+ * @param dev		TPM device
  * @return return code of the operation (0 = success)
  */
-u32 tpm_resume(void);
+u32 tpm_resume(struct udevice *dev);
 
 #endif /* __TPM_V1_H */
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index c77b416..2f2e66d 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -131,45 +131,51 @@
 /**
  * Issue a TPM2_Startup command.
  *
+ * @dev		TPM device
  * @mode	TPM startup mode
  *
  * @return code of the operation
  */
-u32 tpm2_startup(enum tpm2_startup_types mode);
+u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode);
 
 /**
  * Issue a TPM2_SelfTest command.
  *
+ * @dev		TPM device
  * @full_test	Asking to perform all tests or only the untested ones
  *
  * @return code of the operation
  */
-u32 tpm2_self_test(enum tpm2_yes_no full_test);
+u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test);
 
 /**
  * Issue a TPM2_Clear command.
  *
+ * @dev		TPM device
  * @handle	Handle
  * @pw		Password
  * @pw_sz	Length of the password
  *
  * @return code of the operation
  */
-u32 tpm2_clear(u32 handle, const char *pw, const ssize_t pw_sz);
+u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
+	       const ssize_t pw_sz);
 
 /**
  * Issue a TPM2_PCR_Extend command.
  *
+ * @dev		TPM device
  * @index	Index of the PCR
  * @digest	Value representing the event to be recorded
  *
  * @return code of the operation
  */
-u32 tpm2_pcr_extend(u32 index, const uint8_t *digest);
+u32 tpm2_pcr_extend(struct udevice *dev, u32 index, const uint8_t *digest);
 
 /**
  * Issue a TPM2_PCR_Read command.
  *
+ * @dev		TPM device
  * @idx		Index of the PCR
  * @idx_min_sz	Minimum size in bytes of the pcrSelect array
  * @data	Output buffer for contents of the named PCR
@@ -177,13 +183,14 @@
  *
  * @return code of the operation
  */
-u32 tpm2_pcr_read(u32 idx, unsigned int idx_min_sz, void *data,
-		  unsigned int *updates);
+u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
+		  void *data, unsigned int *updates);
 
 /**
  * Issue a TPM2_GetCapability command.  This implementation is limited
  * to query property index that is 4-byte wide.
  *
+ * @dev		TPM device
  * @capability	Partition of capabilities
  * @property	Further definition of capability, limited to be 4 bytes wide
  * @buf		Output buffer for capability information
@@ -191,22 +198,24 @@
  *
  * @return code of the operation
  */
-u32 tpm2_get_capability(u32 capability, u32 property, void *buf,
-			size_t prop_count);
+u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
+			void *buf, size_t prop_count);
 
 /**
  * Issue a TPM2_DictionaryAttackLockReset command.
  *
+ * @dev		TPM device
  * @pw		Password
  * @pw_sz	Length of the password
  *
  * @return code of the operation
  */
-u32 tpm2_dam_reset(const char *pw, const ssize_t pw_sz);
+u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz);
 
 /**
  * Issue a TPM2_DictionaryAttackParameters command.
  *
+ * @dev		TPM device
  * @pw		Password
  * @pw_sz	Length of the password
  * @max_tries	Count of authorizations before lockout
@@ -215,13 +224,15 @@
  *
  * @return code of the operation
  */
-u32 tpm2_dam_parameters(const char *pw, const ssize_t pw_sz,
-			unsigned int max_tries, unsigned int recovery_time,
+u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
+			const ssize_t pw_sz, unsigned int max_tries,
+			unsigned int recovery_time,
 			unsigned int lockout_recovery);
 
 /**
  * Issue a TPM2_HierarchyChangeAuth command.
  *
+ * @dev		TPM device
  * @handle	Handle
  * @newpw	New password
  * @newpw_sz	Length of the new password
@@ -230,12 +241,14 @@
  *
  * @return code of the operation
  */
-int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz,
-		     const char *oldpw, const ssize_t oldpw_sz);
+int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
+		     const ssize_t newpw_sz, const char *oldpw,
+		     const ssize_t oldpw_sz);
 
 /**
  * Issue a TPM_PCR_SetAuthPolicy command.
  *
+ * @dev		TPM device
  * @pw		Platform password
  * @pw_sz	Length of the password
  * @index	Index of the PCR
@@ -243,12 +256,13 @@
  *
  * @return code of the operation
  */
-u32 tpm2_pcr_setauthpolicy(const char *pw, const ssize_t pw_sz, u32 index,
-			   const char *key);
+u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
+			   const ssize_t pw_sz, u32 index, const char *key);
 
 /**
  * Issue a TPM_PCR_SetAuthValue command.
  *
+ * @dev		TPM device
  * @pw		Platform password
  * @pw_sz	Length of the password
  * @index	Index of the PCR
@@ -257,7 +271,8 @@
  *
  * @return code of the operation
  */
-u32 tpm2_pcr_setauthvalue(const char *pw, const ssize_t pw_sz, u32 index,
-			  const char *key, const ssize_t key_sz);
+u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
+			  const ssize_t pw_sz, u32 index, const char *key,
+			  const ssize_t key_sz);
 
 #endif /* __TPM_V2_H */
diff --git a/lib/tpm-common.c b/lib/tpm-common.c
index a440639..6afe59b 100644
--- a/lib/tpm-common.c
+++ b/lib/tpm-common.c
@@ -151,9 +151,9 @@
 	return get_unaligned_be32(response + return_code_offset);
 }
 
-u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr)
+u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
+			 void *response, size_t *size_ptr)
 {
-	struct udevice *dev;
 	int err, ret;
 	u8 response_buffer[COMMAND_BUFFER_SIZE];
 	size_t response_length;
@@ -166,9 +166,6 @@
 		response_length = sizeof(response_buffer);
 	}
 
-	ret = uclass_first_device_err(UCLASS_TPM, &dev);
-	if (ret)
-		return ret;
 	err = tpm_xfer(dev, command, tpm_command_size(command),
 		       response, &response_length);
 
@@ -188,14 +185,7 @@
 	return ret;
 }
 
-int tpm_init(void)
+int tpm_init(struct udevice *dev)
 {
-	struct udevice *dev;
-	int err;
-
-	err = uclass_first_device_err(UCLASS_TPM, &dev);
-	if (err)
-		return err;
-
 	return tpm_open(dev);
 }
diff --git a/lib/tpm-utils.h b/lib/tpm-utils.h
index a9cb7dc..d680d14 100644
--- a/lib/tpm-utils.h
+++ b/lib/tpm-utils.h
@@ -19,24 +19,6 @@
 #define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
 
 /**
- * tpm_open() - Request access to locality 0 for the caller
- *
- * After all commands have been completed the caller is supposed to
- * call tpm_close().
- *
- * Returns 0 on success, -ve on failure.
- */
-int tpm_open(struct udevice *dev);
-
-/**
- * tpm_close() - Close the current session
- *
- * Releasing the locked locality. Returns 0 on success, -ve 1 on
- * failure (in case lock removal did not succeed).
- */
-int tpm_close(struct udevice *dev);
-
-/**
  * Pack data into a byte string.  The data types are specified in
  * the format string: 'b' means unsigned byte, 'w' unsigned word,
  * 'd' unsigned double word, and 's' byte string.  The data are a
@@ -96,6 +78,7 @@
  *			is a bidirectional
  * @return return code of the TPM response
  */
-u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr);
+u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
+			 void *response, size_t *size_ptr);
 
 #endif /* __TPM_UTILS_H */
diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
index 9d45c3d..f29e62f 100644
--- a/lib/tpm-v1.c
+++ b/lib/tpm-v1.c
@@ -31,7 +31,7 @@
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
-u32 tpm_startup(enum tpm_startup_type mode)
+u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
 {
 	const u8 command[12] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
@@ -44,49 +44,49 @@
 			     mode_offset, mode))
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(buf, NULL, NULL);
+	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_resume(void)
+u32 tpm_resume(struct udevice *dev)
 {
-	return tpm_startup(TPM_ST_STATE);
+	return tpm_startup(dev, TPM_ST_STATE);
 }
 
-u32 tpm_self_test_full(void)
+u32 tpm_self_test_full(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
 	};
-	return tpm_sendrecv_command(command, NULL, NULL);
+	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_continue_self_test(void)
+u32 tpm_continue_self_test(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
 	};
-	return tpm_sendrecv_command(command, NULL, NULL);
+	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_clear_and_reenable(void)
+u32 tpm_clear_and_reenable(struct udevice *dev)
 {
 	u32 ret;
 
 	log_info("TPM: Clear and re-enable\n");
-	ret = tpm_force_clear();
+	ret = tpm_force_clear(dev);
 	if (ret != TPM_SUCCESS) {
 		log_err("Can't initiate a force clear\n");
 		return ret;
 	}
 
 #if IS_ENABLED(CONFIG_TPM_V1)
-	ret = tpm_physical_enable();
+	ret = tpm_physical_enable(dev);
 	if (ret != TPM_SUCCESS) {
 		log_err("TPM: Can't set enabled state\n");
 		return ret;
 	}
 
-	ret = tpm_physical_set_deactivated(0);
+	ret = tpm_physical_set_deactivated(dev, 0);
 	if (ret != TPM_SUCCESS) {
 		log_err("TPM: Can't set deactivated state\n");
 		return ret;
@@ -96,7 +96,7 @@
 	return TPM_SUCCESS;
 }
 
-u32 tpm_nv_define_space(u32 index, u32 perm, u32 size)
+u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
 {
 	const u8 command[101] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -136,15 +136,15 @@
 			     size_offset, size))
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(buf, NULL, NULL);
+	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_nv_set_locked(void)
+u32 tpm_nv_set_locked(struct udevice *dev)
 {
-	return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
+	return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
 }
 
-u32 tpm_nv_read_value(u32 index, void *data, u32 count)
+u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
 {
 	const u8 command[22] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
@@ -163,7 +163,7 @@
 			     index_offset, index,
 			     length_offset, count))
 		return TPM_LIB_ERROR;
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "d",
@@ -178,7 +178,8 @@
 	return 0;
 }
 
-u32 tpm_nv_write_value(u32 index, const void *data, u32 length)
+u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
+		       u32 length)
 {
 	const u8 command[256] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
@@ -201,21 +202,22 @@
 			     length_offset, length,
 			     data_offset, data, length))
 		return TPM_LIB_ERROR;
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 
 	return 0;
 }
 
-uint32_t tpm_set_global_lock(void)
+uint32_t tpm_set_global_lock(struct udevice *dev)
 {
 	u32 x;
 
-	return tpm_nv_write_value(TPM_NV_INDEX_0, (uint8_t *)&x, 0);
+	return tpm_nv_write_value(dev, TPM_NV_INDEX_0, (uint8_t *)&x, 0);
 }
 
-u32 tpm_extend(u32 index, const void *in_digest, void *out_digest)
+u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
+	       void *out_digest)
 {
 	const u8 command[34] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
@@ -234,7 +236,7 @@
 			     in_digest_offset, in_digest,
 			     PCR_DIGEST_LENGTH))
 		return TPM_LIB_ERROR;
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 
@@ -246,7 +248,7 @@
 	return 0;
 }
 
-u32 tpm_pcr_read(u32 index, void *data, size_t count)
+u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
 {
 	const u8 command[14] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
@@ -264,7 +266,7 @@
 			     0, command, sizeof(command),
 			     index_offset, index))
 		return TPM_LIB_ERROR;
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "s",
@@ -274,7 +276,7 @@
 	return 0;
 }
 
-u32 tpm_tsc_physical_presence(u16 presence)
+u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
 {
 	const u8 command[12] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
@@ -287,19 +289,19 @@
 			     presence_offset, presence))
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(buf, NULL, NULL);
+	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_finalise_physical_presence(void)
+u32 tpm_finalise_physical_presence(struct udevice *dev)
 {
 	const u8 command[12] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
 	};
 
-	return tpm_sendrecv_command(command, NULL, NULL);
+	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_read_pubek(void *data, size_t count)
+u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
 {
 	const u8 command[30] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
@@ -312,7 +314,7 @@
 	u32 data_size;
 	u32 err;
 
-	err = tpm_sendrecv_command(command, response, &response_length);
+	err = tpm_sendrecv_command(dev, command, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "d",
@@ -330,34 +332,34 @@
 	return 0;
 }
 
-u32 tpm_force_clear(void)
+u32 tpm_force_clear(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
 	};
 
-	return tpm_sendrecv_command(command, NULL, NULL);
+	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_enable(void)
+u32 tpm_physical_enable(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
 	};
 
-	return tpm_sendrecv_command(command, NULL, NULL);
+	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_disable(void)
+u32 tpm_physical_disable(struct udevice *dev)
 {
 	const u8 command[10] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
 	};
 
-	return tpm_sendrecv_command(command, NULL, NULL);
+	return tpm_sendrecv_command(dev, command, NULL, NULL);
 }
 
-u32 tpm_physical_set_deactivated(u8 state)
+u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
 {
 	const u8 command[11] = {
 		0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
@@ -370,10 +372,11 @@
 			     state_offset, state))
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(buf, NULL, NULL);
+	return tpm_sendrecv_command(dev, buf, NULL, NULL);
 }
 
-u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
+u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
+		       void *cap, size_t count)
 {
 	const u8 command[22] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -397,7 +400,7 @@
 			     cap_area_offset, cap_area,
 			     sub_cap_offset, sub_cap))
 		return TPM_LIB_ERROR;
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "d",
@@ -412,7 +415,8 @@
 	return 0;
 }
 
-u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
+u32 tpm_get_permanent_flags(struct udevice *dev,
+			    struct tpm_permanent_flags *pflags)
 {
 	const u8 command[22] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -429,7 +433,7 @@
 	u32 err;
 	u32 data_size;
 
-	err = tpm_sendrecv_command(command, response, &response_length);
+	err = tpm_sendrecv_command(dev, command, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "d",
@@ -450,7 +454,7 @@
 	return 0;
 }
 
-u32 tpm_get_permissions(u32 index, u32 *perm)
+u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
 {
 	const u8 command[22] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -468,7 +472,7 @@
 	if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
 			     index_offset, index))
 		return TPM_LIB_ERROR;
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "d",
@@ -479,7 +483,7 @@
 }
 
 #ifdef CONFIG_TPM_FLUSH_RESOURCES
-u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
+u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
 {
 	const u8 command[18] = {
 		0x00, 0xc1,             /* TPM_TAG */
@@ -500,7 +504,7 @@
 			     resource_type_offset, resource_type))
 		return TPM_LIB_ERROR;
 
-	err = tpm_sendrecv_command(buf, response, &response_length);
+	err = tpm_sendrecv_command(dev, buf, response, &response_length);
 	if (err)
 		return err;
 	return 0;
@@ -638,7 +642,7 @@
 	return TPM_SUCCESS;
 }
 
-u32 tpm_terminate_auth_session(u32 auth_handle)
+u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
 {
 	const u8 command[18] = {
 		0x00, 0xc1,		/* TPM_TAG */
@@ -657,19 +661,19 @@
 	if (oiap_session.valid && oiap_session.handle == auth_handle)
 		oiap_session.valid = 0;
 
-	return tpm_sendrecv_command(request, NULL, NULL);
+	return tpm_sendrecv_command(dev, request, NULL, NULL);
 }
 
-u32 tpm_end_oiap(void)
+u32 tpm_end_oiap(struct udevice *dev)
 {
 	u32 err = TPM_SUCCESS;
 
 	if (oiap_session.valid)
-		err = tpm_terminate_auth_session(oiap_session.handle);
+		err = tpm_terminate_auth_session(dev, oiap_session.handle);
 	return err;
 }
 
-u32 tpm_oiap(u32 *auth_handle)
+u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
 {
 	const u8 command[10] = {
 		0x00, 0xc1,		/* TPM_TAG */
@@ -683,9 +687,9 @@
 	u32 err;
 
 	if (oiap_session.valid)
-		tpm_terminate_auth_session(oiap_session.handle);
+		tpm_terminate_auth_session(dev, oiap_session.handle);
 
-	err = tpm_sendrecv_command(command, response, &response_length);
+	err = tpm_sendrecv_command(dev, command, response, &response_length);
 	if (err)
 		return err;
 	if (unpack_byte_string(response, response_length, "ds",
@@ -699,8 +703,9 @@
 	return 0;
 }
 
-u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
-		       const void *parent_key_usage_auth, u32 *key_handle)
+u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
+		       size_t key_length, const void *parent_key_usage_auth,
+		       u32 *key_handle)
 {
 	const u8 command[14] = {
 		0x00, 0xc2,		/* TPM_TAG */
@@ -719,7 +724,7 @@
 	u32 err;
 
 	if (!oiap_session.valid) {
-		err = tpm_oiap(NULL);
+		err = tpm_oiap(dev, NULL);
 		if (err)
 			return err;
 	}
@@ -739,7 +744,7 @@
 				  parent_key_usage_auth);
 	if (err)
 		return err;
-	err = tpm_sendrecv_command(request, response, &response_length);
+	err = tpm_sendrecv_command(dev, request, response, &response_length);
 	if (err) {
 		if (err == TPM_AUTHFAIL)
 			oiap_session.valid = 0;
@@ -764,7 +769,8 @@
 	return 0;
 }
 
-u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
+u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
+			 const void *usage_auth, void *pubkey,
 			 size_t *pubkey_len)
 {
 	const u8 command[14] = {
@@ -783,7 +789,7 @@
 	u32 err;
 
 	if (!oiap_session.valid) {
-		err = tpm_oiap(NULL);
+		err = tpm_oiap(dev, NULL);
 		if (err)
 			return err;
 	}
@@ -799,7 +805,7 @@
 				  request + sizeof(command), usage_auth);
 	if (err)
 		return err;
-	err = tpm_sendrecv_command(request, response, &response_length);
+	err = tpm_sendrecv_command(dev, request, response, &response_length);
 	if (err) {
 		if (err == TPM_AUTHFAIL)
 			oiap_session.valid = 0;
@@ -829,8 +835,8 @@
 }
 
 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
-		      u32 *handle)
+u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
+		      const u8 pubkey_digest[20], u32 *handle)
 {
 	u16 key_count;
 	u32 key_handles[10];
@@ -842,7 +848,8 @@
 	unsigned int i;
 
 	/* fetch list of already loaded keys in the TPM */
-	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+	err = tpm_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+				 sizeof(buf));
 	if (err)
 		return -1;
 	key_count = get_unaligned_be16(buf);
@@ -870,7 +877,7 @@
 
 #endif /* CONFIG_TPM_AUTH_SESSIONS */
 
-u32 tpm_get_random(void *data, u32 count)
+u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
 {
 	const u8 command[14] = {
 		0x0, 0xc1,		/* TPM_TAG */
@@ -894,7 +901,8 @@
 				     0, command, sizeof(command),
 				     length_offset, this_bytes))
 			return TPM_LIB_ERROR;
-		err = tpm_sendrecv_command(buf, response, &response_length);
+		err = tpm_sendrecv_command(dev, buf, response,
+					   &response_length);
 		if (err)
 			return err;
 		if (unpack_byte_string(response, response_length, "d",
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index f1bbca8..f89592d 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -10,7 +10,7 @@
 #include <tpm-v2.h>
 #include "tpm-utils.h"
 
-u32 tpm2_startup(enum tpm2_startup_types mode)
+u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
 {
 	const u8 command_v2[12] = {
 		tpm_u16(TPM2_ST_NO_SESSIONS),
@@ -24,14 +24,14 @@
 	 * Note TPM2_Startup command will return RC_SUCCESS the first time,
 	 * but will return RC_INITIALIZE otherwise.
 	 */
-	ret = tpm_sendrecv_command(command_v2, NULL, NULL);
+	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 	if (ret && ret != TPM2_RC_INITIALIZE)
 		return ret;
 
 	return 0;
 }
 
-u32 tpm2_self_test(enum tpm2_yes_no full_test)
+u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
 {
 	const u8 command_v2[12] = {
 		tpm_u16(TPM2_ST_NO_SESSIONS),
@@ -40,10 +40,11 @@
 		full_test,
 	};
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-u32 tpm2_clear(u32 handle, const char *pw, const ssize_t pw_sz)
+u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
+	       const ssize_t pw_sz)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
@@ -75,10 +76,10 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-u32 tpm2_pcr_extend(u32 index, const uint8_t *digest)
+u32 tpm2_pcr_extend(struct udevice *dev, u32 index, const uint8_t *digest)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
@@ -113,11 +114,11 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2,	NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-u32 tpm2_pcr_read(u32 idx, unsigned int idx_min_sz, void *data,
-		  unsigned int *updates)
+u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
+		  void *data, unsigned int *updates)
 {
 	u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
@@ -142,7 +143,7 @@
 			     17 + pcr_sel_idx, pcr_sel_bit))
 		return TPM_LIB_ERROR;
 
-	ret = tpm_sendrecv_command(command_v2, response, &response_len);
+	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
 	if (ret)
 		return ret;
 
@@ -158,8 +159,8 @@
 	return 0;
 }
 
-u32 tpm2_get_capability(u32 capability, u32 property, void *buf,
-			size_t prop_count)
+u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
+			void *buf, size_t prop_count)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
@@ -175,7 +176,7 @@
 	unsigned int properties_off;
 	int ret;
 
-	ret = tpm_sendrecv_command(command_v2, response, &response_len);
+	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
 	if (ret)
 		return ret;
 
@@ -191,7 +192,7 @@
 	return 0;
 }
 
-u32 tpm2_dam_reset(const char *pw, const ssize_t pw_sz)
+u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
@@ -223,11 +224,12 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-u32 tpm2_dam_parameters(const char *pw, const ssize_t pw_sz,
-			unsigned int max_tries, unsigned int recovery_time,
+u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
+			const ssize_t pw_sz, unsigned int max_tries,
+			unsigned int recovery_time,
 			unsigned int lockout_recovery)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
@@ -271,11 +273,12 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz,
-		     const char *oldpw, const ssize_t oldpw_sz)
+int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
+		     const ssize_t newpw_sz, const char *oldpw,
+		     const ssize_t oldpw_sz)
 {
 	unsigned int offset = 27;
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
@@ -315,11 +318,11 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-u32 tpm2_pcr_setauthpolicy(const char *pw, const ssize_t pw_sz, u32 index,
-			   const char *key)
+u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
+			   const ssize_t pw_sz, u32 index, const char *key)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
@@ -370,11 +373,12 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
 
-u32 tpm2_pcr_setauthvalue(const char *pw, const ssize_t pw_sz, u32 index,
-			  const char *key, const ssize_t key_sz)
+u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
+			  const ssize_t pw_sz, u32 index, const char *key,
+			  const ssize_t key_sz)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
@@ -415,5 +419,5 @@
 	if (ret)
 		return TPM_LIB_ERROR;
 
-	return tpm_sendrecv_command(command_v2, NULL, NULL);
+	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
 }
diff --git a/test/README b/test/README
index 873a4e1..4bc9ca3 100644
--- a/test/README
+++ b/test/README
@@ -10,11 +10,15 @@
 
 To run most tests on sandbox, type this:
 
-    test/run
+    make check
 
 in the U-Boot directory. Note that only the pytest suite is run using this
 command.
 
+Some tests take ages to run. To run just the quick ones, type this:
+
+    make qcheck
+
 
 Sandbox
 -------
diff --git a/test/dm/i2c.c b/test/dm/i2c.c
index 772f62b..cbbd4aa 100644
--- a/test/dm/i2c.c
+++ b/test/dm/i2c.c
@@ -35,7 +35,7 @@
 	 */
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
 	ut_assertok(dm_i2c_probe(bus, chip, 0, &dev));
-	ut_asserteq(-ENODEV, dm_i2c_probe(bus, no_chip, 0, &dev));
+	ut_asserteq(-ENOENT, dm_i2c_probe(bus, no_chip, 0, &dev));
 	ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_I2C, 1, &bus));
 
 	return 0;
diff --git a/test/dm/rtc.c b/test/dm/rtc.c
index e2bc648..7188742 100644
--- a/test/dm/rtc.c
+++ b/test/dm/rtc.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <i2c.h>
 #include <rtc.h>
 #include <asm/io.h>
 #include <asm/test.h>
@@ -60,7 +61,7 @@
 	ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
 	ut_assertok(dm_rtc_get(dev, &now));
 
-	ut_assertok(device_find_first_child(dev, &emul));
+	ut_assertok(i2c_emul_find(dev, &emul));
 	ut_assert(emul != NULL);
 
 	/* Tell the RTC to go into manual mode */
@@ -125,7 +126,7 @@
 	ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev));
 	ut_assertok(dm_rtc_get(dev, &now));
 
-	ut_assertok(device_find_first_child(dev, &emul));
+	ut_assertok(i2c_emul_find(dev, &emul));
 	ut_assert(emul != NULL);
 
 	old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0);
@@ -154,9 +155,9 @@
 	ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev2));
 	ut_assertok(dm_rtc_get(dev2, &now2));
 
-	ut_assertok(device_find_first_child(dev1, &emul1));
+	ut_assertok(i2c_emul_find(dev1, &emul1));
 	ut_assert(emul1 != NULL);
-	ut_assertok(device_find_first_child(dev2, &emul2));
+	ut_assertok(i2c_emul_find(dev2, &emul2));
 	ut_assert(emul2 != NULL);
 
 	offset = sandbox_i2c_rtc_set_offset(emul1, false, -1);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index e43acb2..0fbd9be 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -611,3 +611,50 @@
 }
 DM_TEST(dm_test_fdt_disable_enable_by_path, DM_TESTF_SCAN_PDATA |
 					    DM_TESTF_SCAN_FDT);
+
+/* Test a few uclass phandle functions */
+static int dm_test_fdt_phandle(struct unit_test_state *uts)
+{
+	struct udevice *back, *dev, *dev2;
+
+	ut_assertok(uclass_find_first_device(UCLASS_PANEL_BACKLIGHT, &back));
+	ut_asserteq(-ENOENT, uclass_find_device_by_phandle(UCLASS_REGULATOR,
+							back, "missing", &dev));
+	ut_assertok(uclass_find_device_by_phandle(UCLASS_REGULATOR, back,
+						  "power-supply", &dev));
+	ut_asserteq(0, device_active(dev));
+	ut_asserteq_str("ldo1", dev->name);
+	ut_assertok(uclass_get_device_by_phandle(UCLASS_REGULATOR, back,
+						 "power-supply", &dev2));
+	ut_asserteq_ptr(dev, dev2);
+
+	return 0;
+}
+DM_TEST(dm_test_fdt_phandle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test device_find_first_child_by_uclass() */
+static int dm_test_first_child(struct unit_test_state *uts)
+{
+	struct udevice *i2c, *dev, *dev2;
+
+	ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c));
+	ut_assertok(device_find_first_child_by_uclass(i2c, UCLASS_RTC, &dev));
+	ut_asserteq_str("rtc@43", dev->name);
+	ut_assertok(device_find_child_by_name(i2c, "rtc@43", &dev2));
+	ut_asserteq_ptr(dev, dev2);
+	ut_assertok(device_find_child_by_name(i2c, "rtc@61", &dev2));
+	ut_asserteq_str("rtc@61", dev2->name);
+
+	ut_assertok(device_find_first_child_by_uclass(i2c, UCLASS_I2C_EEPROM,
+						      &dev));
+	ut_asserteq_str("eeprom@2c", dev->name);
+	ut_assertok(device_find_child_by_name(i2c, "eeprom@2c", &dev2));
+	ut_asserteq_ptr(dev, dev2);
+
+	ut_asserteq(-ENODEV, device_find_first_child_by_uclass(i2c,
+							UCLASS_VIDEO, &dev));
+	ut_asserteq(-ENODEV, device_find_child_by_name(i2c, "missing", &dev));
+
+	return 0;
+}
+DM_TEST(dm_test_first_child, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
diff --git a/test/py/tests/test_fs/test_basic.py b/test/py/tests/test_fs/test_basic.py
index c067cc9..140ca29 100644
--- a/test/py/tests/test_fs/test_basic.py
+++ b/test/py/tests/test_fs/test_basic.py
@@ -13,6 +13,7 @@
 from fstest_defs import *
 
 @pytest.mark.boardspec('sandbox')
+@pytest.mark.slow
 class TestFsBasic(object):
     def test_fs1(self, u_boot_console, fs_obj_basic):
         """
diff --git a/test/py/tests/test_fs/test_ext.py b/test/py/tests/test_fs/test_ext.py
index 38217d0..06cad55 100644
--- a/test/py/tests/test_fs/test_ext.py
+++ b/test/py/tests/test_fs/test_ext.py
@@ -13,6 +13,7 @@
 from fstest_defs import *
 
 @pytest.mark.boardspec('sandbox')
+@pytest.mark.slow
 class TestFsExt(object):
     def test_fs_ext1(self, u_boot_console, fs_obj_ext):
         """
diff --git a/test/py/tests/test_fs/test_mkdir.py b/test/py/tests/test_fs/test_mkdir.py
index d9da97b..b3fe11c 100644
--- a/test/py/tests/test_fs/test_mkdir.py
+++ b/test/py/tests/test_fs/test_mkdir.py
@@ -11,6 +11,7 @@
 import pytest
 
 @pytest.mark.boardspec('sandbox')
+@pytest.mark.slow
 class TestMkdir(object):
     def test_mkdir1(self, u_boot_console, fs_obj_mkdir):
         """
diff --git a/test/py/tests/test_fs/test_unlink.py b/test/py/tests/test_fs/test_unlink.py
index 69c1a6e..2b81746 100644
--- a/test/py/tests/test_fs/test_unlink.py
+++ b/test/py/tests/test_fs/test_unlink.py
@@ -12,6 +12,7 @@
 import pytest
 
 @pytest.mark.boardspec('sandbox')
+@pytest.mark.slow
 class TestUnlink(object):
     def test_unlink1(self, u_boot_console, fs_obj_unlink):
         """
diff --git a/test/run b/test/run
index cd323b0..55a6649 100755
--- a/test/run
+++ b/test/run
@@ -1,6 +1,7 @@
 #!/bin/bash
 
 # Script to run all U-Boot tests that use sandbox.
+#  $1: tests to run (empty for all, 'quick' for quick ones only)
 
 # Runs a test and checks the exit code to decide if it passed
 #  $1:         Test name
@@ -12,10 +13,13 @@
 	[ $? -ne 0 ] && failures=$((failures+1))
 }
 
+# SKip slow tests if requested
+[ "$1" == "quick" ] && mark_expr="not slow"
+
 failures=0
 
 # Run all tests that the standard sandbox build can support
-run_test "sandbox" ./test/py/test.py --bd sandbox --build
+run_test "sandbox" ./test/py/test.py --bd sandbox --build -m "${mark_expr}"
 
 # Run tests which require sandbox_spl
 run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
@@ -36,7 +40,9 @@
 
 run_test "binman" ./tools/binman/binman -t
 run_test "patman" ./tools/patman/patman --test
-run_test "buildman" ./tools/buildman/buildman -t
+
+[ "$1" == "quick" ] && skip=--skip-net-tests
+run_test "buildman" ./tools/buildman/buildman -t ${skip}
 run_test "fdt" ./tools/dtoc/test_fdt -t
 run_test "dtoc" ./tools/dtoc/dtoc -t