
Hi Jean-Luc,
On 9 July 2014 01:40, Jean-Luc BLANC stmicroelectronics.tpm@gmail.com wrote:
This driver add support for STMicroelectronics ST33ZP24 I2C TPM.
README | 6 + drivers/tpm/Makefile | 1 + drivers/tpm/tpm_i2c_stm_st33.c | 633 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 640 insertions(+) create mode 100644 drivers/tpm/tpm_i2c_stm_st33.c
diff --git a/README b/README index a4aa28a..c4463d8 100644 --- a/README +++ b/README @@ -1426,6 +1426,12 @@ The following options need to be configured: TPM1_SPI_CS Define SPI Chip Select ID connected to TPM
CONFIG_TPM_ST_I2C
Support I2C STMicroelectronics TPM. Require I2C support
CONFIG_TPM_I2C_BUS
Define the i2c bus number for the TPM device
- USB Support: At the moment only the UHCI host controller is supported (PIP405, MIP405, MPC5200); define
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 1ee707e..29e1f80 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o obj-$(CONFIG_TPM_ST_SPI) += tpm_spi_stm_st33.o +obj-$(CONFIG_TPM_ST_I2C) += tpm_i2c_stm_st33.o diff --git a/drivers/tpm/tpm_i2c_stm_st33.c b/drivers/tpm/tpm_i2c_stm_st33.c new file mode 100644 index 0000000..6e20f8c --- /dev/null +++ b/drivers/tpm/tpm_i2c_stm_st33.c @@ -0,0 +1,633 @@ +/*
- STMicroelectronics TPM I2C UBOOT Linux driver for TPM ST33ZP24
- Copyright (C) 2014 STMicroelectronics
- Description: Device driver for ST33ZP24 I2C TPM TCG.
- This device driver implements the TPM interface as defined in
- the TCG TPM Interface Spec version 1.21, revision 1.0 and the
- STMicroelectronics I2C Protocol Stack Specification version 1.2.0.
- SPDX-License-Identifier: GPL-2.0+
- @Author: Jean-Luc BLANC jean-luc.blanc@st.com
- @File: tpm_i2c_stm_st33.c
- */
+#include <common.h> +#include <i2c.h> +#include <linux/types.h> +#include <tpm.h> +#include <errno.h> +#include <asm/unaligned.h>
+#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 +#define LOCALITY0_I2C_ADDR 0x13 +#define LOCALITY4_I2C_ADDR 0x1B
If the chips have a lot of common defines / functions, please put them in a common header file/interface. Duplicated code creates problems for refactoring later.
+/* Index of Count field in TPM response buffer */ +#define TPM_RSP_SIZE_BYTE 2
+/* Maximum command duration */ +#define TPM_MAX_COMMAND_DURATION_MS 120000
+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_LOCTPM_BUFSIZE4SOFTRELEASE_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_MS = 750, /* ms */
TIS_LONG_TIMEOUT_MS = 2000, /* 2 sec */
+};
+/**
- @addr: TPM I2C address
- @i2c_bus: I2C bus ID the TPM is connected to
- @is_open: TPM connection establishment information
- @locality: active locality of the TPM (0 OR 4)
- @buf: command/response buffer
- @timeout_*: timeouts for TPM states changes
- @duration: maximum time for a TPM command processing
- */
+struct tpm_chip {
uint addr;
uint i2c_bus;
int is_open;
u8 buf[TPM_BUFSIZE];
int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */
unsigned long duration; /* msec */
+};
+static struct tpm_chip tpm_dev;
+/*
- write8_reg(): Send byte to the TIS register according to I2C TPM protocol.
- @tpm_register, the tpm tis register where the data should be written
- @tpm_data, the tpm_data to write inside the tpm_register
- @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,
const 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);
+}
I'm wondering whether the I2C/SPI size should go in a separate lower-level routine which understands how to communicate with either? What do you think? Or perhaps that will just make things complicated?
Regards, Simonn