summaryrefslogtreecommitdiff
path: root/src/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/i2c')
-rw-r--r--src/drivers/i2c/tpm/Kconfig16
-rw-r--r--src/drivers/i2c/tpm/Makefile.inc13
-rw-r--r--src/drivers/i2c/tpm/tis_atmel.c132
3 files changed, 156 insertions, 5 deletions
diff --git a/src/drivers/i2c/tpm/Kconfig b/src/drivers/i2c/tpm/Kconfig
index d35eb754b4..32e5fb4700 100644
--- a/src/drivers/i2c/tpm/Kconfig
+++ b/src/drivers/i2c/tpm/Kconfig
@@ -2,24 +2,38 @@ config I2C_TPM
bool "I2C TPM"
depends on TPM || TPM2
+config MAINBOARD_HAS_I2C_TPM_ATMEL
+ bool
+ default n
+
config MAINBOARD_HAS_I2C_TPM_CR50
bool
default n
choice
prompt "I2C TPM Driver"
+ default I2C_TPM_ATMEL if MAINBOARD_HAS_I2C_TPM_ATMEL
default I2C_TPM_CR50 if MAINBOARD_HAS_I2C_TPM_CR50
- default I2C_TPM_GENERIC if !MAINBOARD_HAS_I2C_TPM_CR50
+ default I2C_TPM_GENERIC if !MAINBOARD_HAS_I2C_TPM_CR50 && !MAINBOARD_HAS_I2C_TPM_ATMEL
depends on I2C_TPM
config I2C_TPM_GENERIC
bool "Generic I2C TPM Driver"
+config I2C_TPM_ATMEL
+ bool "ATMEL I2C TPM Driver"
+
config I2C_TPM_CR50
bool "CR50 I2C TPM Driver"
endchoice
+config DRIVER_TIS_DEFAULT
+ bool
+ depends on I2C_TPM
+ default n if MAINBOARD_HAS_I2C_TPM_ATMEL
+ default y
+
config DRIVER_TPM_I2C_BUS
hex "I2C TPM chip bus"
default 0x9 # FIXME, workaround for Kconfig BS
diff --git a/src/drivers/i2c/tpm/Makefile.inc b/src/drivers/i2c/tpm/Makefile.inc
index 7fcfc78d56..afcb33bb93 100644
--- a/src/drivers/i2c/tpm/Makefile.inc
+++ b/src/drivers/i2c/tpm/Makefile.inc
@@ -1,8 +1,13 @@
-ramstage-$(CONFIG_I2C_TPM) += tis.c
-romstage-$(CONFIG_I2C_TPM) += tis.c
-verstage-$(CONFIG_I2C_TPM) += tis.c
-bootblock-$(CONFIG_I2C_TPM) += tis.c
+ramstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c
+romstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c
+verstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c
+bootblock-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c
+
+ramstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c
+romstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c
+verstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c
+bootblock-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c
ramstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c
romstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c
diff --git a/src/drivers/i2c/tpm/tis_atmel.c b/src/drivers/i2c/tpm/tis_atmel.c
new file mode 100644
index 0000000000..7d8b7a17b8
--- /dev/null
+++ b/src/drivers/i2c/tpm/tis_atmel.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 Intel Corporation
+ *
+ * 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.
+ */
+
+#include <arch/early_variables.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <commonlib/endian.h>
+#include <console/console.h>
+#include <delay.h>
+#include <device/i2c.h>
+#include <endian.h>
+#include <lib.h>
+#include <tpm.h>
+#include <timer.h>
+
+#define RECV_TIMEOUT (1 * 1000) /* 1 second */
+#define XMIT_TIMEOUT (1 * 1000) /* 1 second */
+#define SLEEP_DURATION 1000 /* microseconds */
+
+struct tpm_output_header {
+ uint16_t tag;
+ uint32_t length;
+ uint32_t return_code;
+} __attribute__ ((packed));
+
+int tis_open(void)
+{
+ return 0;
+}
+
+int tis_close(void)
+{
+ return 0;
+}
+
+int tis_init(void)
+{
+ return 0;
+}
+
+int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
+ uint8_t *recvbuf, size_t *rbuf_len)
+{
+ size_t hdr_bytes;
+ struct tpm_output_header *header;
+ size_t max_recv_bytes;
+ size_t recv_bytes;
+ int status;
+ struct stopwatch sw;
+
+ ASSERT(sbuf_size >= 10);
+ if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) {
+ /* Display the TPM command */
+ if (sbuf_size >= 10)
+ printk(BIOS_DEBUG, "TPM Command: 0x%08x\n",
+ read_at_be32(sendbuf, sizeof(uint16_t)
+ + sizeof(uint32_t)));
+ hexdump(sendbuf, sbuf_size);
+ }
+
+ /* Send the command to the TPM */
+ stopwatch_init_msecs_expire(&sw, XMIT_TIMEOUT);
+ while (1) {
+ status = i2c_write_raw(CONFIG_DRIVER_TPM_I2C_BUS,
+ CONFIG_DRIVER_TPM_I2C_ADDR, (uint8_t *)sendbuf,
+ sbuf_size);
+ if ((status < 0) && (!stopwatch_expired(&sw)))
+ continue;
+ if (status < 0)
+ return status;
+ break;
+ }
+
+ /* Read the TPM response header */
+ max_recv_bytes = *rbuf_len;
+ ASSERT(max_recv_bytes >= sizeof(*header));
+ hdr_bytes = sizeof(*header);
+ header = (struct tpm_output_header *)recvbuf;
+ stopwatch_init_msecs_expire(&sw, RECV_TIMEOUT);
+ do {
+ status = i2c_read_raw(CONFIG_DRIVER_TPM_I2C_BUS,
+ CONFIG_DRIVER_TPM_I2C_ADDR, recvbuf, hdr_bytes);
+ if (status > 0)
+ break;
+ udelay(SLEEP_DURATION);
+ } while (!stopwatch_expired(&sw));
+ if (status != sizeof(*header))
+ return -1;
+
+ /* Determine the number of bytes remaining */
+ recv_bytes = min(be32_to_cpu(*(uint32_t *)&header->length),
+ max_recv_bytes);
+
+ /* Determine if there is additional response data */
+ if (recv_bytes > hdr_bytes) {
+ /* Display the TPM response */
+ if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES))
+ hexdump(recvbuf, hdr_bytes);
+
+ /* Read the full TPM response */
+ status = i2c_read_raw(CONFIG_DRIVER_TPM_I2C_BUS,
+ CONFIG_DRIVER_TPM_I2C_ADDR, recvbuf, recv_bytes);
+ if (status < 0)
+ return status;
+ }
+
+ /* Return the number of bytes received */
+ *rbuf_len = status;
+
+ /* Display the TPM response */
+ if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) {
+ printk(BIOS_DEBUG, "TPM Response: 0x%08x\n",
+ read_at_be32(recvbuf, sizeof(uint16_t)
+ + sizeof(uint32_t)));
+ hexdump(recvbuf, *rbuf_len);
+ }
+
+ /* Successful transfer */
+ return 0;
+}