[U-Boot] [PATCH 1/3] tpm: Add casts for proper compilation

From: Taylor Hutt thutt@chromium.org
When building for the Sandbox version, the casts in this change are necessary to avoid compilation issues.
Signed-off-by: Taylor Hutt thutt@chromium.org Signed-off-by: Simon Glass sjg@chromium.org --- drivers/tpm/generic_lpc_tpm.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/tpm/generic_lpc_tpm.c b/drivers/tpm/generic_lpc_tpm.c index 6c494eb..04ad418 100644 --- a/drivers/tpm/generic_lpc_tpm.c +++ b/drivers/tpm/generic_lpc_tpm.c @@ -135,7 +135,7 @@ static u8 tpm_read_byte(const u8 *ptr) { u8 ret = readb(ptr); debug(PREFIX "Read reg 0x%4.4x returns 0x%2.2x\n", - (u32)ptr - (u32)lpc_tpm_dev, ret); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret); return ret; }
@@ -143,21 +143,21 @@ static u32 tpm_read_word(const u32 *ptr) { u32 ret = readl(ptr); debug(PREFIX "Read reg 0x%4.4x returns 0x%8.8x\n", - (u32)ptr - (u32)lpc_tpm_dev, ret); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, ret); return ret; }
static void tpm_write_byte(u8 value, u8 *ptr) { debug(PREFIX "Write reg 0x%4.4x with 0x%2.2x\n", - (u32)ptr - (u32)lpc_tpm_dev, value); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value); writeb(value, ptr); }
static void tpm_write_word(u32 value, u32 *ptr) { debug(PREFIX "Write reg 0x%4.4x with 0x%8.8x\n", - (u32)ptr - (u32)lpc_tpm_dev, value); + (u32)(uintptr_t)ptr - (u32)(uintptr_t)lpc_tpm_dev, value); writel(value, ptr); }
@@ -491,5 +491,5 @@ int tis_sendrecv(const u8 *sendbuf, size_t send_size, return TPM_DRIVER_ERR; }
- return tis_readresponse(recvbuf, recv_len); + return tis_readresponse(recvbuf, (u32 *)recv_len); }

