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