diff --git a/Makefile b/Makefile
index 12763ce..ef954a4 100644
--- a/Makefile
+++ b/Makefile
@@ -314,7 +314,7 @@ endif
 LIBS-y += drivers/rtc/librtc.o
 LIBS-y += drivers/serial/libserial.o
 LIBS-y += drivers/sound/libsound.o
-LIBS-$(CONFIG_GENERIC_LPC_TPM) += drivers/tpm/libtpm.o
+LIBS-$(CONFIG_TPM) += drivers/tpm/libtpm.o
 LIBS-y += drivers/twserial/libtws.o
 LIBS-y += drivers/usb/eth/libusb_eth.o
 LIBS-y += drivers/usb/gadget/libusb_gadget.o
diff --git a/README b/README
index 7f2506a..3b1b633 100644
--- a/README
+++ b/README
@@ -1201,7 +1201,7 @@ The following options need to be configured:
 			If this option is set, the driver enables cache flush.
 
 - TPM Support:
-		CONFIG_GENERIC_LPC_TPM
+		CONFIG_TPM
 		Support for generic parallel port TPM devices. Only one device
 		per system is supported at this time.
 
@@ -1210,6 +1210,18 @@ The following options need to be configured:
 			to. Contemporary x86 systems usually map it at
 			0xfed40000.
 
+		CONFIG_ST_TPM_I2C
+		Define to compile the ST TPM I2C DRIVER.
+
+		CONFIG_TPM_I2C_BUS
+		Define the bus number of the board.
+
+		CONFIG_TPM_I2C_ADDR
+		Define the address of the TPM.
+
+		CONFIG_CMD_TPM
+		Define to use some TPM u-boot commands.
+
 - USB Support:
 		At the moment only the UHCI host controller is
 		supported (PIP405, MIP405, MPC5200); define
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c
index 0970a6f..2b7bf35 100644
--- a/common/cmd_tpm.c
+++ b/common/cmd_tpm.c
@@ -145,10 +145,177 @@ static int do_tpm_many(cmd_tbl_t *cmdtp, int flag,
 	return rv;
 }
 
+static int do_tpm_hash(cmd_tbl_t *cmdtp, int flag, int argc,
+char * const argv[])
+{
+	u8 tpm_buffer[MAX_TRANSACTION_SIZE];
+	u32 write_size, read_size;
+	char *p;
+	int rv = -1;
+	argc -= 1;
+	argv += 1;
+	u8 response[MAX_TRANSACTION_SIZE];
+	u32 rlength = MAX_TRANSACTION_SIZE;
+
+	u8 startup[] = {
+		0x00, 0xc1,
+		0x00, 0x00, 0x00, 0x0c,
+		0x00, 0x00, 0x00, 0x99,
+		0x00, 0x01
+	};
+
+	u8 selftestfull[] = {
+		0x00, 0xc1,
+		0x00, 0x00, 0x00, 0x0a,
+		0x00, 0x00, 0x00, 0x50
+	};
+
+	u8 readpcr17[] = {
+		0x00, 0xc1,
+		0x00, 0x00, 0x00, 0x0e,
+		0x00, 0x00, 0x00, 0x15,
+		0x00, 0x00, 0x00, 0x11
+	};
+
+	for (write_size = 0; write_size < argc; write_size++) {
+		u32 datum = simple_strtoul(argv[write_size], &p, 0);
+		if (*p || (datum > 0xff)) {
+			printf("\n%s: bad data value\n\n", argv[write_size]);
+			cmd_usage(cmdtp);
+			return rv;
+		}
+		tpm_buffer[write_size] = (u8)datum;
+	}
+
+	if (tis_init()) {
+		puts("tis_init() failed!\n");
+		return -1;
+	}
+
+	if (tis_open()) {
+		puts("tis_open() failed!\n");
+		return -1;
+	}
+
+	rv = tis_sendrecv(startup, sizeof(startup), &response, &rlength);
+	if (rv) {
+		printf("tpm test startup failed\n");
+		CHECK(tis_close());
+	}
+
+	rv = tis_sendrecv(selftestfull, sizeof(selftestfull), &response,
+		 &rlength);
+	if (rv) {
+		printf("tpm test selftestfull failed\n");
+		CHECK(tis_close());
+	}
+
+	if (!
+	tis_sendrecv(readpcr17, sizeof(readpcr17), &response, &read_size)) {
+			int i;
+			puts("TPM Read PCR 17:\n");
+			for (i = 10; i < read_size; i++)
+				printf(" %2.2x", response[i]);
+			puts("\n");
+			rv = 0;
+			} else {
+				printf("tpm test readpcr17 failed\n");
+				CHECK(tis_close());
+			}
+
+	read_size = sizeof(tpm_buffer);
+	if (!
+	tis_sendrecv_hash(tpm_buffer, write_size, tpm_buffer, &read_size)) {
+			int i;
+			puts("Got TPM Hash response:\n");
+			for (i = 0; i < read_size; i++)
+				printf(" %2.2x", tpm_buffer[i]);
+			puts("\n");
+			rv = 0;
+			} else {
+				puts("tpm hash command failed\n");
+				}
+
+	if (!
+	tis_sendrecv(readpcr17, sizeof(readpcr17), &response, &read_size)) {
+			int i;
+			puts("TPM Read PCR 17 after hash:\n");
+			for (i = 10; i < read_size; i++)
+				printf(" %2.2x", response[i]);
+			puts("\n");
+			rv = 0;
+			} else {
+				printf("tpm test readpcr17 failed\n");
+				CHECK(tis_close());
+				}
+
+	if (tis_close()) {
+		puts("tis_close() failed!\n");
+		rv = -1;
+	}
+
+	return rv;
+}
+
+static int do_tpm_get_flag(void)
+{
+	int rv = 0;
+	u8 response[MAX_TRANSACTION_SIZE];
+	u32 rlength = MAX_TRANSACTION_SIZE;
+
+	u8 startup[] = {
+		0x00, 0xc1,
+		0x00, 0x00, 0x00, 0x0c,
+		0x00, 0x00, 0x00, 0x99,
+		0x00, 0x01
+	};
+	u8 selftestfull[] = {
+		0x00, 0xc1,
+		0x00, 0x00, 0x00, 0x0a,
+		0x00, 0x00, 0x00, 0x50
+	};
+	u8 getpermflags[] = {
+		0x00, 0xc1,
+		0x00, 0x00, 0x00, 0x16,
+		0x00, 0x00, 0x00, 0x65,
+		0x00, 0x00, 0x00, 0x04,
+		0x00, 0x00, 0x00, 0x04,
+		0x00, 0x00, 0x01, 0x08
+	};
+
+
+	CHECK(tis_init());
+
+
+	CHECK(tis_open());
+	rv = tis_sendrecv(startup, sizeof(startup), response, &rlength);
+	if (rv) {
+		printf("tpm test startup failed\n");
+		CHECK(tis_close());
+	}
+	rv = tis_sendrecv(selftestfull, sizeof(selftestfull), response,
+	 &rlength);
+	if (rv) {
+		printf("tpm test selftestfull failed\n");
+		CHECK(tis_close());
+	}
+	rv = tis_sendrecv(getpermflags, sizeof(getpermflags), response,
+	 &rlength);
+	if (rv) {
+		printf("tpm test getpermflags failed\n");
+		CHECK(tis_close());
+	}
+	CHECK(tis_close());
+	return rv;
+}
 
 static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	return do_tpm_many(cmdtp, flag, argc, argv, 0);