From: Rong Chang rongchang@chromium.org
Add a driver for the I2C TPM from Infineon.
Signed-off-by: Che-Liang Chiou clchiou@chromium.org Signed-off-by: Rong Chang rongchang@chromium.org Signed-off-by: Tom Wai-Hong Tam waihong@chromium.org Signed-off-by: Simon Glass sjg@chromium.org --- Makefile | 2 +- drivers/tpm/Makefile | 4 + drivers/tpm/slb9635_i2c/compatibility.h | 51 +++ drivers/tpm/slb9635_i2c/tpm.c | 453 +++++++++++++++++++++++++ drivers/tpm/slb9635_i2c/tpm.h | 161 +++++++++ drivers/tpm/slb9635_i2c/tpm_tis_i2c.c | 562 +++++++++++++++++++++++++++++++ drivers/tpm/tis_i2c.c | 181 ++++++++++ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 9 files changed, 1415 insertions(+), 1 deletions(-) create mode 100644 drivers/tpm/slb9635_i2c/compatibility.h create mode 100644 drivers/tpm/slb9635_i2c/tpm.c create mode 100644 drivers/tpm/slb9635_i2c/tpm.h create mode 100644 drivers/tpm/slb9635_i2c/tpm_tis_i2c.c create mode 100644 drivers/tpm/tis_i2c.c
diff --git a/Makefile b/Makefile index 2fe1490..5355c33 100644 --- a/Makefile +++ b/Makefile @@ -313,7 +313,7 @@ LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o endif LIBS-y += drivers/rtc/librtc.o LIBS-y += drivers/serial/libserial.o -LIBS-$(CONFIG_GENERIC_LPC_TPM) += drivers/tpm/libtpm.o +LIBS-y += 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/drivers/tpm/Makefile b/drivers/tpm/Makefile index be11c8b..e8c159c 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -23,7 +23,11 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libtpm.o
+$(shell mkdir -p $(obj)slb9635_i2c) + COBJS-$(CONFIG_GENERIC_LPC_TPM) = generic_lpc_tpm.o +COBJS-$(CONFIG_INFINEON_TPM_I2C) += tis_i2c.o slb9635_i2c/tpm.o +COBJS-$(CONFIG_INFINEON_TPM_I2C) += slb9635_i2c/tpm_tis_i2c.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/tpm/slb9635_i2c/compatibility.h b/drivers/tpm/slb9635_i2c/compatibility.h new file mode 100644 index 0000000..62dc9fa --- /dev/null +++ b/drivers/tpm/slb9635_i2c/compatibility.h @@ -0,0 +1,51 @@ +/* + * 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/slb9635_i2c/tpm.c b/drivers/tpm/slb9635_i2c/tpm.c new file mode 100644 index 0000000..4b8d2d7 --- /dev/null +++ b/drivers/tpm/slb9635_i2c/tpm.c @@ -0,0 +1,453 @@ +/* + * 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 + */ + +#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; +} + +#define TPM_CMD_COUNT_BYTE 2 +#define TPM_CMD_ORDINAL_BYTE 6 + +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_COUNT_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; +} + +#define TPM_ERROR_SIZE 10 + +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/slb9635_i2c/tpm.h b/drivers/tpm/slb9635_i2c/tpm.h new file mode 100644 index 0000000..9ddee86 --- /dev/null +++ b/drivers/tpm/slb9635_i2c/tpm.h @@ -0,0 +1,161 @@ +/* + * 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 + */ + +#ifndef _TPM_H_ +#define _TPM_H_ + +#include <linux/compiler.h> + +#include "compatibility.h" + +enum tpm_timeout { + TPM_TIMEOUT = 5, /* msecs */ +}; + +/* Size of external transmit buffer (used in tpm_transmit)*/ +#define TPM_BUFSIZE 4096 + +/* 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); + 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; +}; + +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; + +union cap_t { + struct timeout_t timeout; + struct duration_t duration; +}; + +struct tpm_getcap_params_in { + __be32 cap; + __be32 subcap_size; + __be32 subcap; +} __packed; + +struct tpm_getcap_params_out { + __be32 cap_size; + union cap_t cap; +} __packed; + +union tpm_cmd_header { + struct tpm_input_header in; + struct tpm_output_header out; +}; + +union tpm_cmd_params { + struct tpm_getcap_params_out getcap_out; + struct tpm_getcap_params_in getcap_in; +}; + +struct tpm_cmd_t { + union tpm_cmd_header header; + union 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/slb9635_i2c/tpm_tis_i2c.c b/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c new file mode 100644 index 0000000..eff6c01 --- /dev/null +++ b/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c @@ -0,0 +1,562 @@ +/* + * 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 + */ + +#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 TPM_BUFSIZE 1260 +/* Address of the TPM on the I2C bus */ +#define TPM_I2C_ADDR 0x20 +/* max. number of iterations after i2c NAK */ +#define MAX_COUNT 3 + +#define SLEEP_DURATION 60 /*in usec*/ + +/* max. number of iterations after i2c NAK for 'long' commands + * we need this especially for sending TPM_READY, since the cleanup after the + * transtion to the ready state may take some time, but it is unpredictable + * how long it will take. + */ +#define MAX_COUNT_LONG 50 + +#define SLEEP_DURATION_LONG 210 /* in usec */ + +/* expected value for DIDVID register */ +#define TPM_TIS_I2C_DID_VID 0x000b15d1L + +/* Structure to store I2C TPM specific stuff */ +struct tpm_inf_dev { + uint addr; + u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ +}; + +static struct tpm_inf_dev tpm_dev = { + .addr = TPM_I2C_ADDR +}; + +/* + * iic_tpm_read() - read from TPM register + * @addr: register address to read from + * @buffer: provided by caller + * @len: number of bytes to read + * + * Read len bytes from TPM register and put them into + * buffer (little-endian format, i.e. first byte is put into buffer[0]). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * Return -EIO on error, 0 on success. + */ +int iic_tpm_read(u8 addr, u8 *buffer, size_t len) +{ + int rc; + int count; + uint myaddr = addr; + /* we have to use uint here, uchar hangs the board */ + + for (count = 0; count < MAX_COUNT; count++) { + rc = i2c_write(tpm_dev.addr, 0, 0, (uchar *) &myaddr, 1); + if (rc == 0) + break; /*success, break to skip sleep*/ + + udelay(SLEEP_DURATION); + } + + if (rc) + return -rc; + + /* After the TPM has successfully received the register address it needs + * some time, thus we're sleeping here again, before retrieving the data + */ + for (count = 0; count < MAX_COUNT; count++) { + udelay(SLEEP_DURATION); + rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); + if (rc == 0) + break; /*success, break to skip sleep*/ + + } + + if (rc) + return -rc; + + return 0; +} + +static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, + unsigned int sleep_time, + u8 max_count) +{ + int rc = 0; + int count; + + /* prepare send buffer */ + tpm_dev.buf[0] = addr; + memcpy(&(tpm_dev.buf[1]), buffer, len); + + for (count = 0; count < max_count; count++) { + rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1); + if (rc == 0) + break; /*success, break to skip sleep*/ + + udelay(sleep_time); + } + + if (rc) + return -rc; + + return 0; +} + +/* + * iic_tpm_write() - write to TPM register + * @addr: register address to write to + * @buffer: containing data to be written + * @len: number of bytes to write + * + * Write len bytes from provided buffer to TPM register (little + * endian format, i.e. buffer[0] is written as first byte). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * NOTE: use this function instead of the iic_tpm_write_generic function. + * + * Return -EIO on error, 0 on success + */ +static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) +{ + return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION, + MAX_COUNT); +} + +/* + * This function is needed especially for the cleanup situation after + * sending TPM_READY + * */ +static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) +{ + return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, + MAX_COUNT_LONG); +} + +#define TPM_HEADER_SIZE 10 + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_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 tis_defaults { + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 2000, /* 2 sec */ +}; + +#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) +#define TPM_STS(l) (0x0001 | ((l) << 4)) +#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) +#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) + +static int check_locality(struct tpm_chip *chip, int loc) +{ + u8 buf; + int rc; + + rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); + if (rc < 0) + return rc; + + if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == + (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { + chip->vendor.locality = loc; + return loc; + } + + return -1; +} + +static void release_locality(struct tpm_chip *chip, int loc, int force) +{ + u8 buf; + if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) + return; + + if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == + (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { + buf = TPM_ACCESS_ACTIVE_LOCALITY; + iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + } +} + +static int request_locality(struct tpm_chip *chip, int loc) +{ + unsigned long start, stop; + u8 buf = TPM_ACCESS_REQUEST_USE; + + if (check_locality(chip, loc) >= 0) + return loc; /* we already have the locality */ + + iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + + /* wait for burstcount */ + start = get_timer(0); + stop = chip->vendor.timeout_a; + do { + if (check_locality(chip, loc) >= 0) + return loc; + msleep(TPM_TIMEOUT); + } while (get_timer(start) < stop); + + return -1; +} + +static u8 tpm_tis_i2c_status(struct tpm_chip *chip) +{ + /* NOTE: since i2c read may fail, return 0 in this case --> time-out */ + u8 buf; + if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) + return 0; + else + return buf; +} + +static void tpm_tis_i2c_ready(struct tpm_chip *chip) +{ + /* this causes the current command to be aborted */ + u8 buf = TPM_STS_COMMAND_READY; + iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); +} + +static ssize_t get_burstcount(struct tpm_chip *chip) +{ + unsigned long start, stop; + ssize_t burstcnt; + u8 buf[3]; + + /* wait for burstcount */ + /* which timeout value, spec has 2 answers (c & d) */ + start = get_timer(0); + stop = chip->vendor.timeout_d; + do { + /* Note: STS is little endian */ + if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3) + < 0) + burstcnt = 0; + else + burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; + + if (burstcnt) + return burstcnt; + msleep(TPM_TIMEOUT); + } while (get_timer(start) < stop); + return -EBUSY; +} + +static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + int *status) +{ + unsigned long start, stop; + + /* check current status */ + *status = tpm_tis_i2c_status(chip); + if ((*status & mask) == mask) + return 0; + + start = get_timer(0); + stop = timeout; + do { + msleep(TPM_TIMEOUT); + *status = tpm_tis_i2c_status(chip); + if ((*status & mask) == mask) + return 0; + + } while (get_timer(start) < stop); + + return -ETIME; +} + +static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) +{ + size_t size = 0; + ssize_t burstcnt; + int rc; + + while (size < count) { + burstcnt = get_burstcount(chip); + + /* burstcount < 0 = tpm is busy */ + if (burstcnt < 0) + return burstcnt; + + /* limit received data to max. left */ + if (burstcnt > (count - size)) + burstcnt = count - size; + + rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), + &(buf[size]), + burstcnt); + if (rc == 0) + size += burstcnt; + + } + return size; +} + +static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) +{ + int size = 0; + int expected, status; + + if (count < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } + + /* read first 10 bytes, including tag, paramsize, and result */ + 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 ((size_t)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; + } + + wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ + dev_err(chip->dev, "Error left over data\n"); + size = -EIO; + goto out; + } + +out: + tpm_tis_i2c_ready(chip); + /* The TPM needs some time to clean up here, + * so we sleep rather than keeping the bus busy + */ + usleep(2000); + release_locality(chip, chip->vendor.locality, 0); + + return size; +} + +static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) +{ + int rc, status; + ssize_t burstcnt; + size_t count = 0; + u8 sts = TPM_STS_GO; + + if (len > TPM_BUFSIZE) + return -E2BIG; /* command is too long for our tpm, sorry */ + + if (request_locality(chip, 0) < 0) + return -EBUSY; + + status = tpm_tis_i2c_status(chip); + if ((status & TPM_STS_COMMAND_READY) == 0) { + tpm_tis_i2c_ready(chip); + if (wait_for_stat + (chip, TPM_STS_COMMAND_READY, + chip->vendor.timeout_b, &status) < 0) { + rc = -ETIME; + goto out_err; + } + } + + while (count < len - 1) { + burstcnt = get_burstcount(chip); + + /* burstcount < 0 = tpm is busy */ + if (burstcnt < 0) + return burstcnt; + + if (burstcnt > (len-1-count)) + burstcnt = len-1-count; + +#ifdef CONFIG_TPM_I2C_BURST_LIMITATION + if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION) + burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION; +#endif /* CONFIG_TPM_I2C_BURST_LIMITATION */ + + rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), + &(buf[count]), burstcnt); + if (rc == 0) + count += burstcnt; + + wait_for_stat(chip, TPM_STS_VALID, + chip->vendor.timeout_c, &status); + + if ((status & TPM_STS_DATA_EXPECT) == 0) { + rc = -EIO; + goto out_err; + } + + } + + /* write last byte */ + iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); + wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); + if ((status & TPM_STS_DATA_EXPECT) != 0) { + rc = -EIO; + goto out_err; + } + + /* go and do it */ + iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); + + return len; +out_err: + tpm_tis_i2c_ready(chip); + /* The TPM needs some time to clean up here, + * so we sleep rather than keeping the bus busy + */ + usleep(2000); + release_locality(chip, chip->vendor.locality, 0); + + return rc; +} + +static struct tpm_vendor_specific tpm_tis_i2c = { + .status = tpm_tis_i2c_status, + .recv = tpm_tis_i2c_recv, + .send = tpm_tis_i2c_send, + .cancel = tpm_tis_i2c_ready, + .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, +}; + +/* initialisation of i2c tpm */ + + +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(&tpm_tis_i2c); + if (chip < 0) { + rc = -ENODEV; + goto out_err; + } + + /* Disable interrupts (not supported) */ + chip->vendor.irq = 0; + + /* 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; + + if (request_locality(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + + /* read four bytes from DID_VID register */ + if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { + rc = -EIO; + goto out_release; + } + + /* create DID_VID register value, after swapping to little-endian */ + vendor = be32_to_cpu(vendor); + + if (vendor != TPM_TIS_I2C_DID_VID) { + rc = -ENODEV; + goto out_release; + } + + dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); + + /* + * A timeout query to TPM can be placed here. + * Standard timeout values are used so far + */ + + return 0; + +out_release: + release_locality(chip, 0, 1); + +out_err: + tpm_dev.addr = old_addr; + return rc; +} + +void tpm_vendor_cleanup(struct tpm_chip *chip) +{ + release_locality(chip, chip->vendor.locality, 1); +} diff --git a/drivers/tpm/tis_i2c.c b/drivers/tpm/tis_i2c.c new file mode 100644 index 0000000..d79e18d --- /dev/null +++ b/drivers/tpm/tis_i2c.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <config.h> +#include <common.h> +#include <fdtdec.h> +#include <i2c.h> +#include "slb9635_i2c/tpm.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* 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_INFINEON_TPM_I2C_BUS; + dev->slave_addr = CONFIG_INFINEON_TPM_I2C_ADDR; +#endif + return 0; +} + +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(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + int len; + uint8_t buf[4096]; + + 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/include/fdtdec.h b/include/fdtdec.h index 0b14075..577b149 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -66,6 +66,7 @@ enum fdt_compat_id { COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */ COMPAT_NVIDIA_TEGRA20_KBC, /* Tegra20 Keyboard */ COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */ + COMPAT_INFINEON_SLB9635_TPM, /* Infineon SLB9635 TPM */
COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 4c23f45..3027835 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -43,6 +43,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"), COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"), COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), + COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"), };
const char *fdtdec_get_compatible(enum fdt_compat_id id)

