[U-Boot] [PATCH 2/2] i2c: ST33ZP24 I2C TPM driver

Simon Glass sjg at chromium.org
Sat Jul 19 06:13:46 CEST 2014


Hi Jean-Luc,

On 9 July 2014 01:40, Jean-Luc BLANC <stmicroelectronics.tpm at 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 at 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


More information about the U-Boot mailing list