+	if (strcmp(argv[1], "hash"))
+		return do_tpm_hash(cmdtp, flag, argc, argv);
+	else if (strcmp(argv[1], "get_flag"))
+			return do_tpm_get_flag();
+		else
+			return do_tpm_many(cmdtp, flag, argc, argv, 0);
 }
 
 
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index be11c8b..802b54e 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -24,6 +24,7 @@ include $(TOPDIR)/config.mk
 LIB := $(obj)libtpm.o
 
 COBJS-$(CONFIG_GENERIC_LPC_TPM) = generic_lpc_tpm.o
+COBJS-$(CONFIG_ST_TPM_I2C) = tis_i2c.o tpm.o tpm_i2c_st.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/tpm/compatibility.h b/drivers/tpm/compatibility.h
new file mode 100644
index 0000000..c68a855
--- /dev/null
+++ b/drivers/tpm/compatibility.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <huewe.external@infineon.com>
+ *
+ * Version: 2.1.1
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _COMPATIBILITY_H_
+#define _COMPATIBILITY_H_
+
+/* all includes from U-Boot */
+#include <linux/types.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <asm-generic/errno.h>
+#include <compiler.h>
+#include <common.h>
+
+/* extended error numbers from linux (see errno.h) */
+#define	ECANCELED	125	/* Operation Canceled */
+
+#define msleep(t) udelay((t)*1000)
+
+/* Timer frequency. Corresponds to msec timer resolution*/
+#define HZ             1000
+
+
+#define dev_dbg(dev, format, arg...) debug(format, ##arg)
+#define dev_err(dev, format, arg...) printf(format, ##arg)
+#define dev_info(dev, format, arg...) debug(format, ##arg)
+#define dbg_printf debug
+
+#endif
diff --git a/drivers/tpm/tis_i2c.c b/drivers/tpm/tis_i2c.c
new file mode 100644
index 0000000..3b3740f
--- /dev/null
+++ b/drivers/tpm/tis_i2c.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2011 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <huewe.external@infineon.com>
+ *
+ * Description:
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
+ * Infineon I2C Protocol Stack Specification v0.20.
+ *
+ * It is based on the Linux kernel driver tpm.c from Leendert van
+ * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
+ *
+ * Version: 2.1.1
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *Date:	Monday April 13
+ *
+ *	[backport from https://github.com/theopolis/u-boot-sboot/
+ *		blob/master/drivers/tpm/tis_i2c.c]
+ */
+
+#include <config.h>
+#include <common.h>
+#include <i2c.h>
+#include "tpm.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Define in board config */
+#ifndef CONFIG_TPM_I2C_BUS
+	#define CONFIG_TPM_I2C_BUS 0
+	#define CONFIG_TPM_I2C_ADDR 0
+#endif
+
+/* TPM configuration */
+struct tpm {
+	int i2c_bus;
+	int slave_addr;
+	char inited;
+	int old_bus;
+} tpm;
+
+
+static int tpm_select(void)
+{
+	int ret;
+
+	tpm.old_bus = i2c_get_bus_num();
+	if (tpm.old_bus != tpm.i2c_bus) {
+		ret = i2c_set_bus_num(tpm.i2c_bus);
+		if (ret) {
+			debug("%s: Fail to set i2c bus %d\n", __func__,
+			      tpm.i2c_bus);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int tpm_deselect(void)
+{
+	int ret;
+
+	if (tpm.old_bus != i2c_get_bus_num()) {
+		ret = i2c_set_bus_num(tpm.old_bus);
+		if (ret) {
+			debug("%s: Fail to restore i2c bus %d\n",
+			      __func__, tpm.old_bus);
+			return -1;
+		}
+	}
+	tpm.old_bus = -1;
+	return 0;
+}
+
+/**
+ * Decode TPM configuration.
+ *
+ * @param dev	Returns a configuration of TPM device
+ * @return 0 if ok, -1 on error
+ */
+static int tpm_decode_config(struct tpm *dev)
+{
+#ifdef CONFIG_OF_CONTROL
+	const void *blob = gd->fdt_blob;
+	int node, parent;
+	int i2c_bus;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
+	if (node < 0) {
+		debug("%s: Node not found\n", __func__);
+		return -1;
+	}
+	parent = fdt_parent_offset(blob, node);
+	if (parent < 0) {
+			debug("%s: Cannot find node parent\n", __func__);
+			return -1;
+	}
+	i2c_bus = i2c_get_bus_num_fdt(blob, parent);
+	if (i2c_bus < 0)
+		return -1;
+	dev->i2c_bus = i2c_bus;
+	dev->slave_addr = fdtdec_get_addr(blob, node, "reg");
+#else
+	dev->i2c_bus = CONFIG_TPM_I2C_BUS;
+	dev->slave_addr = CONFIG_TPM_I2C_ADDR;
+#endif
+	return 0;
+}
+
+/* Methods used by cmd_tpm */
+int tis_init(void)
+{
+	if (tpm.inited)
+		return 0;
+	if (tpm_decode_config(&tpm))
+		return -1;
+	if (tpm_select())
+		return -1;
+	/*
+	 * Probe TPM twice; the first probing might fail because TPM is asleep,
+	 * and the probing can wake up TPM.
+	 */
+	if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) {
+		debug(
+		"%s: fail to probe i2c addr 0x%x\n", __func__, tpm.slave_addr);
+		return -1;
+	}
+	tpm_deselect();
+	tpm.inited = 1;
+	return 0;
+}
+
+int tis_open(void)
+{
+	int rc;
+	if (!tpm.inited)
+		return -1;
+
+	if (tpm_select())
+		return -1;
+
+	rc = tpm_open(tpm.slave_addr);
+	tpm_deselect();
+
+	return rc;
+}
+
+int tis_close(void)
+{
+	if (!tpm.inited)
+		return -1;
+
+	if (tpm_select())
+		return -1;
+
+	tpm_close();
+
+	tpm_deselect();
+
+	return 0;
+}
+
+int tis_sendrecv_hash(const uint8_t *sendbuf, size_t sbuf_size,
+		uint8_t *recvbuf, size_t *rbuf_len)
+{
+	int len;
+	uint8_t buf[TPM_BUFSIZE];
+
+	if (!tpm.inited)
+		return -1;
+
+	if (sizeof(buf) < sbuf_size)
+		return -1;
+
+	memcpy(buf, sendbuf, sbuf_size);
+
+	if (tpm_select())
+		return -1;
+
+	len = tpm_transmit_hash(buf, sbuf_size);
+
+	tpm_deselect();
+
+	if (len < 10) {
+		*rbuf_len = 0;
+		return -1;
+	}
+
+	memcpy(recvbuf, buf, len);
+	*rbuf_len = len;
+
+	return 0;
+}
+
+int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
+		uint8_t *recvbuf, size_t *rbuf_len)
+{
+	int len;
+	uint8_t buf[TPM_BUFSIZE];
+
+	if (!tpm.inited)
+		return -1;
+
+	if (sizeof(buf) < sbuf_size)
+		return -1;
+
+	memcpy(buf, sendbuf, sbuf_size);
+
+	if (tpm_select())
+		return -1;
+
+	len = tpm_transmit(buf, sbuf_size);
+
+	tpm_deselect();
+
+	if (len < 10) {
+		*rbuf_len = 0;
+		return -1;
+	}
+
+	memcpy(recvbuf, buf, len);
+	*rbuf_len = len;
+
+	return 0;
+}
diff --git a/drivers/tpm/tpm.c b/drivers/tpm/tpm.c
new file mode 100644
index 0000000..25d6157
--- /dev/null
+++ b/drivers/tpm/tpm.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2011 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <huewe.external@infineon.com>
+ *
+ * Description:
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * It is based on the Linux kernel driver tpm.c from Leendert van
+ * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
+ *
+ * Version: 2.1.1
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *Date:	Monday April 13
+ *
+ *	[backport from https://github.com/theopolis/u-boot-sboot/
+ *		blob/master/drivers/tpm/tpm.c]
+ */
+
+#include <malloc.h>
+#include "tpm.h"
+
+/* global structure for tpm chip data */
+struct tpm_chip g_chip;
+
+enum tpm_duration {
+	TPM_SHORT = 0,
+	TPM_MEDIUM = 1,
+	TPM_LONG = 2,
+	TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result.  The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+	TPM_UNDEFINED,		/* 0 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 5 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 10 */
+	TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+	TPM_UNDEFINED,		/* 0 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 5 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 10 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_LONG,
+	TPM_MEDIUM,		/* 15 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_SHORT,		/* 20 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,		/* 25 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 30 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 35 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 40 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 45 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_LONG,
+	TPM_MEDIUM,		/* 50 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 55 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 60 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 65 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 70 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 75 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 80 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+	TPM_LONG,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 85 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 90 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 95 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 100 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 105 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 110 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 115 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 120 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 125 */
+	TPM_SHORT,
+	TPM_LONG,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,		/* 130 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,		/* 135 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 140 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 145 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 150 */
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 155 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 160 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 165 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_LONG,		/* 170 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 175 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_MEDIUM,		/* 180 */
+	TPM_SHORT,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,		/* 185 */
+	TPM_SHORT,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 190 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 195 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 200 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 205 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_MEDIUM,		/* 210 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,		/* 215 */
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,
+	TPM_SHORT,		/* 220 */
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_SHORT,
+	TPM_UNDEFINED,		/* 225 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 230 */
+	TPM_LONG,
+	TPM_MEDIUM,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,		/* 235 */
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_UNDEFINED,
+	TPM_SHORT,		/* 240 */
+	TPM_UNDEFINED,
+	TPM_MEDIUM,
+};
+
+/*
+ * Returns max number of milliseconds to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+{
+	int duration_idx = TPM_UNDEFINED;
+	int duration = 0;
+
+	if (ordinal < TPM_MAX_ORDINAL)
+		duration_idx = tpm_ordinal_duration[ordinal];
+	else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+		 TPM_MAX_PROTECTED_ORDINAL)
+		duration_idx =
+		    tpm_protected_ordinal_duration[ordinal &
+						   TPM_PROTECTED_ORDINAL_MASK];
+
+	if (duration_idx != TPM_UNDEFINED)
+		duration = chip->vendor.duration[duration_idx];
+	if (duration <= 0)
+		return 2 * 60 * HZ; /*two minutes timeout*/
+	else
+		return duration;
+}
+
+ssize_t tpm_transmit_hash(const unsigned char *buf, size_t bufsiz)
+{
+	ssize_t rc;
+	u32 count, ordinal;
+	unsigned long start, stop;
+
+	struct tpm_chip *chip = &g_chip;
+
+	rc = chip->vendor.send_hash(chip, (u8 *)buf, bufsiz);
+	if (rc < 0) {
+		dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc);
+		goto out;
+	}
+
+out_recv:
+
+	dbg_printf("out_recv: reading response...\n");
+	rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
+	if (rc < 0)
+		dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
+	return rc;
+}
+
+ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
+{
+	ssize_t rc;
+	u32 count, ordinal;
+	unsigned long start, stop;
+
+	struct tpm_chip *chip = &g_chip;
+
+	/* switch endianess: big->little */
+	count = get_unaligned_be32(buf + TPM_CMD_SIZE_BYTE);
+	ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
+
+	if (count == 0) {
+		dev_err(chip->dev, "no data\n");
+		return -ENODATA;
+	}
+	if (count > bufsiz) {
+		dev_err(chip->dev,
+			"invalid count value %x %zx\n", count, bufsiz);
+		return -E2BIG;
+	}
+
+	rc = chip->vendor.send(chip, (u8 *)buf, count);
+	if (rc < 0) {
+		dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc);
+		goto out;
+	}
+
+	if (chip->vendor.irq)
+		goto out_recv;
+
+	start = get_timer(0);
+	stop = tpm_calc_ordinal_duration(chip, ordinal);
+	do {
+		dbg_printf("waiting for status...\n");
+		u8 status = chip->vendor.status(chip);
+		if ((status & chip->vendor.req_complete_mask) ==
+		    chip->vendor.req_complete_val) {
+			dbg_printf("...got it;\n");
+			goto out_recv;
+		}
+
+		if ((status == chip->vendor.req_canceled)) {
+			dev_err(chip->dev, "Operation Canceled\n");
+			rc = -ECANCELED;
+			goto out;
+		}
+		msleep(TPM_TIMEOUT);
+	} while (get_timer(start) < stop);
+
+	chip->vendor.cancel(chip);
+	dev_err(chip->dev, "Operation Timed out\n");
+	rc = -ETIME;
+	goto out;
+
+out_recv:
+
+	dbg_printf("out_recv: reading response...\n");
+	rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
+	if (rc < 0)
+		dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
+	return rc;
+}
+
+enum tpm_capabilities {
+	TPM_CAP_PROP = cpu_to_be32(5),
+};
+
+enum tpm_sub_capabilities {
+	TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
+	TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
+};
+
+struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry)
+{
+	struct tpm_chip *chip;
+
+	/* Driver specific per-device data */
+	chip = &g_chip;
+	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
+	chip->is_open = 1;
+
+	return chip;
+}
+
+int tpm_open(uint32_t dev_addr)
+{
+	int rc;
+	if (g_chip.is_open)
+		return -EBUSY;
+	rc = tpm_vendor_init(dev_addr);
+	if (rc < 0)
+		g_chip.is_open = 0;
+	return rc;
+}
+
+void tpm_close(void)
+{
+	if (g_chip.is_open) {
+		tpm_vendor_cleanup(&g_chip);
+		g_chip.is_open = 0;
+	}
+}
diff --git a/drivers/tpm/tpm.h b/drivers/tpm/tpm.h
new file mode 100644
index 0000000..e5ce16e
--- /dev/null
+++ b/drivers/tpm/tpm.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <huewe.external@infineon.com>
+ *
+ * Version: 2.1.1
+ *
+ * Description:
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * It is based on the Linux kernel driver tpm.c from Leendert van
+ * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
+ *
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *Date:	Monday April 13
+ *
+ *	[backport from https://github.com/theopolis/u-boot-sboot/
+ *		blob/master/drivers/tpm/tpm.h]
+ */
+
+#ifndef _TPM_H_
+#define _TPM_H_
+
+#include "compatibility.h"
+
+enum tpm_timeout {
+	TPM_TIMEOUT = 5,	/* msecs */
+};
+
+/* Size of external transmit buffer (used in tpm_transmit)*/
+#define TPM_BUFSIZE 4096
+#define TPM_ERROR_SIZE 10
+#define TPM_HEADER_SIZE 10
+
+/* Index of fields in TPM command buffer */
+#define TPM_CMD_SIZE_BYTE 2
+#define TPM_CMD_ORDINAL_BYTE 6
+
+/* Index of Count field in TPM response buffer */
+#define TPM_RSP_SIZE_BYTE 2
+#define TPM_RSP_RC_BYTE 6
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+	const u8 req_complete_mask;
+	const u8 req_complete_val;
+	const u8 req_canceled;
+	int irq;
+	int (*recv) (struct tpm_chip *, u8 *, size_t);
+	int (*send) (struct tpm_chip *, u8 *, size_t);
+	int (*send_hash) (struct tpm_chip *, u8 *, size_t);
+	void (*cancel) (struct tpm_chip *);
+	 u8 (*status) (struct tpm_chip *);
+	int locality;
+	unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */
+	unsigned long duration[3];	/* msec */
+};
+
+struct tpm_chip {
+	int is_open;
+	struct tpm_vendor_specific vendor;
+	/* testing */
+	u8 dev;
+};
+
+struct tpm_input_header {
+	__be16 tag;
+	__be32 length;
+	__be32 ordinal;
+} __packed;
+
+struct tpm_output_header {
+	__be16 tag;
+	__be32 length;
+	__be32 return_code;
+} __packed;
+
+struct timeout_t {
+	__be32 a;
+	__be32 b;
+	__be32 c;
+	__be32 d;
+} __packed;
+
+struct duration_t {
+	__be32 tpm_short;
+	__be32 tpm_medium;
+	__be32 tpm_long;
+} __packed;
+
+struct cap_t {
+	struct timeout_t timeout;
+	struct duration_t duration;
+} __packed;
+
+struct tpm_getcap_params_in {
+	__be32 cap;
+	__be32 subcap_size;
+	__be32 subcap;
+} __packed;
+
+struct tpm_getcap_params_out {
+	__be32 cap_size;
+	struct cap_t cap;
+} __packed;
+
+struct tpm_cmd_header {
+	struct tpm_input_header in;
+	struct tpm_output_header out;
+} __packed;
+
+struct tpm_cmd_params {
+	struct tpm_getcap_params_out getcap_out;
+	struct tpm_getcap_params_in getcap_in;
+} __packed;
+
+struct tpm_cmd_t {
+	struct tpm_cmd_header header;
+	struct tpm_cmd_params params;
+} __packed;
+
+
+/* ---------- Interface for TPM vendor ------------ */
+
+extern struct tpm_chip *tpm_register_hardware(
+	const struct tpm_vendor_specific *);
+
+extern int tpm_vendor_init(uint32_t dev_addr);
+
+extern void tpm_vendor_cleanup(struct tpm_chip *chip);
+
+/* ---------- Interface for TDDL ------------------- */
+
+/*
+ * if dev_addr != 0 - redefines TPM device address
+ * Returns < 0 on error, 0 on success.
+ */
+extern int tpm_open(uint32_t dev_addr);
+
+extern void tpm_close(void);
+
+/*
+ * Transmit bufsiz bytes out of buf to TPM and get results back in buf, too.
+ * Returns < 0 on error, 0 on success.
+ */
+extern ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz);
+
+#endif
diff --git a/drivers/tpm/tpm_i2c_st.c b/drivers/tpm/tpm_i2c_st.c
new file mode 100644
index 0000000..f630dbd
--- /dev/null
+++ b/drivers/tpm/tpm_i2c_st.c
@@ -0,0 +1,599 @@
+/*
+ * STMicroelectronics TPM I2C UBOOT Linux driver for TPM ST33ZP24
+ * Copyright (C) 2013  STMicroelectronics
+ *
+ * (c) Copyright 2013 Mathias Leblanc <mathias.leblanc@st.com>
+ * This file is released under the terms of GPL v2 and any later version
+ * See the file COPYING in the root directory of the source tree for details
+ *
+ * Description:
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
+ * STMicroelectronics I2C Protocol Stack Specification version 1.2.0.
+ *
+ * It is based on the Linux I2C TPM driver from Peter Huewe, modified
+ * from the original tpm
+ * device drivers from Leendert van Dorn, Dave Safford, Reiner Sailer
+ * and Kyleen Hall.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * @Author: Mathias Leblanc tpmsupport@st.com
+ *
+ * @File: tpm_i2c_st.c
+ *
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <linux/types.h>
+
+#include "compatibility.h"
+#include "tpm.h"
+
+/* max. buffer size supported by our tpm */
+#ifdef TPM_BUFSIZE
+#undef TPM_BUFSIZE
+#endif
+
+#define MINOR_NUM_I2C		224
+
+#define TPM_ACCESS			(0x0)
+#define TPM_STS				(0x18)
+#define TPM_HASH_END			(0x20)
+#define TPM_DATA_FIFO			(0x24)
+#define TPM_HASH_DATA			(0x24)
+#define TPM_HASH_START			(0x28)
+#define TPM_INTF_CAPABILITY		(0x14)
+#define TPM_INT_STATUS			(0x10)
+#define TPM_INT_ENABLE			(0x08)
+
+#define TPM_DUMMY_BYTE			0xAA
+#define TPM_WRITE_DIRECTION		0x80
+#define TPM_HEADER_SIZE			10
+#define TPM_BUFSIZE			2048
+
+#define LOCALITY0		0
+#define LOCALITY4		4
+
+struct st_tpm_hash {
+	int size;
+	u8 *data;
+};
+
+enum stm33zp24_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum stm33zp24_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum stm33zp24_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
+	TPM_INTF_WAKE_UP_READY_INT = 0x020,
+	TPM_INTF_LOC4SOFTRELEASE_INT = 0x008,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT = 750,	/* ms */
+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
+};
+
+struct tpm_i2c_ST_dev {
+	uint addr;
+	u8 buf[TPM_BUFSIZE];
+};
+
+static struct tpm_i2c_ST_dev tpm_dev = {
+		/* Note: replace with defined addr from board configuration */
+		.addr = CONFIG_TPM_I2C_ADDR
+};
+
+/*
+ * write8_reg
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: Returns zero in case of success else the negative error code.
+ */
+static int write8_reg(u8 addr, u8 tpm_register,
+		      u8 *tpm_data, u16 tpm_size)
+{
+	u8 data;
+	data = tpm_register;
+	memcpy(&(tpm_dev.buf[0]), &data, sizeof(data));
+	memcpy(&(tpm_dev.buf[0])+1, tpm_data, tpm_size);
+
+	return i2c_write(addr, 0, 0, &tpm_dev.buf[0],
+				tpm_size + 1);
+
+} /* write8_reg() */
+
+/*
+* read8_reg
+* Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+* @param: tpm_register, the tpm tis register where the data should be read
+* @param: tpm_data, the TPM response
+* @param: tpm_size, tpm TPM response size to read.
+* @return: Returns zero in case of success else the negative error code.
+*/
+static int read8_reg(u8 addr, u8 tpm_register,
+u8 *tpm_data, int tpm_size)
+{
+	u8 status = 0;
+	u8 data;
+	data = TPM_DUMMY_BYTE;
+	status = write8_reg(addr, tpm_register, &data, 1);
+	if (status == 0)
+		status = i2c_read(addr, 0, 0, tpm_data, tpm_size);
+return status;
+} /* read8_reg() */
+
+/*
+ * I2C_WRITE_DATA
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: client, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: Returns zero in case of success else the negative error code.
+ */
+#define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size)\
+	 (write8_reg(client, tpm_register | \
+	TPM_WRITE_DIRECTION, tpm_data, tpm_size))
+
+/*
+ * I2C_READ_DATA
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: Returns zero in case of success else the negative error code.
+ */
+#define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size)\
+	 (read8_reg(client, tpm_register, tpm_data, tpm_size))
+
+/*
+ * release_locality release the active locality
+ * @param: chip, the tpm chip description.
+ */
+static void release_locality(struct tpm_chip *chip)
+{
+	u8 data = TPM_ACCESS_ACTIVE_LOCALITY;
+
+	I2C_WRITE_DATA(tpm_dev.addr, TPM_ACCESS, &data, 1);
+}
+
+/*
+ * clear_interruption
+ * clear the TPM interrupt register.
+ * @param: tpm, the chip description
+ */
+static void clear_interruption(u8 addr)
+{
+	u8 interrupt;
+	I2C_READ_DATA(tpm_dev.addr, TPM_INT_STATUS, &interrupt, 1);
+	I2C_WRITE_DATA(tpm_dev.addr, TPM_INT_STATUS, &interrupt, 1);
+	I2C_READ_DATA(tpm_dev.addr, TPM_INT_STATUS, &interrupt, 1);
+} /* clear_interruption() */
+
+int wait_for_serirq_timeout(struct tpm_chip *chip, int condition,
+	 unsigned long timeout)
+{
+	int status = 2;
+
+	clear_interruption(tpm_dev.addr);
+	if (condition)
+		status = 1;
+
+	return status;
+}
+
+/*
+ * check_locality if the locality is active
+ * @param: chip, the tpm chip description
+ * @return: the active locality or -EACCESS.
+ */
+static int check_locality(struct tpm_chip *chip)
+{
+	u8 data;
+	u8 status;
+	status = I2C_READ_DATA(tpm_dev.addr, TPM_ACCESS, &data, 1);
+
+	if ((status == 0) && (data &
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality;
+
+	return -EACCES;
+
+} /* check_locality() */
+
+/*
+ * request_locality request the TPM locality
+ * @param: chip, the chip description
+ * @return: the active locality or EACCESS.
+ */
+static int request_locality(struct tpm_chip *chip)
+{
+	unsigned long start, stop;
+	long rc;
+	u8 data;
+	if (check_locality(chip) == chip->vendor.locality)
+		return chip->vendor.locality;
+
+	data = TPM_ACCESS_REQUEST_USE;
+	rc = I2C_WRITE_DATA(tpm_dev.addr, TPM_ACCESS, &data, 1);
+	if (rc < 0)
+		goto end;
+
+	if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, (check_locality
+						       (chip) >= 0),
+						      chip->vendor.timeout_a);
+		if (rc > 0)
+			return chip->vendor.locality;
+	} else{
+	/* wait for locality activated */
+	start = get_timer(0);
+	stop = chip->vendor.timeout_a;
+		do {
+			if (check_locality(chip) >= 0)
+				return chip->vendor.locality;
+
+			msleep(TPM_TIMEOUT);
+		} while	 (get_timer(start) < stop);
+	}
+	rc = -EACCES;
+end:
+	return rc;
+} /* request_locality() */
+
+/*
+ * tpm_stm_i2c_cancel, cancel is not implemented.
+ * @param: chip, tpm_chip description.
+ */
+static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
+{
+	u8 data;
+
+	data = TPM_STS_COMMAND_READY;
+	I2C_WRITE_DATA(tpm_dev.addr, TPM_STS, &data, 1);
+	if (chip->vendor.irq)
+		wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a);
+}	/* tpm_stm_i2c_cancel() */
+
+/*
+ * tpm_stm_spi_status return the TPM_STS register
+ * @param: chip, the tpm chip description
+ * @return: the TPM_STS register value.
+ */
+static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
+{
+	u8 data;
+	I2C_READ_DATA(tpm_dev.addr, TPM_STS, &data, 1);
+	return data;
+}				/* tpm_stm_i2c_status() */
+
+/*
+ * get_burstcount return the burstcount address 0x19 0x1A
+ * @param: chip, the chip description
+ * return: the burstcount.
+ */
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long start, stop;
+	int burstcnt, status;
+	u8 tpm_reg, temp;
+
+	/* wait for burstcount */
+	/* which timeout value, spec has 2 answers (c & d) */
+	start = get_timer(0);
+	stop = chip->vendor.timeout_d;
+	do {
+		tpm_reg = TPM_STS + 1;
+		status = I2C_READ_DATA(tpm_dev.addr, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		tpm_reg = tpm_reg + 1;
+		burstcnt = temp;
+		status = I2C_READ_DATA(tpm_dev.addr, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		burstcnt |= temp << 8;
+		if (burstcnt)
+			return burstcnt;
+
+		msleep(TPM_TIMEOUT);
+	} while (get_timer(start) < stop);
+
+end:
+	return -EBUSY;
+} /* get_burstcount() */
+
+
+/*
+ * recv_data receive data
+ * @param: chip, the tpm chip description
+ * @param: buf, the buffer where the data are received
+ * @param: count, the number of data to receive
+ * @return: the number of bytes read from TPM FIFO.
+ */
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt, len;
+
+	while (size < count) {
+		burstcnt = get_burstcount(chip);
+		len = count - size;
+		if ((len) > burstcnt)
+			len = burstcnt;
+	if (
+	I2C_READ_DATA(tpm_dev.addr, TPM_DATA_FIFO, buf + size, len) == 0)
+			size += len;
+		else
+			break;
+	}
+	return size;
+} /* recv_data() */
+
+/*
+ * tpm_stm_i2c_recv received TPM response through the I2C bus.
+ * @param: chip, tpm_chip description.
+ * @param: buf,	the buffer to store datas.
+ * @param: count, the number of bytes to send.
+ * @return: Returns zero in case of success else the negative error code.
+ */
+static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	int size = 0;
+	int expected;
+
+	if (chip == NULL)
+		return -EBUSY;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	size = recv_data(chip, buf, TPM_HEADER_SIZE);
+	if (size < TPM_HEADER_SIZE) {
+		dev_err(chip->dev, "Unable to read header\n");
+		goto out;
+	}
+
+
+	expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE);
+	if (expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+					expected - TPM_HEADER_SIZE);
+	if (size < expected) {
+		dev_err(chip->dev, "Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+out:
+	chip->vendor.cancel(chip);
+	release_locality(chip);
+	return size;
+} /* tpm_stm_i2c_recv() */
+
+/*
+ * tpm_stm_i2c_send send TPM commands through the I2C bus.
+ *
+ * @param: chip, tpm_chip description.
+ * @param: buf,	the buffer to send.
+ * @param: len, the number of bytes to send.
+ * @return: Returns zero in case of success else the negative error code.
+ */
+static int tpm_stm_i2c_send(struct tpm_chip *chip, u8 *buf,
+			    size_t len)
+{
+	u32 ret = 0,
+	    status,
+	    burstcnt = 0, i, size;
+	u8 data;
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (len < TPM_HEADER_SIZE)
+		return -EBUSY;
+
+	ret = request_locality(chip);
+	if (ret < 0)
+		return ret;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0)
+		tpm_stm_i2c_cancel(chip);
+
+	for (i = 0; i < len - 1;) {
+		burstcnt = get_burstcount(chip);
+		size = len - i - 1;
+		if ((size) > burstcnt)
+			size = burstcnt;
+		ret = I2C_WRITE_DATA(tpm_dev.addr, TPM_DATA_FIFO, buf, size);
+		if (ret < 0)
+			goto out_err;
+
+		i += size;
+	}
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) == 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	ret = I2C_WRITE_DATA(tpm_dev.addr, TPM_DATA_FIFO, buf + len - 1, 1);
+	if (ret < 0)
+		goto out_err;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	data = TPM_STS_GO;
+	I2C_WRITE_DATA(tpm_dev.addr, TPM_STS, &data, 1);
+
+	return len;
+out_err:
+	tpm_stm_i2c_cancel(chip);
+	release_locality(chip);
+	return ret;
+} /* tpm_stm_i2c_send() */
+
+/*
+ * tpm_stm_i2c_send_hash send TPM locality 4 hash datas through the I2C bus
+ * to update the PCR[17].
+ * @param: chip, the tpm_chip description.
+ * @param: buf,	the data buffer to send.
+ * @param: len, the number of bytes to send.
+ * @return: Returns zero in case of success else the negative error code.
+ */
+static int tpm_stm_i2c_send_hash(struct tpm_chip *chip, unsigned char *buf,
+			    size_t len)
+{
+	u32 ret = 0;
+	u8 data;
+
+	if (chip == NULL)
+		return -EBUSY;
+
+	release_locality(chip);
+
+	tpm_dev.addr = 0x1B;
+	chip->vendor.locality = LOCALITY4;
+
+	data = TPM_DUMMY_BYTE;
+	ret = I2C_WRITE_DATA(tpm_dev.addr, TPM_HASH_START, &data, 1);
+	if (ret < 0)
+		goto end;
+	ret = I2C_WRITE_DATA(tpm_dev.addr, TPM_DATA_FIFO, buf, len);
+	if (ret < 0)
+		goto end;
+
+end:
+	I2C_WRITE_DATA(tpm_dev.addr, TPM_HASH_END, &data, 1);
+	release_locality(chip);
+	chip->vendor.locality = LOCALITY0;
+	tpm_dev.addr = 0x13;
+	ret = request_locality(chip);
+	return ret;
+} /* tpm_stm_i2c_send_hash */
+
+static struct tpm_vendor_specific st_i2c_tpm = {
+	.send = tpm_stm_i2c_send,
+	.send_hash = tpm_stm_i2c_send_hash,
+	.recv = tpm_stm_i2c_recv,
+	.cancel = tpm_stm_i2c_cancel,
+	.status = tpm_stm_i2c_status,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+};
+
+/*
+ * tpm_vendor_init initialize the TPM device
+ * @param: dev_addr, the i2c address of the tpm.
+ * @return: 0 in case of success.
+ *	 -1 in other case.
+ */
+int tpm_vendor_init(uint32_t dev_addr)
+{
+	u32 vendor;
+	uint old_addr;
+	int rc = 0;
+	struct tpm_chip *chip;
+
+	old_addr = tpm_dev.addr;
+	if (dev_addr != 0)
+		tpm_dev.addr = dev_addr;
+
+	chip = tpm_register_hardware(&st_i2c_tpm);
+
+	if (chip < 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = TIS_SHORT_TIMEOUT;
+	chip->vendor.timeout_b = TIS_LONG_TIMEOUT;
+	chip->vendor.timeout_c = TIS_SHORT_TIMEOUT;
+	chip->vendor.timeout_d = TIS_SHORT_TIMEOUT;
+
+	chip->vendor.locality = LOCALITY0;
+
+	if (request_locality(chip) != 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	vendor = be32_to_cpu(vendor);
+
+
+	dev_info(dev, "1.2 TPM STMicroelectronics");
+	/*
+	 * A timeout query to TPM can be placed here.
+	 * Standard timeout values are used so far
+	 */
+
+	return 0;
+
+out_err:
+	tpm_dev.addr = old_addr;
+	return rc;
+} /* tpm_vendor_init() */
+
+
+
+void tpm_vendor_cleanup(struct tpm_chip *chip)
+{
+	release_locality(chip);
+} /* tpm_vendor_cleanup() */
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index 87daf62..fda6512 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -76,8 +76,8 @@
 					 CONFIG_SYS_SCSI_MAX_LUN)
 #endif
 
-/* Generic TPM interfaced through LPC bus */
-#define CONFIG_GENERIC_LPC_TPM
+/* Generic TPM interfaced through LPC / I2C bus */
+#define CONFIG_TPM
 #define CONFIG_TPM_TIS_BASE_ADDRESS        0xfed40000
 
 /*-----------------------------------------------------------------------
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 48ce4c0..ef381f8 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -111,6 +111,14 @@
 #define STATUS_LED_BOOT			STATUS_LED_BIT
 #define STATUS_LED_GREEN		STATUS_LED_BIT1
 
+/* TPM */
+#define CONFIG_CMD_TPM
+#define CONFIG_TPM
+#define CONFIG_ST_TPM_DEBUG
+#define CONFIG_ST_TPM_I2C
+#define CONFIG_TPM_I2C_BUS	1
+#define CONFIG_TPM_I2C_ADDR	0x13
+
 /* Enable Multi Bus support for I2C */
 #define CONFIG_I2C_MULTI_BUS		1
 
diff --git a/include/tpm.h b/include/tpm.h
index 6b21e9c..77a1514 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -68,4 +68,21 @@ int tis_close(void);
 int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf,
 			size_t *recv_len);
 
+/*
+ * tis_sendrecv_hash()
+ *
+ * Send the requested data to the TPM for hash in LOC 4
+ * and then try to get its response
+ *
+ * @sendbuf - buffer of the data to hash
+ * @send_size size of the data to send
+ * @recvbuf - memory to save the response to
+ * @recv_len - pointer to the size of the response buffer
+ *
+ * Returns 0 on success (and places the number of response bytes at recv_len)
+ * or -1 on failure.
+ */
+int tis_sendrecv_hash(const uint8_t *sendbuf, size_t send_size,
+	 uint8_t *recvbuf,
+			size_t *recv_len);
+
 #endif /* _INCLUDE_TPM_H_ */
