blob: 046e282ccc628b710a31e0523193db1884a5b240 [file] [log] [blame]
Rong Changf6267992013-04-12 10:44:57 +00001/*
2 * Copyright (C) 2011 Infineon Technologies
3 *
4 * Authors:
5 * Peter Huewe <huewe.external@infineon.com>
6 *
7 * Description:
8 * Device driver for TCG/TCPA TPM (trusted platform module).
9 * Specifications at www.trustedcomputinggroup.org
10 *
11 * This device driver implements the TPM interface as defined in
12 * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
13 * Infineon I2C Protocol Stack Specification v0.20.
14 *
15 * It is based on the Linux kernel driver tpm.c from Leendert van
16 * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
17 *
18 * Version: 2.1.1
19 *
Simon Glass07470d62015-08-22 18:31:21 -060020 * SPDX-License-Identifier: GPL-2.0
Rong Changf6267992013-04-12 10:44:57 +000021 */
22
23#include <common.h>
Simon Glassf90acf12015-05-04 11:30:59 -060024#include <dm.h>
Vincent Palatinec34fa52013-04-12 11:04:36 +000025#include <fdtdec.h>
Masahiro Yamadaafc366f2014-11-26 16:00:58 +090026#include <linux/compiler.h>
Rong Changf6267992013-04-12 10:44:57 +000027#include <i2c.h>
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000028#include <tpm.h>
29#include <asm-generic/errno.h>
Rong Changf6267992013-04-12 10:44:57 +000030#include <linux/types.h>
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000031#include <linux/unaligned/be_byteshift.h>
Rong Changf6267992013-04-12 10:44:57 +000032
Simon Glass4cd7b782015-08-22 18:31:22 -060033#include "tpm_tis_i2c.h"
Rong Changf6267992013-04-12 10:44:57 +000034
Vincent Palatinec34fa52013-04-12 11:04:36 +000035DECLARE_GLOBAL_DATA_PTR;
36
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000037/* Max number of iterations after i2c NAK */
38#define MAX_COUNT 3
39
40/*
41 * Max number of iterations after i2c NAK for 'long' commands
42 *
43 * We need this especially for sending TPM_READY, since the cleanup after the
Rong Changf6267992013-04-12 10:44:57 +000044 * transtion to the ready state may take some time, but it is unpredictable
45 * how long it will take.
46 */
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000047#define MAX_COUNT_LONG 50
Rong Changf6267992013-04-12 10:44:57 +000048
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000049#define SLEEP_DURATION 60 /* in usec */
50#define SLEEP_DURATION_LONG 210 /* in usec */
51
52#define TPM_HEADER_SIZE 10
53
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000054enum tis_access {
55 TPM_ACCESS_VALID = 0x80,
56 TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
57 TPM_ACCESS_REQUEST_PENDING = 0x04,
58 TPM_ACCESS_REQUEST_USE = 0x02,
59};
60
61enum tis_status {
62 TPM_STS_VALID = 0x80,
63 TPM_STS_COMMAND_READY = 0x40,
64 TPM_STS_GO = 0x20,
65 TPM_STS_DATA_AVAIL = 0x10,
66 TPM_STS_DATA_EXPECT = 0x08,
67};
68
69enum tis_defaults {
70 TIS_SHORT_TIMEOUT = 750, /* ms */
71 TIS_LONG_TIMEOUT = 2000, /* ms */
72};
Rong Changf6267992013-04-12 10:44:57 +000073
74/* expected value for DIDVID register */
Vincent Palatinec34fa52013-04-12 11:04:36 +000075#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L
76#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L
77
Vincent Palatinec34fa52013-04-12 11:04:36 +000078static const char * const chip_name[] = {
79 [SLB9635] = "slb9635tt",
80 [SLB9645] = "slb9645tt",
81 [UNKNOWN] = "unknown/fallback to slb9635",
82};
Rong Changf6267992013-04-12 10:44:57 +000083
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +000084#define TPM_ACCESS(l) (0x0000 | ((l) << 4))
85#define TPM_STS(l) (0x0001 | ((l) << 4))
86#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4))
87#define TPM_DID_VID(l) (0x0006 | ((l) << 4))
88
Simon Glass4cd7b782015-08-22 18:31:22 -060089enum tpm_duration {
90 TPM_SHORT = 0,
91 TPM_MEDIUM = 1,
92 TPM_LONG = 2,
93 TPM_UNDEFINED,
94};
95
96/* Extended error numbers from linux (see errno.h) */
97#define ECANCELED 125 /* Operation Canceled */
98
99/* Timer frequency. Corresponds to msec timer resolution*/
100#define HZ 1000
101
102#define TPM_MAX_ORDINAL 243
103#define TPM_MAX_PROTECTED_ORDINAL 12
104#define TPM_PROTECTED_ORDINAL_MASK 0xFF
105
106#define TPM_CMD_COUNT_BYTE 2
107#define TPM_CMD_ORDINAL_BYTE 6
108
109/*
110 * Array with one entry per ordinal defining the maximum amount
111 * of time the chip could take to return the result. The ordinal
112 * designation of short, medium or long is defined in a table in
113 * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
114 * values of the SHORT, MEDIUM, and LONG durations are retrieved
115 * from the chip during initialization with a call to tpm_get_timeouts.
116 */
117static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
118 TPM_UNDEFINED, /* 0 */
119 TPM_UNDEFINED,
120 TPM_UNDEFINED,
121 TPM_UNDEFINED,
122 TPM_UNDEFINED,
123 TPM_UNDEFINED, /* 5 */
124 TPM_UNDEFINED,
125 TPM_UNDEFINED,
126 TPM_UNDEFINED,
127 TPM_UNDEFINED,
128 TPM_SHORT, /* 10 */
129 TPM_SHORT,
130};
131
132static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
133 TPM_UNDEFINED, /* 0 */
134 TPM_UNDEFINED,
135 TPM_UNDEFINED,
136 TPM_UNDEFINED,
137 TPM_UNDEFINED,
138 TPM_UNDEFINED, /* 5 */
139 TPM_UNDEFINED,
140 TPM_UNDEFINED,
141 TPM_UNDEFINED,
142 TPM_UNDEFINED,
143 TPM_SHORT, /* 10 */
144 TPM_SHORT,
145 TPM_MEDIUM,
146 TPM_LONG,
147 TPM_LONG,
148 TPM_MEDIUM, /* 15 */
149 TPM_SHORT,
150 TPM_SHORT,
151 TPM_MEDIUM,
152 TPM_LONG,
153 TPM_SHORT, /* 20 */
154 TPM_SHORT,
155 TPM_MEDIUM,
156 TPM_MEDIUM,
157 TPM_MEDIUM,
158 TPM_SHORT, /* 25 */
159 TPM_SHORT,
160 TPM_MEDIUM,
161 TPM_SHORT,
162 TPM_SHORT,
163 TPM_MEDIUM, /* 30 */
164 TPM_LONG,
165 TPM_MEDIUM,
166 TPM_SHORT,
167 TPM_SHORT,
168 TPM_SHORT, /* 35 */
169 TPM_MEDIUM,
170 TPM_MEDIUM,
171 TPM_UNDEFINED,
172 TPM_UNDEFINED,
173 TPM_MEDIUM, /* 40 */
174 TPM_LONG,
175 TPM_MEDIUM,
176 TPM_SHORT,
177 TPM_SHORT,
178 TPM_SHORT, /* 45 */
179 TPM_SHORT,
180 TPM_SHORT,
181 TPM_SHORT,
182 TPM_LONG,
183 TPM_MEDIUM, /* 50 */
184 TPM_MEDIUM,
185 TPM_UNDEFINED,
186 TPM_UNDEFINED,
187 TPM_UNDEFINED,
188 TPM_UNDEFINED, /* 55 */
189 TPM_UNDEFINED,
190 TPM_UNDEFINED,
191 TPM_UNDEFINED,
192 TPM_UNDEFINED,
193 TPM_MEDIUM, /* 60 */
194 TPM_MEDIUM,
195 TPM_MEDIUM,
196 TPM_SHORT,
197 TPM_SHORT,
198 TPM_MEDIUM, /* 65 */
199 TPM_UNDEFINED,
200 TPM_UNDEFINED,
201 TPM_UNDEFINED,
202 TPM_UNDEFINED,
203 TPM_SHORT, /* 70 */
204 TPM_SHORT,
205 TPM_UNDEFINED,
206 TPM_UNDEFINED,
207 TPM_UNDEFINED,
208 TPM_UNDEFINED, /* 75 */
209 TPM_UNDEFINED,
210 TPM_UNDEFINED,
211 TPM_UNDEFINED,
212 TPM_UNDEFINED,
213 TPM_LONG, /* 80 */
214 TPM_UNDEFINED,
215 TPM_MEDIUM,
216 TPM_LONG,
217 TPM_SHORT,
218 TPM_UNDEFINED, /* 85 */
219 TPM_UNDEFINED,
220 TPM_UNDEFINED,
221 TPM_UNDEFINED,
222 TPM_UNDEFINED,
223 TPM_SHORT, /* 90 */
224 TPM_SHORT,
225 TPM_SHORT,
226 TPM_SHORT,
227 TPM_SHORT,
228 TPM_UNDEFINED, /* 95 */
229 TPM_UNDEFINED,
230 TPM_UNDEFINED,
231 TPM_UNDEFINED,
232 TPM_UNDEFINED,
233 TPM_MEDIUM, /* 100 */
234 TPM_SHORT,
235 TPM_SHORT,
236 TPM_UNDEFINED,
237 TPM_UNDEFINED,
238 TPM_UNDEFINED, /* 105 */
239 TPM_UNDEFINED,
240 TPM_UNDEFINED,
241 TPM_UNDEFINED,
242 TPM_UNDEFINED,
243 TPM_SHORT, /* 110 */
244 TPM_SHORT,
245 TPM_SHORT,
246 TPM_SHORT,
247 TPM_SHORT,
248 TPM_SHORT, /* 115 */
249 TPM_SHORT,
250 TPM_SHORT,
251 TPM_UNDEFINED,
252 TPM_UNDEFINED,
253 TPM_LONG, /* 120 */
254 TPM_LONG,
255 TPM_MEDIUM,
256 TPM_UNDEFINED,
257 TPM_SHORT,
258 TPM_SHORT, /* 125 */
259 TPM_SHORT,
260 TPM_LONG,
261 TPM_SHORT,
262 TPM_SHORT,
263 TPM_SHORT, /* 130 */
264 TPM_MEDIUM,
265 TPM_UNDEFINED,
266 TPM_SHORT,
267 TPM_MEDIUM,
268 TPM_UNDEFINED, /* 135 */
269 TPM_UNDEFINED,
270 TPM_UNDEFINED,
271 TPM_UNDEFINED,
272 TPM_UNDEFINED,
273 TPM_SHORT, /* 140 */
274 TPM_SHORT,
275 TPM_UNDEFINED,
276 TPM_UNDEFINED,
277 TPM_UNDEFINED,
278 TPM_UNDEFINED, /* 145 */
279 TPM_UNDEFINED,
280 TPM_UNDEFINED,
281 TPM_UNDEFINED,
282 TPM_UNDEFINED,
283 TPM_SHORT, /* 150 */
284 TPM_MEDIUM,
285 TPM_MEDIUM,
286 TPM_SHORT,
287 TPM_SHORT,
288 TPM_UNDEFINED, /* 155 */
289 TPM_UNDEFINED,
290 TPM_UNDEFINED,
291 TPM_UNDEFINED,
292 TPM_UNDEFINED,
293 TPM_SHORT, /* 160 */
294 TPM_SHORT,
295 TPM_SHORT,
296 TPM_SHORT,
297 TPM_UNDEFINED,
298 TPM_UNDEFINED, /* 165 */
299 TPM_UNDEFINED,
300 TPM_UNDEFINED,
301 TPM_UNDEFINED,
302 TPM_UNDEFINED,
303 TPM_LONG, /* 170 */
304 TPM_UNDEFINED,
305 TPM_UNDEFINED,
306 TPM_UNDEFINED,
307 TPM_UNDEFINED,
308 TPM_UNDEFINED, /* 175 */
309 TPM_UNDEFINED,
310 TPM_UNDEFINED,
311 TPM_UNDEFINED,
312 TPM_UNDEFINED,
313 TPM_MEDIUM, /* 180 */
314 TPM_SHORT,
315 TPM_MEDIUM,
316 TPM_MEDIUM,
317 TPM_MEDIUM,
318 TPM_MEDIUM, /* 185 */
319 TPM_SHORT,
320 TPM_UNDEFINED,
321 TPM_UNDEFINED,
322 TPM_UNDEFINED,
323 TPM_UNDEFINED, /* 190 */
324 TPM_UNDEFINED,
325 TPM_UNDEFINED,
326 TPM_UNDEFINED,
327 TPM_UNDEFINED,
328 TPM_UNDEFINED, /* 195 */
329 TPM_UNDEFINED,
330 TPM_UNDEFINED,
331 TPM_UNDEFINED,
332 TPM_UNDEFINED,
333 TPM_SHORT, /* 200 */
334 TPM_UNDEFINED,
335 TPM_UNDEFINED,
336 TPM_UNDEFINED,
337 TPM_SHORT,
338 TPM_SHORT, /* 205 */
339 TPM_SHORT,
340 TPM_SHORT,
341 TPM_SHORT,
342 TPM_SHORT,
343 TPM_MEDIUM, /* 210 */
344 TPM_UNDEFINED,
345 TPM_MEDIUM,
346 TPM_MEDIUM,
347 TPM_MEDIUM,
348 TPM_UNDEFINED, /* 215 */
349 TPM_MEDIUM,
350 TPM_UNDEFINED,
351 TPM_UNDEFINED,
352 TPM_SHORT,
353 TPM_SHORT, /* 220 */
354 TPM_SHORT,
355 TPM_SHORT,
356 TPM_SHORT,
357 TPM_SHORT,
358 TPM_UNDEFINED, /* 225 */
359 TPM_UNDEFINED,
360 TPM_UNDEFINED,
361 TPM_UNDEFINED,
362 TPM_UNDEFINED,
363 TPM_SHORT, /* 230 */
364 TPM_LONG,
365 TPM_MEDIUM,
366 TPM_UNDEFINED,
367 TPM_UNDEFINED,
368 TPM_UNDEFINED, /* 235 */
369 TPM_UNDEFINED,
370 TPM_UNDEFINED,
371 TPM_UNDEFINED,
372 TPM_UNDEFINED,
373 TPM_SHORT, /* 240 */
374 TPM_UNDEFINED,
375 TPM_MEDIUM,
376};
377
Simon Glass4cd7b782015-08-22 18:31:22 -0600378static struct tpm_chip g_chip;
379
Rong Changf6267992013-04-12 10:44:57 +0000380/*
381 * iic_tpm_read() - read from TPM register
382 * @addr: register address to read from
383 * @buffer: provided by caller
384 * @len: number of bytes to read
385 *
386 * Read len bytes from TPM register and put them into
387 * buffer (little-endian format, i.e. first byte is put into buffer[0]).
388 *
389 * NOTE: TPM is big-endian for multi-byte values. Multi-byte
390 * values have to be swapped.
391 *
392 * Return -EIO on error, 0 on success.
393 */
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000394static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
Rong Changf6267992013-04-12 10:44:57 +0000395{
396 int rc;
397 int count;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000398 uint32_t addrbuf = addr;
Rong Changf6267992013-04-12 10:44:57 +0000399
Simon Glass13932b02015-08-22 18:31:25 -0600400 if ((g_chip.chip_type == SLB9635) || (g_chip.chip_type == UNKNOWN)) {
Vincent Palatinec34fa52013-04-12 11:04:36 +0000401 /* slb9635 protocol should work in both cases */
402 for (count = 0; count < MAX_COUNT; count++) {
Simon Glass13932b02015-08-22 18:31:25 -0600403 rc = dm_i2c_write(g_chip.dev, 0, (uchar *)&addrbuf, 1);
Vincent Palatinec34fa52013-04-12 11:04:36 +0000404 if (rc == 0)
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000405 break; /* Success, break to skip sleep */
Vincent Palatinec34fa52013-04-12 11:04:36 +0000406 udelay(SLEEP_DURATION);
407 }
Vincent Palatinec34fa52013-04-12 11:04:36 +0000408 if (rc)
409 return -rc;
410
411 /* After the TPM has successfully received the register address
412 * it needs some time, thus we're sleeping here again, before
413 * retrieving the data
414 */
415 for (count = 0; count < MAX_COUNT; count++) {
416 udelay(SLEEP_DURATION);
Simon Glass13932b02015-08-22 18:31:25 -0600417 rc = dm_i2c_read(g_chip.dev, 0, buffer, len);
Vincent Palatinec34fa52013-04-12 11:04:36 +0000418 if (rc == 0)
419 break; /* success, break to skip sleep */
420 }
421 } else {
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000422 /*
423 * Use a combined read for newer chips.
424 * Unfortunately the smbus functions are not suitable due to
Vincent Palatinec34fa52013-04-12 11:04:36 +0000425 * the 32 byte limit of the smbus.
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000426 * Retries should usually not be needed, but are kept just to
Vincent Palatinec34fa52013-04-12 11:04:36 +0000427 * be safe on the safe side.
428 */
429 for (count = 0; count < MAX_COUNT; count++) {
Simon Glass13932b02015-08-22 18:31:25 -0600430 rc = dm_i2c_read(g_chip.dev, addr, buffer, len);
Vincent Palatinec34fa52013-04-12 11:04:36 +0000431 if (rc == 0)
432 break; /* break here to skip sleep */
433 udelay(SLEEP_DURATION);
434 }
Rong Changf6267992013-04-12 10:44:57 +0000435 }
436
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000437 /* Take care of 'guard time' */
Vincent Palatinec34fa52013-04-12 11:04:36 +0000438 udelay(SLEEP_DURATION);
Rong Changf6267992013-04-12 10:44:57 +0000439 if (rc)
440 return -rc;
441
442 return 0;
443}
444
445static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000446 unsigned int sleep_time, u8 max_count)
Rong Changf6267992013-04-12 10:44:57 +0000447{
448 int rc = 0;
449 int count;
450
Rong Changf6267992013-04-12 10:44:57 +0000451 for (count = 0; count < max_count; count++) {
Simon Glass13932b02015-08-22 18:31:25 -0600452 rc = dm_i2c_write(g_chip.dev, addr, buffer, len);
Rong Changf6267992013-04-12 10:44:57 +0000453 if (rc == 0)
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000454 break; /* Success, break to skip sleep */
Rong Changf6267992013-04-12 10:44:57 +0000455 udelay(sleep_time);
456 }
457
Vincent Palatinec34fa52013-04-12 11:04:36 +0000458 /* take care of 'guard time' */
Simon Glassf90acf12015-05-04 11:30:59 -0600459 udelay(sleep_time);
Rong Changf6267992013-04-12 10:44:57 +0000460 if (rc)
461 return -rc;
462
463 return 0;
464}
465
466/*
467 * iic_tpm_write() - write to TPM register
468 * @addr: register address to write to
469 * @buffer: containing data to be written
470 * @len: number of bytes to write
471 *
472 * Write len bytes from provided buffer to TPM register (little
473 * endian format, i.e. buffer[0] is written as first byte).
474 *
475 * NOTE: TPM is big-endian for multi-byte values. Multi-byte
476 * values have to be swapped.
477 *
478 * NOTE: use this function instead of the iic_tpm_write_generic function.
479 *
480 * Return -EIO on error, 0 on success
481 */
482static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
483{
484 return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION,
485 MAX_COUNT);
486}
487
488/*
489 * This function is needed especially for the cleanup situation after
490 * sending TPM_READY
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000491 */
Rong Changf6267992013-04-12 10:44:57 +0000492static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
493{
494 return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG,
495 MAX_COUNT_LONG);
496}
497
Rong Changf6267992013-04-12 10:44:57 +0000498static int check_locality(struct tpm_chip *chip, int loc)
499{
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000500 const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID;
Rong Changf6267992013-04-12 10:44:57 +0000501 u8 buf;
502 int rc;
503
504 rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
505 if (rc < 0)
506 return rc;
507
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000508 if ((buf & mask) == mask) {
Simon Glass7c735372015-08-22 18:31:24 -0600509 chip->locality = loc;
Rong Changf6267992013-04-12 10:44:57 +0000510 return loc;
511 }
512
513 return -1;
514}
515
516static void release_locality(struct tpm_chip *chip, int loc, int force)
517{
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000518 const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID;
Rong Changf6267992013-04-12 10:44:57 +0000519 u8 buf;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000520
Rong Changf6267992013-04-12 10:44:57 +0000521 if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
522 return;
523
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000524 if (force || (buf & mask) == mask) {
Rong Changf6267992013-04-12 10:44:57 +0000525 buf = TPM_ACCESS_ACTIVE_LOCALITY;
526 iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
527 }
528}
529
530static int request_locality(struct tpm_chip *chip, int loc)
531{
532 unsigned long start, stop;
533 u8 buf = TPM_ACCESS_REQUEST_USE;
Simon Glassf90acf12015-05-04 11:30:59 -0600534 int rc;
Rong Changf6267992013-04-12 10:44:57 +0000535
536 if (check_locality(chip, loc) >= 0)
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000537 return loc; /* We already have the locality */
Rong Changf6267992013-04-12 10:44:57 +0000538
Simon Glassf90acf12015-05-04 11:30:59 -0600539 rc = iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
540 if (rc)
541 return rc;
Rong Changf6267992013-04-12 10:44:57 +0000542
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000543 /* Wait for burstcount */
Rong Changf6267992013-04-12 10:44:57 +0000544 start = get_timer(0);
Simon Glass7c735372015-08-22 18:31:24 -0600545 stop = chip->timeout_a;
Rong Changf6267992013-04-12 10:44:57 +0000546 do {
547 if (check_locality(chip, loc) >= 0)
548 return loc;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000549 udelay(TPM_TIMEOUT * 1000);
Rong Changf6267992013-04-12 10:44:57 +0000550 } while (get_timer(start) < stop);
551
552 return -1;
553}
554
555static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
556{
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000557 /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */
Rong Changf6267992013-04-12 10:44:57 +0000558 u8 buf;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000559
Simon Glass7c735372015-08-22 18:31:24 -0600560 if (iic_tpm_read(TPM_STS(chip->locality), &buf, 1) < 0)
Rong Changf6267992013-04-12 10:44:57 +0000561 return 0;
562 else
563 return buf;
564}
565
566static void tpm_tis_i2c_ready(struct tpm_chip *chip)
567{
Simon Glassf90acf12015-05-04 11:30:59 -0600568 int rc;
569
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000570 /* This causes the current command to be aborted */
Rong Changf6267992013-04-12 10:44:57 +0000571 u8 buf = TPM_STS_COMMAND_READY;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000572
Simon Glassf90acf12015-05-04 11:30:59 -0600573 debug("%s\n", __func__);
Simon Glass7c735372015-08-22 18:31:24 -0600574 rc = iic_tpm_write_long(TPM_STS(chip->locality), &buf, 1);
Simon Glassf90acf12015-05-04 11:30:59 -0600575 if (rc)
576 debug("%s: rc=%d\n", __func__, rc);
Rong Changf6267992013-04-12 10:44:57 +0000577}
578
579static ssize_t get_burstcount(struct tpm_chip *chip)
580{
581 unsigned long start, stop;
582 ssize_t burstcnt;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000583 u8 addr, buf[3];
Rong Changf6267992013-04-12 10:44:57 +0000584
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000585 /* Wait for burstcount */
586 /* XXX: Which timeout value? Spec has 2 answers (c & d) */
Rong Changf6267992013-04-12 10:44:57 +0000587 start = get_timer(0);
Simon Glass7c735372015-08-22 18:31:24 -0600588 stop = chip->timeout_d;
Rong Changf6267992013-04-12 10:44:57 +0000589 do {
590 /* Note: STS is little endian */
Simon Glass7c735372015-08-22 18:31:24 -0600591 addr = TPM_STS(chip->locality) + 1;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000592 if (iic_tpm_read(addr, buf, 3) < 0)
Rong Changf6267992013-04-12 10:44:57 +0000593 burstcnt = 0;
594 else
595 burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
596
597 if (burstcnt)
598 return burstcnt;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000599 udelay(TPM_TIMEOUT * 1000);
Rong Changf6267992013-04-12 10:44:57 +0000600 } while (get_timer(start) < stop);
601
602 return -EBUSY;
603}
604
605static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000606 int *status)
Rong Changf6267992013-04-12 10:44:57 +0000607{
608 unsigned long start, stop;
609
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000610 /* Check current status */
Rong Changf6267992013-04-12 10:44:57 +0000611 *status = tpm_tis_i2c_status(chip);
612 if ((*status & mask) == mask)
613 return 0;
614
615 start = get_timer(0);
616 stop = timeout;
617 do {
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000618 udelay(TPM_TIMEOUT * 1000);
Rong Changf6267992013-04-12 10:44:57 +0000619 *status = tpm_tis_i2c_status(chip);
620 if ((*status & mask) == mask)
621 return 0;
Rong Changf6267992013-04-12 10:44:57 +0000622 } while (get_timer(start) < stop);
623
624 return -ETIME;
625}
626
627static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
628{
629 size_t size = 0;
630 ssize_t burstcnt;
631 int rc;
632
633 while (size < count) {
634 burstcnt = get_burstcount(chip);
635
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000636 /* burstcount < 0 -> tpm is busy */
Rong Changf6267992013-04-12 10:44:57 +0000637 if (burstcnt < 0)
638 return burstcnt;
639
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000640 /* Limit received data to max left */
Rong Changf6267992013-04-12 10:44:57 +0000641 if (burstcnt > (count - size))
642 burstcnt = count - size;
643
Simon Glass7c735372015-08-22 18:31:24 -0600644 rc = iic_tpm_read(TPM_DATA_FIFO(chip->locality),
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000645 &(buf[size]), burstcnt);
Rong Changf6267992013-04-12 10:44:57 +0000646 if (rc == 0)
647 size += burstcnt;
648 }
649
650 return size;
651}
652
653static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
654{
655 int size = 0;
656 int expected, status;
657
658 if (count < TPM_HEADER_SIZE) {
659 size = -EIO;
660 goto out;
661 }
662
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000663 /* Read first 10 bytes, including tag, paramsize, and result */
Rong Changf6267992013-04-12 10:44:57 +0000664 size = recv_data(chip, buf, TPM_HEADER_SIZE);
665 if (size < TPM_HEADER_SIZE) {
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000666 error("Unable to read header\n");
Rong Changf6267992013-04-12 10:44:57 +0000667 goto out;
668 }
669
670 expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE);
671 if ((size_t)expected > count) {
Simon Glassf90acf12015-05-04 11:30:59 -0600672 error("Error size=%x, expected=%x, count=%x\n", size, expected,
673 count);
Rong Changf6267992013-04-12 10:44:57 +0000674 size = -EIO;
675 goto out;
676 }
677
678 size += recv_data(chip, &buf[TPM_HEADER_SIZE],
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000679 expected - TPM_HEADER_SIZE);
Rong Changf6267992013-04-12 10:44:57 +0000680 if (size < expected) {
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000681 error("Unable to read remainder of result\n");
Rong Changf6267992013-04-12 10:44:57 +0000682 size = -ETIME;
683 goto out;
684 }
685
Simon Glass7c735372015-08-22 18:31:24 -0600686 wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status);
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000687 if (status & TPM_STS_DATA_AVAIL) { /* Retry? */
688 error("Error left over data\n");
Rong Changf6267992013-04-12 10:44:57 +0000689 size = -EIO;
690 goto out;
691 }
692
693out:
694 tpm_tis_i2c_ready(chip);
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000695 /*
696 * The TPM needs some time to clean up here,
Rong Changf6267992013-04-12 10:44:57 +0000697 * so we sleep rather than keeping the bus busy
698 */
699 udelay(2000);
Simon Glass7c735372015-08-22 18:31:24 -0600700 release_locality(chip, chip->locality, 0);
Rong Changf6267992013-04-12 10:44:57 +0000701
702 return size;
703}
704
705static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
706{
707 int rc, status;
Simon Glassf90acf12015-05-04 11:30:59 -0600708 size_t burstcnt;
Rong Changf6267992013-04-12 10:44:57 +0000709 size_t count = 0;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000710 int retry = 0;
Rong Changf6267992013-04-12 10:44:57 +0000711 u8 sts = TPM_STS_GO;
712
Simon Glassf90acf12015-05-04 11:30:59 -0600713 debug("%s: len=%d\n", __func__, len);
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000714 if (len > TPM_DEV_BUFSIZE)
715 return -E2BIG; /* Command is too long for our tpm, sorry */
Rong Changf6267992013-04-12 10:44:57 +0000716
717 if (request_locality(chip, 0) < 0)
718 return -EBUSY;
719
720 status = tpm_tis_i2c_status(chip);
721 if ((status & TPM_STS_COMMAND_READY) == 0) {
722 tpm_tis_i2c_ready(chip);
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000723 if (wait_for_stat(chip, TPM_STS_COMMAND_READY,
Simon Glass7c735372015-08-22 18:31:24 -0600724 chip->timeout_b, &status) < 0) {
Rong Changf6267992013-04-12 10:44:57 +0000725 rc = -ETIME;
726 goto out_err;
727 }
728 }
729
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000730 burstcnt = get_burstcount(chip);
731
732 /* burstcount < 0 -> tpm is busy */
733 if (burstcnt < 0)
734 return burstcnt;
735
Simon Glassf90acf12015-05-04 11:30:59 -0600736 while (count < len) {
737 udelay(300);
738 if (burstcnt > len - count)
739 burstcnt = len - count;
Rong Changf6267992013-04-12 10:44:57 +0000740
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000741#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION
742 if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION)
743 burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION;
744#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */
Rong Changf6267992013-04-12 10:44:57 +0000745
Simon Glass7c735372015-08-22 18:31:24 -0600746 rc = iic_tpm_write(TPM_DATA_FIFO(chip->locality),
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000747 &(buf[count]), burstcnt);
Rong Changf6267992013-04-12 10:44:57 +0000748 if (rc == 0)
749 count += burstcnt;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000750 else {
Simon Glassf90acf12015-05-04 11:30:59 -0600751 debug("%s: error\n", __func__);
752 if (retry++ > 10) {
753 rc = -EIO;
754 goto out_err;
755 }
756 rc = wait_for_stat(chip, TPM_STS_VALID,
Simon Glass7c735372015-08-22 18:31:24 -0600757 chip->timeout_c, &status);
Simon Glassf90acf12015-05-04 11:30:59 -0600758 if (rc)
759 goto out_err;
Rong Changf6267992013-04-12 10:44:57 +0000760
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000761 if ((status & TPM_STS_DATA_EXPECT) == 0) {
762 rc = -EIO;
763 goto out_err;
764 }
Rong Changf6267992013-04-12 10:44:57 +0000765 }
766 }
767
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000768 /* Go and do it */
Simon Glass7c735372015-08-22 18:31:24 -0600769 iic_tpm_write(TPM_STS(chip->locality), &sts, 1);
Simon Glassf90acf12015-05-04 11:30:59 -0600770 debug("done\n");
Rong Changf6267992013-04-12 10:44:57 +0000771
772 return len;
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000773
Rong Changf6267992013-04-12 10:44:57 +0000774out_err:
Simon Glassf90acf12015-05-04 11:30:59 -0600775 debug("%s: out_err\n", __func__);
Rong Changf6267992013-04-12 10:44:57 +0000776 tpm_tis_i2c_ready(chip);
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000777 /*
778 * The TPM needs some time to clean up here,
Rong Changf6267992013-04-12 10:44:57 +0000779 * so we sleep rather than keeping the bus busy
780 */
781 udelay(2000);
Simon Glass7c735372015-08-22 18:31:24 -0600782 release_locality(chip, chip->locality, 0);
Rong Changf6267992013-04-12 10:44:57 +0000783
784 return rc;
785}
786
Simon Glass13932b02015-08-22 18:31:25 -0600787static enum i2c_chip_type tpm_tis_i2c_chip_type(void)
Vincent Palatinec34fa52013-04-12 11:04:36 +0000788{
Masahiro Yamada0f925822015-08-12 07:31:55 +0900789#if CONFIG_IS_ENABLED(OF_CONTROL)
Vincent Palatinec34fa52013-04-12 11:04:36 +0000790 const void *blob = gd->fdt_blob;
791
792 if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0)
793 return SLB9645;
794
795 if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM) >= 0)
796 return SLB9635;
797#endif
798 return UNKNOWN;
799}
800
Simon Glass13932b02015-08-22 18:31:25 -0600801static int tpm_tis_i2c_init(struct udevice *dev)
Rong Changf6267992013-04-12 10:44:57 +0000802{
Simon Glass7c735372015-08-22 18:31:24 -0600803 struct tpm_chip *chip = &g_chip;
Rong Changf6267992013-04-12 10:44:57 +0000804 u32 vendor;
Vincent Palatinec34fa52013-04-12 11:04:36 +0000805 u32 expected_did_vid;
Rong Changf6267992013-04-12 10:44:57 +0000806
Simon Glass13932b02015-08-22 18:31:25 -0600807 g_chip.dev = dev;
808 g_chip.chip_type = tpm_tis_i2c_chip_type();
Simon Glass7c735372015-08-22 18:31:24 -0600809 chip->is_open = 1;
Rong Changf6267992013-04-12 10:44:57 +0000810
811 /* Disable interrupts (not supported) */
Simon Glass7c735372015-08-22 18:31:24 -0600812 chip->irq = 0;
Rong Changf6267992013-04-12 10:44:57 +0000813
814 /* Default timeouts */
Simon Glass7c735372015-08-22 18:31:24 -0600815 chip->timeout_a = TIS_SHORT_TIMEOUT;
816 chip->timeout_b = TIS_LONG_TIMEOUT;
817 chip->timeout_c = TIS_SHORT_TIMEOUT;
818 chip->timeout_d = TIS_SHORT_TIMEOUT;
819 chip->req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID;
820 chip->req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID;
821 chip->req_canceled = TPM_STS_COMMAND_READY;
Rong Changf6267992013-04-12 10:44:57 +0000822
Simon Glassf90acf12015-05-04 11:30:59 -0600823 if (request_locality(chip, 0) < 0)
824 return -ENODEV;
Rong Changf6267992013-04-12 10:44:57 +0000825
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000826 /* Read four bytes from DID_VID register */
Rong Changf6267992013-04-12 10:44:57 +0000827 if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) {
Simon Glassf90acf12015-05-04 11:30:59 -0600828 release_locality(chip, 0, 1);
829 return -EIO;
Rong Changf6267992013-04-12 10:44:57 +0000830 }
831
Simon Glass13932b02015-08-22 18:31:25 -0600832 if (g_chip.chip_type == SLB9635) {
Vincent Palatinec34fa52013-04-12 11:04:36 +0000833 vendor = be32_to_cpu(vendor);
834 expected_did_vid = TPM_TIS_I2C_DID_VID_9635;
835 } else {
836 /* device id and byte order has changed for newer i2c tpms */
837 expected_did_vid = TPM_TIS_I2C_DID_VID_9645;
838 }
Rong Changf6267992013-04-12 10:44:57 +0000839
Simon Glass13932b02015-08-22 18:31:25 -0600840 if (g_chip.chip_type != UNKNOWN && vendor != expected_did_vid) {
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000841 error("Vendor id did not match! ID was %08x\n", vendor);
Simon Glassf90acf12015-05-04 11:30:59 -0600842 return -ENODEV;
Rong Changf6267992013-04-12 10:44:57 +0000843 }
844
Tom Wai-Hong Tam1b393db2013-04-12 11:04:37 +0000845 debug("1.2 TPM (chip type %s device-id 0x%X)\n",
Simon Glass13932b02015-08-22 18:31:25 -0600846 chip_name[g_chip.chip_type], vendor >> 16);
Rong Changf6267992013-04-12 10:44:57 +0000847
848 /*
849 * A timeout query to TPM can be placed here.
850 * Standard timeout values are used so far
851 */
852
853 return 0;
Simon Glassf90acf12015-05-04 11:30:59 -0600854}
Rong Changf6267992013-04-12 10:44:57 +0000855
Simon Glass4cd7b782015-08-22 18:31:22 -0600856/* Returns max number of milliseconds to wait */
857static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
858 u32 ordinal)
859{
860 int duration_idx = TPM_UNDEFINED;
861 int duration = 0;
862
863 if (ordinal < TPM_MAX_ORDINAL) {
864 duration_idx = tpm_ordinal_duration[ordinal];
865 } else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
866 TPM_MAX_PROTECTED_ORDINAL) {
867 duration_idx = tpm_protected_ordinal_duration[
868 ordinal & TPM_PROTECTED_ORDINAL_MASK];
869 }
870
871 if (duration_idx != TPM_UNDEFINED)
Simon Glass7c735372015-08-22 18:31:24 -0600872 duration = chip->duration[duration_idx];
Simon Glass4cd7b782015-08-22 18:31:22 -0600873
874 if (duration <= 0)
875 return 2 * 60 * HZ; /* Two minutes timeout */
876 else
877 return duration;
878}
879
880static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
881{
882 int rc;
883 u32 count, ordinal;
884 unsigned long start, stop;
885
886 struct tpm_chip *chip = &g_chip;
887
888 /* switch endianess: big->little */
889 count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
890 ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
891
892 if (count == 0) {
893 error("no data\n");
894 return -ENODATA;
895 }
896 if (count > bufsiz) {
897 error("invalid count value %x %zx\n", count, bufsiz);
898 return -E2BIG;
899 }
900
901 debug("Calling send\n");
Simon Glassb382e022015-08-22 18:31:23 -0600902 rc = tpm_tis_i2c_send(chip, (u8 *)buf, count);
Simon Glass4cd7b782015-08-22 18:31:22 -0600903 debug(" ... done calling send\n");
904 if (rc < 0) {
905 error("tpm_transmit: tpm_send: error %d\n", rc);
906 goto out;
907 }
908
Simon Glass7c735372015-08-22 18:31:24 -0600909 if (chip->irq)
Simon Glass4cd7b782015-08-22 18:31:22 -0600910 goto out_recv;
911
912 start = get_timer(0);
913 stop = tpm_calc_ordinal_duration(chip, ordinal);
914 do {
915 debug("waiting for status... %ld %ld\n", start, stop);
Simon Glassb382e022015-08-22 18:31:23 -0600916 u8 status = tpm_tis_i2c_status(chip);
Simon Glass7c735372015-08-22 18:31:24 -0600917 if ((status & chip->req_complete_mask) ==
918 chip->req_complete_val) {
Simon Glass4cd7b782015-08-22 18:31:22 -0600919 debug("...got it;\n");
920 goto out_recv;
921 }
922
Simon Glass7c735372015-08-22 18:31:24 -0600923 if (status == chip->req_canceled) {
Simon Glass4cd7b782015-08-22 18:31:22 -0600924 error("Operation Canceled\n");
925 rc = -ECANCELED;
926 goto out;
927 }
928 udelay(TPM_TIMEOUT * 1000);
929 } while (get_timer(start) < stop);
930
Simon Glassb382e022015-08-22 18:31:23 -0600931 tpm_tis_i2c_ready(chip);
Simon Glass4cd7b782015-08-22 18:31:22 -0600932 error("Operation Timed out\n");
933 rc = -ETIME;
934 goto out;
935
936out_recv:
937 debug("out_recv: reading response...\n");
Simon Glassb382e022015-08-22 18:31:23 -0600938 rc = tpm_tis_i2c_recv(chip, (u8 *)buf, TPM_BUFSIZE);
Simon Glass4cd7b782015-08-22 18:31:22 -0600939 if (rc < 0)
940 error("tpm_transmit: tpm_recv: error %d\n", rc);
941
942out:
943 return rc;
944}
945
946static int tpm_open_dev(struct udevice *dev)
947{
948 int rc;
949
950 debug("%s: start\n", __func__);
951 if (g_chip.is_open)
952 return -EBUSY;
Simon Glass13932b02015-08-22 18:31:25 -0600953 rc = tpm_tis_i2c_init(dev);
Simon Glass4cd7b782015-08-22 18:31:22 -0600954 if (rc < 0)
955 g_chip.is_open = 0;
956 return rc;
957}
958
959static void tpm_close(void)
960{
961 if (g_chip.is_open) {
Simon Glass13932b02015-08-22 18:31:25 -0600962 release_locality(&g_chip, g_chip.locality, 1);
Simon Glass4cd7b782015-08-22 18:31:22 -0600963 g_chip.is_open = 0;
964 }
965}
966
967/**
968 * Decode TPM configuration.
969 *
970 * @param dev Returns a configuration of TPM device
971 * @return 0 if ok, -1 on error
972 */
Simon Glass605152a2015-08-22 18:31:26 -0600973static int tpm_decode_config(struct tpm_chip *chip)
Simon Glass4cd7b782015-08-22 18:31:22 -0600974{
975 const void *blob = gd->fdt_blob;
976 struct udevice *bus;
977 int chip_addr;
978 int parent;
979 int node;
980 int ret;
981
982 node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
983 if (node < 0) {
984 node = fdtdec_next_compatible(blob, 0,
985 COMPAT_INFINEON_SLB9645_TPM);
986 }
987 if (node < 0) {
988 debug("%s: Node not found\n", __func__);
989 return -1;
990 }
991 parent = fdt_parent_offset(blob, node);
992 if (parent < 0) {
993 debug("%s: Cannot find node parent\n", __func__);
994 return -1;
995 }
996
997 /*
998 * TODO(sjg@chromium.org): Remove this when driver model supports
999 * TPMs
1000 */
1001 ret = uclass_get_device_by_of_offset(UCLASS_I2C, parent, &bus);
1002 if (ret) {
1003 debug("Cannot find bus for node '%s: ret=%d'\n",
1004 fdt_get_name(blob, parent, NULL), ret);
1005 return ret;
1006 }
1007
1008 chip_addr = fdtdec_get_int(blob, node, "reg", -1);
1009 if (chip_addr == -1) {
1010 debug("Cannot find reg property for node '%s: ret=%d'\n",
1011 fdt_get_name(blob, node, NULL), ret);
1012 return ret;
1013 }
1014 /*
1015 * TODO(sjg@chromium.org): Older TPMs will need to use the older method
1016 * in iic_tpm_read() so the offset length needs to be 0 here.
1017 */
Simon Glass605152a2015-08-22 18:31:26 -06001018 ret = i2c_get_chip(bus, chip_addr, 1, &chip->dev);
Simon Glass4cd7b782015-08-22 18:31:22 -06001019 if (ret) {
1020 debug("Cannot find device for node '%s: ret=%d'\n",
1021 fdt_get_name(blob, node, NULL), ret);
1022 return ret;
1023 }
1024
1025 return 0;
1026}
1027
Simon Glass4cd7b782015-08-22 18:31:22 -06001028int tis_init(void)
1029{
Simon Glass605152a2015-08-22 18:31:26 -06001030 if (g_chip.inited)
Simon Glass4cd7b782015-08-22 18:31:22 -06001031 return 0;
1032
Simon Glass605152a2015-08-22 18:31:26 -06001033 if (tpm_decode_config(&g_chip))
Simon Glass4cd7b782015-08-22 18:31:22 -06001034 return -1;
1035
1036 debug("%s: done\n", __func__);
1037
Simon Glass605152a2015-08-22 18:31:26 -06001038 g_chip.inited = 1;
Simon Glass4cd7b782015-08-22 18:31:22 -06001039
1040 return 0;
1041}
1042
1043int tis_open(void)
1044{
1045 int rc;
1046
Simon Glass605152a2015-08-22 18:31:26 -06001047 if (!g_chip.inited)
Simon Glass4cd7b782015-08-22 18:31:22 -06001048 return -1;
1049
Simon Glass605152a2015-08-22 18:31:26 -06001050 rc = tpm_open_dev(g_chip.dev);
Simon Glass4cd7b782015-08-22 18:31:22 -06001051
1052 return rc;
1053}
1054
1055int tis_close(void)
1056{
Simon Glass605152a2015-08-22 18:31:26 -06001057 if (!g_chip.inited)
Simon Glass4cd7b782015-08-22 18:31:22 -06001058 return -1;
1059
1060 tpm_close();
1061
1062 return 0;
1063}
1064
1065int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
1066 uint8_t *recvbuf, size_t *rbuf_len)
1067{
1068 int len;
1069 uint8_t buf[4096];
1070
Simon Glass605152a2015-08-22 18:31:26 -06001071 if (!g_chip.inited)
Simon Glass4cd7b782015-08-22 18:31:22 -06001072 return -1;
1073
1074 if (sizeof(buf) < sbuf_size)
1075 return -1;
1076
1077 memcpy(buf, sendbuf, sbuf_size);
1078
1079 len = tpm_transmit(buf, sbuf_size);
1080
1081 if (len < 10) {
1082 *rbuf_len = 0;
1083 return -1;
1084 }
1085
1086 memcpy(recvbuf, buf, len);
1087 *rbuf_len = len;
1088
1089 return 0;
1090}