| 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 |