Dear Simon Glass,
In message 1351874667-23959-2-git-send-email-sjg@chromium.org you wrote:
From: Rong Chang rongchang@chromium.org
Add a driver for the I2C TPM from Infineon.
Signed-off-by: Che-Liang Chiou clchiou@chromium.org Signed-off-by: Rong Chang rongchang@chromium.org Signed-off-by: Tom Wai-Hong Tam waihong@chromium.org Signed-off-by: Simon Glass sjg@chromium.org
NAK. I will not accept any more additions of such dead code. We added TPM support long ago, based on the assumption/promise that users for it would follow soon. But nothing ever happened.
Instead of adding more such dead code, we should rather completely remove this unused stuff - note that it does not even get compile-tested io any mainline configuration.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 8:07 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351874667-23959-2-git-send-email-sjg@chromium.org you wrote:
From: Rong Chang rongchang@chromium.org
Add a driver for the I2C TPM from Infineon.
Signed-off-by: Che-Liang Chiou clchiou@chromium.org Signed-off-by: Rong Chang rongchang@chromium.org Signed-off-by: Tom Wai-Hong Tam waihong@chromium.org Signed-off-by: Simon Glass sjg@chromium.org
NAK. I will not accept any more additions of such dead code. We added TPM support long ago, based on the assumption/promise that users for it would follow soon. But nothing ever happened.
Instead of adding more such dead code, we should rather completely remove this unused stuff - note that it does not even get compile-tested io any mainline configuration.
Please see my other message on this. Patches are pending for smdk5250 and chromebook-x86.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de A year spent in artificial intelligence is enough to make one believe in God.

