OLD | NEW |
1 /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 */ | 4 */ |
5 | 5 |
6 #include <config.h> | 6 #include <config.h> |
7 #include <common.h> | 7 #include <common.h> |
8 #include <i2c.h> | 8 #include <i2c.h> |
9 | 9 |
10 #define INFINEON_TPM_CHIP (CONFIG_INFINEON_TPM_CHIP_ADDRESS) | |
11 | 10 |
12 /* infineon prototype i2c tpm's internal registers | 11 /* infineon prototype i2c tpm's internal registers |
13 */ | 12 */ |
| 13 #define INFINEON_TPM_CHIP (0x1A) |
14 #define REG_RDATA (0xA4) | 14 #define REG_RDATA (0xA4) |
15 #define REG_WDATA (0xA5) | 15 #define REG_WDATA (0xA5) |
16 #define REG_STAT (0xA7) | 16 #define REG_STAT (0xA7) |
17 /* i2c timeout value and polling period | 17 /* i2c timeout value and polling period |
18 */ | 18 */ |
19 #define I2CBUSY_WAIT_US» (1000ul) | 19 #define I2CBUSY_WAIT_MS» (1ul) |
20 #define TIMEOUT_REG_US (1000000ul) | 20 #define TIMEOUT_REG_MS (1000ul) |
21 | 21 |
22 /* error code follows u-boot standard | 22 /* error code follows u-boot standard |
23 * 0 : success | 23 * 0 : success |
24 * non zero : failed | 24 * non zero : failed |
25 */ | 25 */ |
26 enum { | 26 enum { |
27 E_TIMEOUT = -7, | 27 E_TIMEOUT = -7, |
28 E_CHECKSUM = -6, | 28 E_CHECKSUM = -6, |
29 E_SIZE = -5, | 29 E_SIZE = -5, |
30 E_MEMORY = -4, | 30 E_MEMORY = -4, |
31 E_DATA = -3, | 31 E_DATA = -3, |
32 E_PARAMETER = -2, | 32 E_PARAMETER = -2, |
33 E_GENERAL = -1, | 33 E_GENERAL = -1, |
34 S_OK = 0, | 34 S_OK = 0, |
35 E_WARNING = 1 | 35 E_WARNING = 1 |
36 }; | 36 }; |
37 | 37 |
38 /* tpm chip timeout value on read/write | 38 /* tpm chip timeout value on read/write |
39 * TODO: | 39 * TODO: |
40 * find the correct timeout when tpm in i2c mode. but since this is the | 40 * find the correct timeout when tpm in i2c mode. but since this is the |
41 * prototype i2c tpm chip, spec is not as clear as lpc tpm chip. just use | 41 * prototype i2c tpm chip, spec is not as clear as lpc tpm chip. just use |
42 * the maximum wait time as the timeout value. | 42 * the maximum wait time as the timeout value. |
43 */ | 43 */ |
44 #define TIMEOUT_READ_US (3000000ul) | 44 #define TIMEOUT_READ_MS (3000ul) |
45 #define TIMEOUT_WRITE_US (1000000ul) | 45 #define TIMEOUT_WRITE_MS (1000ul) |
46 | 46 |
47 /* tpm stat register bits | 47 /* tpm stat register bits |
48 */ | 48 */ |
49 #define TPM_RECEIVE_DATA_AVAILABLE (1u) | 49 #define TPM_RECEIVE_DATA_AVAILABLE (1u) |
50 #define TPM_TRANSMIT_FIFO_NOTFULL (1u << 7) | 50 #define TPM_TRANSMIT_FIFO_NOTFULL (1u << 7) |
51 | 51 |
52 /* tpm transport and vendor layers | 52 /* tpm transport and vendor layers |
53 */ | 53 */ |
54 enum { | 54 enum { |
55 TSPT_VER = 0, | 55 TSPT_VER = 0, |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 *pcopy_size = data_len; | 217 *pcopy_size = data_len; |
218 tpm_i2c_debug_dump(from, 0, DATA_START + data_len + 1); | 218 tpm_i2c_debug_dump(from, 0, DATA_START + data_len + 1); |
219 return 0; | 219 return 0; |
220 } | 220 } |
221 | 221 |
222 static int tpm_i2c_reg(uint8_t *reg) | 222 static int tpm_i2c_reg(uint8_t *reg) |
223 { | 223 { |
224 ulong stime = get_timer(0); | 224 ulong stime = get_timer(0); |
225 while (i2c_write_data((uchar)INFINEON_TPM_CHIP, reg, 1)) { | 225 while (i2c_write_data((uchar)INFINEON_TPM_CHIP, reg, 1)) { |
226 /* i2c busy, wait 1ms */ | 226 /* i2c busy, wait 1ms */ |
227 » » udelay(I2CBUSY_WAIT_US); | 227 » » udelay(I2CBUSY_WAIT_MS * 1000); |
228 » » if (get_timer(stime) > TIMEOUT_REG_US) | 228 » » if (get_timer(stime) > TIMEOUT_REG_MS) |
229 return E_TIMEOUT; | 229 return E_TIMEOUT; |
230 } | 230 } |
231 return 0; | 231 return 0; |
232 } | 232 } |
233 | 233 |
234 static int tpm_i2c_read_status(t_inf_stat_reg *preg) | 234 static int tpm_i2c_read_status(t_inf_stat_reg *preg) |
235 { | 235 { |
236 uint8_t s_reg[8]; | 236 uint8_t s_reg[8]; |
237 uint8_t stat[4]; | 237 uint8_t stat[4]; |
238 s_reg[0] = (uchar)REG_STAT; | 238 s_reg[0] = (uchar)REG_STAT; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 TPM_CHECK(tpm_i2c_read_status(&st_reg)); | 328 TPM_CHECK(tpm_i2c_read_status(&st_reg)); |
329 } while ((get_timer(stime) < timeout_us) && | 329 } while ((get_timer(stime) < timeout_us) && |
330 (st_reg.status & TPM_RECEIVE_DATA_AVAILABLE) == 0); | 330 (st_reg.status & TPM_RECEIVE_DATA_AVAILABLE) == 0); |
331 | 331 |
332 return (st_reg.status & TPM_RECEIVE_DATA_AVAILABLE) == 0 ? | 332 return (st_reg.status & TPM_RECEIVE_DATA_AVAILABLE) == 0 ? |
333 E_TIMEOUT : 0; | 333 E_TIMEOUT : 0; |
334 } | 334 } |
335 | 335 |
336 /* TPM API | 336 /* TPM API |
337 */ | 337 */ |
338 int tpm_status(int *ready_write, int *ready_read, size_t *p_len) | 338 int tpm_status_v03(int *ready_write, int *ready_read, size_t *p_len) |
339 { | 339 { |
340 t_inf_stat_reg reg; | 340 t_inf_stat_reg reg; |
341 | 341 |
342 TPM_CHECK(tpm_i2c_read_status(®)); | 342 TPM_CHECK(tpm_i2c_read_status(®)); |
343 /* exception case in prototype spec, error | 343 /* exception case in prototype spec, error |
344 */ | 344 */ |
345 if (reg.status == 0xff && reg.len_h == 0xff && reg.len_l == 0xff) | 345 if (reg.status == 0xff && reg.len_h == 0xff && reg.len_l == 0xff) |
346 return E_GENERAL; | 346 return E_GENERAL; |
347 /* verify status checksum | 347 /* verify status checksum |
348 */ | 348 */ |
349 if ((reg.status ^ reg.len_h ^ reg.len_l) != reg.checksum) | 349 if ((reg.status ^ reg.len_h ^ reg.len_l) != reg.checksum) |
350 return E_CHECKSUM; | 350 return E_CHECKSUM; |
351 /* data available | 351 /* data available |
352 » */ | 352 » */ |
353 if (ready_read) | 353 if (ready_read) |
354 *ready_read = (reg.status & TPM_RECEIVE_DATA_AVAILABLE) ? 1 : 0; | 354 *ready_read = (reg.status & TPM_RECEIVE_DATA_AVAILABLE) ? 1 : 0; |
355 /* data length | 355 /* data length |
356 */ | 356 */ |
357 if (p_len) { | 357 if (p_len) { |
358 if (*ready_read) | 358 if (*ready_read) |
359 *p_len = ((size_t)reg.len_h << 8) + (size_t)reg.len_l; | 359 *p_len = ((size_t)reg.len_h << 8) + (size_t)reg.len_l; |
360 else | 360 else |
361 *p_len = 0; | 361 *p_len = 0; |
362 } | 362 } |
363 /* device writable | 363 /* device writable |
364 */ | 364 */ |
365 if (ready_write) | 365 if (ready_write) |
366 *ready_write = (reg.status & TPM_TRANSMIT_FIFO_NOTFULL) ? 1 : 0; | 366 *ready_write = (reg.status & TPM_TRANSMIT_FIFO_NOTFULL) ? 1 : 0; |
367 return 0; | 367 return 0; |
368 } | 368 } |
369 | 369 |
370 | 370 |
371 int tpm_init(void) | 371 int tpm_init_v03(void) |
372 { | 372 { |
373 int ready_write = 0, ready_read = 0; | 373 int ready_write = 0, ready_read = 0; |
374 size_t read_len = 0; | 374 size_t read_len = 0; |
375 int ret_code; | 375 int ret_code; |
376 #if defined(CONFIG_I2C_MULTI_BUS) | 376 #if defined(CONFIG_I2C_MULTI_BUS) |
377 i2c_set_bus_num(CONFIG_INFINEON_TPM_I2C_BUS); | 377 i2c_set_bus_num(CONFIG_INFINEON_TPM_I2C_BUS); |
378 #endif | 378 #endif |
379 ret_code = i2c_probe(INFINEON_TPM_CHIP); | 379 ret_code = i2c_probe(INFINEON_TPM_CHIP); |
380 #ifdef VBOOT_DEBUG | 380 #ifdef VBOOT_DEBUG |
381 » printf("probe : %d\n", ret_code); | 381 » printf("v03 probe : %s\n", ret_code ? "N/A" : "found"); |
382 #endif /* VBOOT_DEBUG */ | 382 #endif /* VBOOT_DEBUG */ |
383 if (ret_code) | 383 if (ret_code) |
384 return ret_code; | 384 return ret_code; |
385 » ret_code = tpm_status(&ready_write, &ready_read, &read_len); | 385 » ret_code = tpm_status_v03(&ready_write, &ready_read, &read_len); |
386 #ifdef VBOOT_DEBUG | 386 #ifdef VBOOT_DEBUG |
387 printf("status : %d\n\tw[%c] r[%c : %u]\n", ret_code, | 387 printf("status : %d\n\tw[%c] r[%c : %u]\n", ret_code, |
388 ready_write ? 'y' : 'n', | 388 ready_write ? 'y' : 'n', |
389 ready_read ? 'y' : 'n', read_len); | 389 ready_read ? 'y' : 'n', read_len); |
390 #endif /* VBOOT_DEBUG */ | 390 #endif /* VBOOT_DEBUG */ |
391 if (ret_code) | 391 if (ret_code) |
392 return ret_code; | 392 return ret_code; |
393 » TPM_CHECK(tpm_prepare_write(TIMEOUT_WRITE_US)); | 393 » TPM_CHECK(tpm_prepare_write(TIMEOUT_WRITE_MS)); |
394 return 0; | 394 return 0; |
395 } | 395 } |
396 | 396 |
397 int tpm_send(const uint8_t *pdata, size_t length) | 397 int tpm_sendrecv_v03(const uint8_t *sendbuf, size_t buf_size, uint8_t *recvbuf, |
| 398 » size_t *recv_len) |
398 { | 399 { |
399 » TPM_CHECK(tpm_prepare_write(TIMEOUT_WRITE_US)); | 400 » int ready_write = 0, ready_read = 0; |
400 » TPM_CHECK(tpm_i2c_write_data(pdata, length)); | 401 » size_t read_length = 0; |
| 402 » TPM_CHECK(tpm_prepare_write(TIMEOUT_WRITE_MS)); |
| 403 » TPM_CHECK(tpm_i2c_write_data(sendbuf, buf_size)); |
| 404 » TPM_CHECK(tpm_prepare_read(TIMEOUT_READ_MS)); |
| 405 » TPM_CHECK(tpm_status_v03(&ready_write, &ready_read, &read_length)); |
| 406 » if (read_length == 0) |
| 407 » » return E_GENERAL; |
| 408 » if (recv_len) { |
| 409 » » /* *recv_len sets the maximum data can be feched |
| 410 » » * if *recv_len == 0, means the buffer is large enough to read a
ny tpm |
| 411 » » * response |
| 412 » » */ |
| 413 » » if (*recv_len != 0 && *recv_len < read_length) |
| 414 » » » return E_SIZE; |
| 415 » } |
| 416 » if (recvbuf) { |
| 417 » » TPM_CHECK(tpm_i2c_read_data(recvbuf, read_length, NULL)); |
| 418 » » /* update recv_len only on success */ |
| 419 » » if (recv_len) |
| 420 » » » *recv_len = read_length; |
| 421 » } else { |
| 422 » » /* discard data in read buffer */ |
| 423 » » TPM_CHECK(tpm_prepare_write(TIMEOUT_WRITE_MS)); |
| 424 » } |
401 return 0; | 425 return 0; |
402 } | 426 } |
403 | 427 |
404 int tpm_receive(uint8_t *pdata, size_t max_length) | |
405 { | |
406 int ready_write = 0, ready_read = 0; | |
407 size_t read_length = 0; | |
408 TPM_CHECK(tpm_prepare_read(TIMEOUT_READ_US)); | |
409 TPM_CHECK(tpm_status(&ready_write, &ready_read, &read_length)); | |
410 if (read_length == 0) | |
411 return E_GENERAL; | |
412 if (max_length < read_length) | |
413 return E_SIZE; | |
414 TPM_CHECK(tpm_i2c_read_data(pdata, read_length, NULL)); | |
415 return 0; | |
416 } | |
OLD | NEW |