uboot/drivers/tpm/tpm_tis_lpc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2011 The Chromium OS Authors.
   4 */
   5
   6/*
   7 * The code in this file is based on the article "Writing a TPM Device Driver"
   8 * published on http://ptgmedia.pearsoncmg.com.
   9 *
  10 * One principal difference is that in the simplest config the other than 0
  11 * TPM localities do not get mapped by some devices (for instance, by Infineon
  12 * slb9635), so this driver provides access to locality 0 only.
  13 */
  14
  15#include <common.h>
  16#include <dm.h>
  17#include <mapmem.h>
  18#include <tpm-v1.h>
  19#include <asm/io.h>
  20
  21#define PREFIX "lpc_tpm: "
  22
  23enum i2c_chip_type {
  24        SLB9635,
  25        AT97SC3204,
  26};
  27
  28static const char * const chip_name[] = {
  29        [SLB9635] = "Infineon SLB9635 TT 1.2",
  30        [AT97SC3204] = "Atmel AT97SC3204",
  31};
  32
  33static const u32 chip_didvid[] = {
  34        [SLB9635] = 0xb15d1,
  35        [AT97SC3204] = 0x32041114,
  36};
  37
  38struct tpm_locality {
  39        u32 access;
  40        u8 padding0[4];
  41        u32 int_enable;
  42        u8 vector;
  43        u8 padding1[3];
  44        u32 int_status;
  45        u32 int_capability;
  46        u32 tpm_status;
  47        u8 padding2[8];
  48        u8 data;
  49        u8 padding3[3803];
  50        u32 did_vid;
  51        u8 rid;
  52        u8 padding4[251];
  53};
  54
  55struct tpm_tis_lpc_priv {
  56        struct tpm_locality *regs;
  57};
  58
  59/*
  60 * This pointer refers to the TPM chip, 5 of its localities are mapped as an
  61 * array.
  62 */
  63#define TPM_TOTAL_LOCALITIES    5
  64
  65/* Some registers' bit field definitions */
  66#define TIS_STS_VALID                  (1 << 7) /* 0x80 */
  67#define TIS_STS_COMMAND_READY          (1 << 6) /* 0x40 */
  68#define TIS_STS_TPM_GO                 (1 << 5) /* 0x20 */
  69#define TIS_STS_DATA_AVAILABLE         (1 << 4) /* 0x10 */
  70#define TIS_STS_EXPECT                 (1 << 3) /* 0x08 */
  71#define TIS_STS_RESPONSE_RETRY         (1 << 1) /* 0x02 */
  72
  73#define TIS_ACCESS_TPM_REG_VALID_STS   (1 << 7) /* 0x80 */
  74#define TIS_ACCESS_ACTIVE_LOCALITY     (1 << 5) /* 0x20 */
  75#define TIS_ACCESS_BEEN_SEIZED         (1 << 4) /* 0x10 */
  76#define TIS_ACCESS_SEIZE               (1 << 3) /* 0x08 */
  77#define TIS_ACCESS_PENDING_REQUEST     (1 << 2) /* 0x04 */
  78#define TIS_ACCESS_REQUEST_USE         (1 << 1) /* 0x02 */
  79#define TIS_ACCESS_TPM_ESTABLISHMENT   (1 << 0) /* 0x01 */
  80
  81#define TIS_STS_BURST_COUNT_MASK       (0xffff)
  82#define TIS_STS_BURST_COUNT_SHIFT      (8)
  83
  84 /* 1 second is plenty for anything TPM does. */
  85#define MAX_DELAY_US    (1000 * 1000)
  86
  87/* Retrieve burst count value out of the status register contents. */
  88static u16 burst_count(u32 status)
  89{
  90        return (status >> TIS_STS_BURST_COUNT_SHIFT) &
  91                        TIS_STS_BURST_COUNT_MASK;
  92}
  93
  94/* TPM access wrappers to support tracing */
  95static u8 tpm_read_byte(struct tpm_tis_lpc_priv *priv, const u8 *ptr)
  96{
  97        u8  ret = readb(ptr);
  98        debug(PREFIX "Read reg 0x%4.4x returns 0x%2.2x\n",
  99              (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret);
 100        return ret;
 101}
 102
 103static u32 tpm_read_word(struct tpm_tis_lpc_priv *priv, const u32 *ptr)
 104{
 105        u32  ret = readl(ptr);
 106        debug(PREFIX "Read reg 0x%4.4x returns 0x%8.8x\n",
 107              (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, ret);
 108        return ret;
 109}
 110
 111static void tpm_write_byte(struct tpm_tis_lpc_priv *priv, u8 value, u8 *ptr)
 112{
 113        debug(PREFIX "Write reg 0x%4.4x with 0x%2.2x\n",
 114              (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value);
 115        writeb(value, ptr);
 116}
 117
 118static void tpm_write_word(struct tpm_tis_lpc_priv *priv, u32 value,
 119                           u32 *ptr)
 120{
 121        debug(PREFIX "Write reg 0x%4.4x with 0x%8.8x\n",
 122              (u32)(uintptr_t)ptr - (u32)(uintptr_t)priv->regs, value);
 123        writel(value, ptr);
 124}
 125
 126/*
 127 * tis_wait_reg()
 128 *
 129 * Wait for at least a second for a register to change its state to match the
 130 * expected state. Normally the transition happens within microseconds.
 131 *
 132 * @reg - pointer to the TPM register
 133 * @mask - bitmask for the bitfield(s) to watch
 134 * @expected - value the field(s) are supposed to be set to
 135 *
 136 * Returns the register contents in case the expected value was found in the
 137 * appropriate register bits, or -ETIMEDOUT on timeout.
 138 */
 139static int tis_wait_reg(struct tpm_tis_lpc_priv *priv, u32 *reg, u8 mask,
 140                        u8 expected)
 141{
 142        u32 time_us = MAX_DELAY_US;
 143
 144        while (time_us > 0) {
 145                u32 value = tpm_read_word(priv, reg);
 146                if ((value & mask) == expected)
 147                        return value;
 148                udelay(1); /* 1 us */
 149                time_us--;
 150        }
 151
 152        return -ETIMEDOUT;
 153}
 154
 155/*
 156 * Probe the TPM device and try determining its manufacturer/device name.
 157 *
 158 * Returns 0 on success, -ve on error
 159 */
 160static int tpm_tis_lpc_probe(struct udevice *dev)
 161{
 162        struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
 163        fdt_addr_t addr;
 164        u32 didvid;
 165        ulong chip_type = dev_get_driver_data(dev);
 166
 167        addr = dev_read_addr(dev);
 168        if (addr == FDT_ADDR_T_NONE)
 169                return -EINVAL;
 170        priv->regs = map_sysmem(addr, 0);
 171        didvid = tpm_read_word(priv, &priv->regs[0].did_vid);
 172
 173        if (didvid != chip_didvid[chip_type]) {
 174                u32 vid, did;
 175                vid = didvid & 0xffff;
 176                did = (didvid >> 16) & 0xffff;
 177                debug("Invalid vendor/device ID %04x/%04x\n", vid, did);
 178                return -ENODEV;
 179        }
 180
 181        debug("Found TPM: %s\n", chip_name[chip_type]);
 182
 183        return 0;
 184}
 185
 186/*
 187 * tis_senddata()
 188 *
 189 * send the passed in data to the TPM device.
 190 *
 191 * @data - address of the data to send, byte by byte
 192 * @len - length of the data to send
 193 *
 194 * Returns 0 on success, -ve on error (in case the device does not accept
 195 * the entire command).
 196 */
 197static int tis_senddata(struct udevice *dev, const u8 *data, size_t len)
 198{
 199        struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
 200        struct tpm_locality *regs = priv->regs;
 201        u32 offset = 0;
 202        u16 burst = 0;
 203        u32 max_cycles = 0;
 204        u8 locality = 0;
 205        u32 value;
 206
 207        value = tis_wait_reg(priv, &regs[locality].tpm_status,
 208                             TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY);
 209        if (value == -ETIMEDOUT) {
 210                printf("%s:%d - failed to get 'command_ready' status\n",
 211                       __FILE__, __LINE__);
 212                return value;
 213        }
 214        burst = burst_count(value);
 215
 216        while (1) {
 217                unsigned count;
 218
 219                /* Wait till the device is ready to accept more data. */
 220                while (!burst) {
 221                        if (max_cycles++ == MAX_DELAY_US) {
 222                                printf("%s:%d failed to feed %zd bytes of %zd\n",
 223                                       __FILE__, __LINE__, len - offset, len);
 224                                return -ETIMEDOUT;
 225                        }
 226                        udelay(1);
 227                        burst = burst_count(tpm_read_word(priv,
 228                                        &regs[locality].tpm_status));
 229                }
 230
 231                max_cycles = 0;
 232
 233                /*
 234                 * Calculate number of bytes the TPM is ready to accept in one
 235                 * shot.
 236                 *
 237                 * We want to send the last byte outside of the loop (hence
 238                 * the -1 below) to make sure that the 'expected' status bit
 239                 * changes to zero exactly after the last byte is fed into the
 240                 * FIFO.
 241                 */
 242                count = min((size_t)burst, len - offset - 1);
 243                while (count--)
 244                        tpm_write_byte(priv, data[offset++],
 245                                       &regs[locality].data);
 246
 247                value = tis_wait_reg(priv, &regs[locality].tpm_status,
 248                                     TIS_STS_VALID, TIS_STS_VALID);
 249
 250                if ((value == -ETIMEDOUT) || !(value & TIS_STS_EXPECT)) {
 251                        printf("%s:%d TPM command feed overflow\n",
 252                               __FILE__, __LINE__);
 253                        return value == -ETIMEDOUT ? value : -EIO;
 254                }
 255
 256                burst = burst_count(value);
 257                if ((offset == (len - 1)) && burst) {
 258                        /*
 259                         * We need to be able to send the last byte to the
 260                         * device, so burst size must be nonzero before we
 261                         * break out.
 262                         */
 263                        break;
 264                }
 265        }
 266
 267        /* Send the last byte. */
 268        tpm_write_byte(priv, data[offset++], &regs[locality].data);
 269        /*
 270         * Verify that TPM does not expect any more data as part of this
 271         * command.
 272         */
 273        value = tis_wait_reg(priv, &regs[locality].tpm_status,
 274                             TIS_STS_VALID, TIS_STS_VALID);
 275        if ((value == -ETIMEDOUT) || (value & TIS_STS_EXPECT)) {
 276                printf("%s:%d unexpected TPM status 0x%x\n",
 277                       __FILE__, __LINE__, value);
 278                return value == -ETIMEDOUT ? value : -EIO;
 279        }
 280
 281        /* OK, sitting pretty, let's start the command execution. */
 282        tpm_write_word(priv, TIS_STS_TPM_GO, &regs[locality].tpm_status);
 283        return 0;
 284}
 285
 286/*
 287 * tis_readresponse()
 288 *
 289 * read the TPM device response after a command was issued.
 290 *
 291 * @buffer - address where to read the response, byte by byte.
 292 * @len - pointer to the size of buffer
 293 *
 294 * On success stores the number of received bytes to len and returns 0. On
 295 * errors (misformatted TPM data or synchronization problems) returns
 296 * -ve value.
 297 */
 298static int tis_readresponse(struct udevice *dev, u8 *buffer, size_t len)
 299{
 300        struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
 301        struct tpm_locality *regs = priv->regs;
 302        u16 burst;
 303        u32 value;
 304        u32 offset = 0;
 305        u8 locality = 0;
 306        const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
 307        u32 expected_count = len;
 308        int max_cycles = 0;
 309
 310        /* Wait for the TPM to process the command. */
 311        value = tis_wait_reg(priv, &regs[locality].tpm_status,
 312                              has_data, has_data);
 313        if (value == -ETIMEDOUT) {
 314                printf("%s:%d failed processing command\n",
 315                       __FILE__, __LINE__);
 316                return value;
 317        }
 318
 319        do {
 320                while ((burst = burst_count(value)) == 0) {
 321                        if (max_cycles++ == MAX_DELAY_US) {
 322                                printf("%s:%d TPM stuck on read\n",
 323                                       __FILE__, __LINE__);
 324                                return -EIO;
 325                        }
 326                        udelay(1);
 327                        value = tpm_read_word(priv, &regs[locality].tpm_status);
 328                }
 329
 330                max_cycles = 0;
 331
 332                while (burst-- && (offset < expected_count)) {
 333                        buffer[offset++] = tpm_read_byte(priv,
 334                                                &regs[locality].data);
 335
 336                        if (offset == 6) {
 337                                /*
 338                                 * We got the first six bytes of the reply,
 339                                 * let's figure out how many bytes to expect
 340                                 * total - it is stored as a 4 byte number in
 341                                 * network order, starting with offset 2 into
 342                                 * the body of the reply.
 343                                 */
 344                                u32 real_length;
 345                                memcpy(&real_length,
 346                                       buffer + 2,
 347                                       sizeof(real_length));
 348                                expected_count = be32_to_cpu(real_length);
 349
 350                                if ((expected_count < offset) ||
 351                                    (expected_count > len)) {
 352                                        printf("%s:%d bad response size %d\n",
 353                                               __FILE__, __LINE__,
 354                                               expected_count);
 355                                        return -ENOSPC;
 356                                }
 357                        }
 358                }
 359
 360                /* Wait for the next portion. */
 361                value = tis_wait_reg(priv, &regs[locality].tpm_status,
 362                                     TIS_STS_VALID, TIS_STS_VALID);
 363                if (value == -ETIMEDOUT) {
 364                        printf("%s:%d failed to read response\n",
 365                               __FILE__, __LINE__);
 366                        return value;
 367                }
 368
 369                if (offset == expected_count)
 370                        break;  /* We got all we needed. */
 371
 372        } while ((value & has_data) == has_data);
 373
 374        /*
 375         * Make sure we indeed read all there was. The TIS_STS_VALID bit is
 376         * known to be set.
 377         */
 378        if (value & TIS_STS_DATA_AVAILABLE) {
 379                printf("%s:%d wrong receive status %x\n",
 380                       __FILE__, __LINE__, value);
 381                return -EBADMSG;
 382        }
 383
 384        /* Tell the TPM that we are done. */
 385        tpm_write_word(priv, TIS_STS_COMMAND_READY,
 386                       &regs[locality].tpm_status);
 387
 388        return offset;
 389}
 390
 391static int tpm_tis_lpc_close(struct udevice *dev)
 392{
 393        struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
 394        struct tpm_locality *regs = priv->regs;
 395        u8 locality = 0;
 396
 397        if (tpm_read_word(priv, &regs[locality].access) &
 398            TIS_ACCESS_ACTIVE_LOCALITY) {
 399                tpm_write_word(priv, TIS_ACCESS_ACTIVE_LOCALITY,
 400                               &regs[locality].access);
 401
 402                if (tis_wait_reg(priv, &regs[locality].access,
 403                                 TIS_ACCESS_ACTIVE_LOCALITY, 0) == -ETIMEDOUT) {
 404                        printf("%s:%d - failed to release locality %d\n",
 405                               __FILE__, __LINE__, locality);
 406                        return -ETIMEDOUT;
 407                }
 408        }
 409        return 0;
 410}
 411
 412static int tpm_tis_lpc_open(struct udevice *dev)
 413{
 414        struct tpm_tis_lpc_priv *priv = dev_get_priv(dev);
 415        struct tpm_locality *regs = priv->regs;
 416        u8 locality = 0; /* we use locality zero for everything. */
 417        int ret;
 418
 419        ret = tpm_tis_lpc_close(dev);
 420        if (ret) {
 421                printf("%s: Failed to close TPM\n", __func__);
 422                return ret;
 423        }
 424
 425        /* now request access to locality. */
 426        tpm_write_word(priv, TIS_ACCESS_REQUEST_USE, &regs[locality].access);
 427
 428        /* did we get a lock? */
 429        ret = tis_wait_reg(priv, &regs[locality].access,
 430                         TIS_ACCESS_ACTIVE_LOCALITY,
 431                         TIS_ACCESS_ACTIVE_LOCALITY);
 432        if (ret == -ETIMEDOUT) {
 433                printf("%s:%d - failed to lock locality %d\n",
 434                       __FILE__, __LINE__, locality);
 435                return ret;
 436        }
 437
 438        tpm_write_word(priv, TIS_STS_COMMAND_READY,
 439                       &regs[locality].tpm_status);
 440
 441        return 0;
 442}
 443
 444static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size)
 445{
 446        ulong chip_type = dev_get_driver_data(dev);
 447
 448        if (size < 50)
 449                return -ENOSPC;
 450
 451        return snprintf(buf, size, "1.2 TPM (%s)",
 452                        chip_name[chip_type]);
 453}
 454
 455
 456static const struct tpm_ops tpm_tis_lpc_ops = {
 457        .open           = tpm_tis_lpc_open,
 458        .close          = tpm_tis_lpc_close,
 459        .get_desc       = tpm_tis_get_desc,
 460        .send           = tis_senddata,
 461        .recv           = tis_readresponse,
 462};
 463
 464static const struct udevice_id tpm_tis_lpc_ids[] = {
 465        { .compatible = "infineon,slb9635lpc", .data = SLB9635 },
 466        { .compatible = "atmel,at97sc3204", .data = AT97SC3204 },
 467        { }
 468};
 469
 470U_BOOT_DRIVER(tpm_tis_lpc) = {
 471        .name   = "tpm_tis_lpc",
 472        .id     = UCLASS_TPM,
 473        .of_match = tpm_tis_lpc_ids,
 474        .ops    = &tpm_tis_lpc_ops,
 475        .probe  = tpm_tis_lpc_probe,
 476        .priv_auto_alloc_size = sizeof(struct tpm_tis_lpc_priv),
 477};
 478