This is used on some Exynos 5250 variants. For now, enable it manually until we have CONFIG_OF_CONTROL support.
Signed-off-by: Simon Glass sjg@chromium.org --- include/configs/smdk5250.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h index c0f8622..c275a0e 100644 --- a/include/configs/smdk5250.h +++ b/include/configs/smdk5250.h @@ -107,6 +107,11 @@ #define CONFIG_USB_EHCI_EXYNOS #define CONFIG_USB_STORAGE
+/* TPM */ +#define CONFIG_INFINEON_TPM_I2C +#define CONFIG_INFINEON_TPM_I2C_BUS 3 +#define CONFIG_INFINEON_TPM_I2C_ADDR 0x20 + /* MMC SPL */ #define CONFIG_SPL #define COPY_BL2_FNPTR_ADDR 0x02020030

Dear Simon Glass,
In message 1351874667-23959-1-git-send-email-sjg@chromium.org you wrote:
From: Taylor Hutt thutt@chromium.org
When building for the Sandbox version, the casts in this change are necessary to avoid compilation issues.
Signed-off-by: Taylor Hutt thutt@chromium.org Signed-off-by: Simon Glass sjg@chromium.org
drivers/tpm/generic_lpc_tpm.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
I see little sense in spending work on this code. After all the time, it is still unused and dead code in mainline - there is not a single configuration which actually enables the necessary CONFIG_ options.,
I recommend to remove the whole TPM code instead.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 8:00 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon Glass,
In message 1351874667-23959-1-git-send-email-sjg@chromium.org you wrote:
From: Taylor Hutt thutt@chromium.org
When building for the Sandbox version, the casts in this change are necessary to avoid compilation issues.
Signed-off-by: Taylor Hutt thutt@chromium.org Signed-off-by: Simon Glass sjg@chromium.org
drivers/tpm/generic_lpc_tpm.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
I see little sense in spending work on this code. After all the time, it is still unused and dead code in mainline - there is not a single configuration which actually enables the necessary CONFIG_ options.,
I recommend to remove the whole TPM code instead.
It is actually used in the x86 Chromebook, but the patch to enable it never made it to mainline. There was quite a bit of push-back on the x86 side at the time and the person working on it finally had enough :-(
I have recently taken this up again to see if we can get x86 into a better state for newer Intel chips and the latest x86 Chromebooks. The patch to enable the TPM there is:
http://patchwork.ozlabs.org/patch/190813/
The patch to enable on ARM Chromebooks is the third patch in this TPM series:
http://patchwork.ozlabs.org/patch/196596/
I accept that it has sat there for a while without a board config to use it. But I would very much like to keep this code and see no sense in removing it now that it is actually in use.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de You are an excellent tactician, Captain. You let your second in com- mand attack while you sit and watch for weakness. -- Khan Noonian Singh, "Space Seed", stardate 3141.9

Dear Simon,
In message CAPnjgZ0RV991pa7MeVxr463g-TkKa+rzF8Gn7R0_ZbZnOWOsZg@mail.gmail.com you wrote:
I recommend to remove the whole TPM code instead.
It is actually used in the x86 Chromebook, but the patch to enable it never made it to mainline. There was quite a bit of push-back on the x86 side at the time and the person working on it finally had enough :-(
I have recently taken this up again to see if we can get x86 into a better state for newer Intel chips and the latest x86 Chromebooks. The patch to enable the TPM there is:
I don;t see how this uses it in any way in U-Boot. It still would not even compile most of the code, right?
I accept that it has sat there for a while without a board config to use it. But I would very much like to keep this code and see no sense in removing it now that it is actually in use.
Feel free to re-add it when there are any real users.
I've posted a removal patch.
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Sat, Nov 3, 2012 at 5:26 PM, Wolfgang Denk wd@denx.de wrote:
Dear Simon,
In message CAPnjgZ0RV991pa7MeVxr463g-TkKa+rzF8Gn7R0_ZbZnOWOsZg@mail.gmail.com you wrote:
I recommend to remove the whole TPM code instead.
It is actually used in the x86 Chromebook, but the patch to enable it never made it to mainline. There was quite a bit of push-back on the x86 side at the time and the person working on it finally had enough :-(
I have recently taken this up again to see if we can get x86 into a better state for newer Intel chips and the latest x86 Chromebooks. The patch to enable the TPM there is:
I don;t see how this uses it in any way in U-Boot. It still would not even compile most of the code, right?
It compiles the driver which is the main thing. The command can be enabled/disabled as needed. If it helps I can post a patch to enable it.
I accept that it has sat there for a while without a board config to use it. But I would very much like to keep this code and see no sense in removing it now that it is actually in use.
Feel free to re-add it when there are any real users.
I've posted a removal patch.
Can you please explain what you mean by 'real users'? Are you looking for an entire verified boot implementation before you will accept the TPM driver?
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de ...when fits of creativity run strong, more than one programmer or writer has been known to abandon the desktop for the more spacious floor. - Fred Brooks, Jr.

Dear Simon,
In message CAPnjgZ2p-Re5Hp13st-Q2CuP49azyZZxwNRZSAfhr_iUSGbNJQ@mail.gmail.com you wrote:
I accept that it has sat there for a while without a board config to use it. But I would very much like to keep this code and see no sense in removing it now that it is actually in use.
Feel free to re-add it when there are any real users.
I've posted a removal patch.
Can you please explain what you mean by 'real users'? Are you looking for an entire verified boot implementation before you will accept the TPM driver?
What exactly is this driver good for? Which function does it provide that can be used on any board in mainline? It looks to me that it's just sitting there, and does nothing good to anybody.
I don't know if there are any other legitimate uses for a TPM driver in U-Boot, but if there are, none appear to be implemented by any mainline board, so why should we have this driver in mainline?
Best regards,
Wolfgang Denk

Hi Wolfgang,
On Wed, Nov 7, 2012 at 5:06 AM, Wolfgang Denk wd@denx.de wrote:
Dear Simon,
In message CAPnjgZ2p-Re5Hp13st-Q2CuP49azyZZxwNRZSAfhr_iUSGbNJQ@mail.gmail.com you wrote:
I accept that it has sat there for a while without a board config to use it. But I would very much like to keep this code and see no sense in removing it now that it is actually in use.
Feel free to re-add it when there are any real users.
I've posted a removal patch.
Can you please explain what you mean by 'real users'? Are you looking for an entire verified boot implementation before you will accept the TPM driver?
What exactly is this driver good for? Which function does it provide that can be used on any board in mainline? It looks to me that it's just sitting there, and does nothing good to anybody.
I don't know if there are any other legitimate uses for a TPM driver in U-Boot, but if there are, none appear to be implemented by any mainline board, so why should we have this driver in mainline?
I replied on the other thread - hopefully we can agree a plan to move this forward.
Regards, Simon
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de While money can't buy happiness, it certainly lets you choose your own form of misery.
participants (2)
-
Simon Glass
-
Wolfgang Denk