2 * Copyright (C) 2011 Infineon Technologies
3 * Copyright 2013 Google Inc.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but without any warranty; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
27 #include <device/i2c.h>
33 #include <console/console.h>
35 /* global structure for tpm chip data */
36 struct tpm_chip g_chip
;
38 #define TPM_CMD_COUNT_BYTE 2
39 #define TPM_CMD_ORDINAL_BYTE 6
40 #define TPM_VALID_STATUS (1 << 7)
47 printk(BIOS_DEBUG
, "tis_open() called twice.\n");
51 rc
= tpm_vendor_init(CONFIG_DRIVER_TPM_I2C_BUS
,
52 CONFIG_DRIVER_TPM_I2C_ADDR
);
67 tpm_vendor_cleanup(&g_chip
);
76 int bus
= CONFIG_DRIVER_TPM_I2C_BUS
;
77 int chip
= CONFIG_DRIVER_TPM_I2C_ADDR
;
81 long sw_run_duration
= 750;
84 * Probe TPM. Check if the TPM_ACCESS register's ValidSts bit is set(1)
85 * If the bit remains clear(0) then claim that init has failed.
87 stopwatch_init_msecs_expire(&sw
, sw_run_duration
);
89 ret
= i2c_readb(bus
, chip
, 0, &buf
);
90 if (!ret
&& (buf
& TPM_VALID_STATUS
)) {
91 sw_run_duration
= stopwatch_duration_msecs(&sw
);
94 } while (!stopwatch_expired(&sw
));
97 "%s: ValidSts bit %s(%d) in TPM_ACCESS register after %ld ms\n",
98 __func__
, (buf
& TPM_VALID_STATUS
) ? "set" : "clear",
99 (buf
& TPM_VALID_STATUS
) >> 7, sw_run_duration
);
102 * Claim failure if the ValidSts (bit 7) is clear.
104 if (!(buf
& TPM_VALID_STATUS
))
110 static ssize_t
tpm_transmit(const uint8_t *buf
, size_t bufsiz
)
113 uint32_t count
, ordinal
;
115 struct tpm_chip
*chip
= &g_chip
;
117 memcpy(&count
, buf
+ TPM_CMD_COUNT_BYTE
, sizeof(count
));
118 count
= be32_to_cpu(count
);
119 memcpy(&ordinal
, buf
+ TPM_CMD_ORDINAL_BYTE
, sizeof(ordinal
));
120 ordinal
= be32_to_cpu(ordinal
);
123 printk(BIOS_DEBUG
, "tpm_transmit: no data\n");
126 if (count
> bufsiz
) {
127 printk(BIOS_DEBUG
, "tpm_transmit: invalid count value %x %zx\n",
132 ASSERT(chip
->vendor
.send
);
133 rc
= chip
->vendor
.send(chip
, (uint8_t *) buf
, count
);
135 printk(BIOS_DEBUG
, "tpm_transmit: tpm_send error\n");
139 if (chip
->vendor
.irq
)
142 int timeout
= 2 * 60 * 1000; /* two minutes timeout */
144 ASSERT(chip
->vendor
.status
);
145 uint8_t status
= chip
->vendor
.status(chip
);
146 if ((status
& chip
->vendor
.req_complete_mask
) ==
147 chip
->vendor
.req_complete_val
) {
151 if ((status
== chip
->vendor
.req_canceled
)) {
152 printk(BIOS_DEBUG
, "tpm_transmit: Operation Canceled\n");
160 ASSERT(chip
->vendor
.cancel
);
161 chip
->vendor
.cancel(chip
);
162 printk(BIOS_DEBUG
, "tpm_transmit: Operation Timed out\n");
168 rc
= chip
->vendor
.recv(chip
, (uint8_t *) buf
, TPM_BUFSIZE
);
170 printk(BIOS_DEBUG
, "tpm_transmit: tpm_recv: error %d\n", rc
);
175 int tis_sendrecv(const uint8_t *sendbuf
, size_t sbuf_size
,
176 uint8_t *recvbuf
, size_t *rbuf_len
)
178 uint8_t buf
[TPM_BUFSIZE
];
180 if (sizeof(buf
) < sbuf_size
)
183 memcpy(buf
, sendbuf
, sbuf_size
);
185 int len
= tpm_transmit(buf
, sbuf_size
);
192 if (len
> *rbuf_len
) {
197 memcpy(recvbuf
, buf
, len
);