uboot/drivers/tpm/tpm2_tis_spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Author:
   4 * Miquel Raynal <miquel.raynal@bootlin.com>
   5 *
   6 * Description:
   7 * SPI-level driver for TCG/TIS TPM (trusted platform module).
   8 * Specifications at www.trustedcomputinggroup.org
   9 *
  10 * This device driver implements the TPM interface as defined in
  11 * the TCG SPI protocol stack version 2.0.
  12 *
  13 * It is based on the U-Boot driver tpm_tis_infineon_i2c.c.
  14 */
  15
  16#include <common.h>
  17#include <dm.h>
  18#include <fdtdec.h>
  19#include <log.h>
  20#include <spi.h>
  21#include <tpm-v2.h>
  22#include <linux/bitops.h>
  23#include <linux/delay.h>
  24#include <linux/errno.h>
  25#include <linux/compiler.h>
  26#include <linux/types.h>
  27#include <linux/unaligned/be_byteshift.h>
  28#include <asm-generic/gpio.h>
  29
  30#include "tpm_tis.h"
  31#include "tpm_internal.h"
  32
  33#define MAX_SPI_FRAMESIZE 64
  34
  35/* Number of wait states to wait for */
  36#define TPM_WAIT_STATES 100
  37
  38/**
  39 * struct tpm_tis_chip_data - Non-discoverable TPM information
  40 *
  41 * @pcr_count:          Number of PCR per bank
  42 * @pcr_select_min:     Size in octets of the pcrSelect array
  43 */
  44struct tpm_tis_chip_data {
  45        unsigned int pcr_count;
  46        unsigned int pcr_select_min;
  47        unsigned int time_before_first_cmd_ms;
  48};
  49
  50/**
  51 * tpm_tis_spi_read() - Read from TPM register
  52 *
  53 * @addr: register address to read from
  54 * @buffer: provided by caller
  55 * @len: number of bytes to read
  56 *
  57 * Read len bytes from TPM register and put them into
  58 * buffer (little-endian format, i.e. first byte is put into buffer[0]).
  59 *
  60 * NOTE: TPM is big-endian for multi-byte values. Multi-byte
  61 * values have to be swapped.
  62 *
  63 * @return -EIO on error, 0 on success.
  64 */
  65static int tpm_tis_spi_xfer(struct udevice *dev, u32 addr, const u8 *out,
  66                            u8 *in, u16 len)
  67{
  68        struct spi_slave *slave = dev_get_parent_priv(dev);
  69        int transfer_len, ret;
  70        u8 tx_buf[MAX_SPI_FRAMESIZE];
  71        u8 rx_buf[MAX_SPI_FRAMESIZE];
  72
  73        if (in && out) {
  74                log(LOGC_NONE, LOGL_ERR, "%s: can't do full duplex\n",
  75                    __func__);
  76                return -EINVAL;
  77        }
  78
  79        ret = spi_claim_bus(slave);
  80        if (ret < 0) {
  81                log(LOGC_NONE, LOGL_ERR, "%s: could not claim bus\n", __func__);
  82                return ret;
  83        }
  84
  85        while (len) {
  86                /* Request */
  87                transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
  88                tx_buf[0] = (in ? BIT(7) : 0) | (transfer_len - 1);
  89                tx_buf[1] = 0xD4;
  90                tx_buf[2] = addr >> 8;
  91                tx_buf[3] = addr;
  92
  93                ret = spi_xfer(slave, 4 * 8, tx_buf, rx_buf, SPI_XFER_BEGIN);
  94                if (ret < 0) {
  95                        log(LOGC_NONE, LOGL_ERR,
  96                            "%s: spi request transfer failed (err: %d)\n",
  97                            __func__, ret);
  98                        goto release_bus;
  99                }
 100
 101                /* Wait state */
 102                if (!(rx_buf[3] & 0x1)) {
 103                        int i;
 104
 105                        for (i = 0; i < TPM_WAIT_STATES; i++) {
 106                                ret = spi_xfer(slave, 1 * 8, NULL, rx_buf, 0);
 107                                if (ret) {
 108                                        log(LOGC_NONE, LOGL_ERR,
 109                                            "%s: wait state failed: %d\n",
 110                                            __func__, ret);
 111                                        goto release_bus;
 112                                }
 113
 114                                if (rx_buf[0] & 0x1)
 115                                        break;
 116                        }
 117
 118                        if (i == TPM_WAIT_STATES) {
 119                                log(LOGC_NONE, LOGL_ERR,
 120                                    "%s: timeout on wait state\n", __func__);
 121                                ret = -ETIMEDOUT;
 122                                goto release_bus;
 123                        }
 124                }
 125
 126                /* Read/Write */
 127                if (out) {
 128                        memcpy(tx_buf, out, transfer_len);
 129                        out += transfer_len;
 130                }
 131
 132                ret = spi_xfer(slave, transfer_len * 8,
 133                               out ? tx_buf : NULL,
 134                               in ? rx_buf : NULL,
 135                               SPI_XFER_END);
 136                if (ret) {
 137                        log(LOGC_NONE, LOGL_ERR,
 138                            "%s: spi read transfer failed (err: %d)\n",
 139                            __func__, ret);
 140                        goto release_bus;
 141                }
 142
 143                if (in) {
 144                        memcpy(in, rx_buf, transfer_len);
 145                        in += transfer_len;
 146                }
 147
 148                len -= transfer_len;
 149        }
 150
 151release_bus:
 152        /* If an error occurred, release the chip by deasserting the CS */
 153        if (ret < 0)
 154                spi_xfer(slave, 0, NULL, NULL, SPI_XFER_END);
 155
 156        spi_release_bus(slave);
 157
 158        return ret;
 159}
 160
 161static int tpm_tis_spi_read(struct udevice *dev, u32 addr, u16 len, u8 *in)
 162{
 163        return tpm_tis_spi_xfer(dev, addr, NULL, in, len);
 164}
 165
 166static int tpm_tis_spi_read32(struct udevice *dev, u32 addr, u32 *result)
 167{
 168        __le32 result_le;
 169        int ret;
 170
 171        ret = tpm_tis_spi_read(dev, addr, sizeof(u32), (u8 *)&result_le);
 172        if (!ret)
 173                *result = le32_to_cpu(result_le);
 174
 175        return ret;
 176}
 177
 178
 179static int tpm_tis_spi_write(struct udevice *dev, u32 addr, u16 len, const u8 *out)
 180{
 181        return tpm_tis_spi_xfer(dev, addr, out, NULL, len);
 182}
 183
 184static int tpm_tis_spi_write32(struct udevice *dev, u32 addr, u32 value)
 185{
 186        __le32 value_le = cpu_to_le32(value);
 187
 188        return tpm_tis_spi_write(dev, addr, sizeof(value), (u8 *)&value_le);
 189}
 190
 191static int tpm_tis_wait_init(struct udevice *dev, int loc)
 192{
 193        struct tpm_chip *chip = dev_get_priv(dev);
 194        unsigned long start, stop;
 195        u8 status;
 196        int ret;
 197
 198        start = get_timer(0);
 199        stop = chip->timeout_b;
 200        do {
 201                mdelay(TPM_TIMEOUT_MS);
 202
 203                ret = tpm_tis_spi_read(dev, TPM_ACCESS(loc), 1, &status);
 204                if (ret)
 205                        break;
 206
 207                if (status & TPM_ACCESS_VALID)
 208                        return 0;
 209        } while (get_timer(start) < stop);
 210
 211        return -EIO;
 212}
 213
 214static struct tpm_tis_phy_ops phy_ops = {
 215        .read_bytes = tpm_tis_spi_read,
 216        .write_bytes = tpm_tis_spi_write,
 217        .read32 = tpm_tis_spi_read32,
 218        .write32 = tpm_tis_spi_write32,
 219};
 220
 221static int tpm_tis_spi_probe(struct udevice *dev)
 222{
 223        struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev);
 224        struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
 225        struct tpm_chip *chip = dev_get_priv(dev);
 226        int ret;
 227
 228        /* Use the TPM v2 stack */
 229        priv->version = TPM_V2;
 230
 231        if (CONFIG_IS_ENABLED(DM_GPIO)) {
 232                struct gpio_desc reset_gpio;
 233
 234                ret = gpio_request_by_name(dev, "reset-gpios", 0,
 235                                           &reset_gpio, GPIOD_IS_OUT);
 236                if (ret) {
 237                        /* legacy reset */
 238                        ret = gpio_request_by_name(dev, "gpio-reset", 0,
 239                                                   &reset_gpio, GPIOD_IS_OUT);
 240                        if (ret) {
 241                                log(LOGC_NONE, LOGL_NOTICE,
 242                                    "%s: missing reset GPIO\n", __func__);
 243                                goto init;
 244                        }
 245                        log(LOGC_NONE, LOGL_NOTICE,
 246                            "%s: gpio-reset is deprecated\n", __func__);
 247                }
 248                dm_gpio_set_value(&reset_gpio, 1);
 249                mdelay(1);
 250                dm_gpio_set_value(&reset_gpio, 0);
 251        }
 252init:
 253        /* Ensure a minimum amount of time elapsed since reset of the TPM */
 254        mdelay(drv_data->time_before_first_cmd_ms);
 255
 256        ret = tpm_tis_wait_init(dev, chip->locality);
 257        if (ret) {
 258                log(LOGC_DM, LOGL_ERR, "%s: no device found\n", __func__);
 259                return ret;
 260        }
 261
 262        tpm_tis_ops_register(dev, &phy_ops);
 263        ret = tpm_tis_init(dev);
 264        if (ret)
 265                goto err;
 266
 267        priv->pcr_count = drv_data->pcr_count;
 268        priv->pcr_select_min = drv_data->pcr_select_min;
 269        priv->version = TPM_V2;
 270
 271        return 0;
 272err:
 273        return -EINVAL;
 274}
 275
 276static int tpm_tis_spi_remove(struct udevice *udev)
 277{
 278        return tpm_tis_cleanup(udev);
 279}
 280
 281static const struct tpm_ops tpm_tis_spi_ops = {
 282        .open           = tpm_tis_open,
 283        .close          = tpm_tis_close,
 284        .get_desc       = tpm_tis_get_desc,
 285        .send           = tpm_tis_send,
 286        .recv           = tpm_tis_recv,
 287        .cleanup        = tpm_tis_cleanup,
 288};
 289
 290static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
 291        .pcr_count = 24,
 292        .pcr_select_min = 3,
 293        .time_before_first_cmd_ms = 30,
 294};
 295
 296static const struct udevice_id tpm_tis_spi_ids[] = {
 297        {
 298                .compatible = "tcg,tpm_tis-spi",
 299                .data = (ulong)&tpm_tis_std_chip_data,
 300        },
 301        { }
 302};
 303
 304U_BOOT_DRIVER(tpm_tis_spi) = {
 305        .name   = "tpm_tis_spi",
 306        .id     = UCLASS_TPM,
 307        .of_match = tpm_tis_spi_ids,
 308        .ops    = &tpm_tis_spi_ops,
 309        .probe  = tpm_tis_spi_probe,
 310        .remove = tpm_tis_spi_remove,
 311        .priv_auto      = sizeof(struct tpm_chip),
 312};
 313