1 /* 2 * Copyright (c) 2025, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <stdbool.h> 10 #include <string.h> 11 12 #include <drivers/gpio_spi.h> 13 #include <drivers/tpm/tpm2.h> 14 #include <drivers/tpm/tpm2_chip.h> 15 #include <drivers/tpm/tpm2_interface.h> 16 17 #define ENCODE_LIMIT 128 18 #define CS_ASSERT_OFFSET 0xD4 19 #define RETRY_COUNT 50 20 21 #define TPM_READ false 22 #define TPM_WRITE true 23 24 extern struct spi_plat *spidev; 25 26 static int tpm2_spi_transfer(const void *data_out, void *data_in, uint8_t len) 27 { 28 return spidev->ops->xfer(len, data_out, data_in); 29 } 30 31 /* 32 * Reference: TCG PC Client Platform TPM Profile (PTP) Specification v1.05 33 */ 34 static int tpm2_spi_start_transaction(uint16_t tpm_reg, bool write, uint8_t len) 35 { 36 int rc; 37 uint8_t header[4]; 38 uint8_t header_response[4]; 39 uint8_t zero = 0, byte; 40 int retries; 41 42 /* check to make sure len does not exceed the encoding limit */ 43 if (len > ENCODE_LIMIT) { 44 return TPM_INVALID_PARAM; 45 } 46 47 /* 48 * 7.4.6 TPM SPI Bit protocol calls for the following header 49 * to be sent to the TPM at the start of every attempted read/write. 50 */ 51 52 /* header[0] contains the r/w and the xfer size, if the msb is not 53 * set, the operation is write, if it is set then it is read. 54 * The size of the transfer is encoded, and must not overwrite 55 * the msb, therefore an ENCODE LIMIT of 128 is present. 56 */ 57 header[0] = ((write) ? 0x00 : 0x80) | (len - 1); 58 59 /* 60 * header[1] contains the address offset 0xD4_xxxx as defined 61 * in the TPM spec, since the CS# is asserted. 62 */ 63 header[1] = CS_ASSERT_OFFSET; 64 65 /* 66 * header[2] and header[3] contain the address of the register 67 * to be read/written. 68 */ 69 header[2] = tpm_reg >> 8; 70 header[3] = tpm_reg; 71 72 rc = tpm2_spi_transfer(header, header_response, 4); 73 if (rc != 0) { 74 return TPM_ERR_TRANSFER; 75 } 76 77 /* 78 * 7.4.5 Flow Control defines a wait state in order to accommodate 79 * the TPM in case it needs to free its buffer. 80 */ 81 if ((header_response[3] & 0x01) != 0U) { 82 return TPM_SUCCESS; 83 } 84 85 /* 86 * if the wait state over bit is not set in the initial header_response, 87 * poll for the wait state over by sending a zeroed byte, if the 88 * RETRY_COUNT is exceeded the transfer fails. 89 */ 90 for (retries = RETRY_COUNT; retries > 0; retries--) { 91 rc = tpm2_spi_transfer(&zero, &byte, 1); 92 if (rc != 0) { 93 return TPM_ERR_TRANSFER; 94 } 95 if ((byte & 0x01) != 0U) { 96 return TPM_SUCCESS; 97 } 98 } 99 100 if (retries == 0) { 101 ERROR("%s: TPM Timeout\n", __func__); 102 return TPM_ERR_TIMEOUT; 103 } 104 105 return TPM_SUCCESS; 106 } 107 108 static void tpm2_spi_end_transaction(void) 109 { 110 spidev->ops->stop(); 111 } 112 113 static void tpm2_spi_init(void) 114 { 115 spidev->ops->get_access(); 116 spidev->ops->start(); 117 } 118 119 static int tpm2_fifo_io(uint16_t tpm_reg, bool is_write, uint8_t len, void *val) 120 { 121 int rc; 122 123 tpm2_spi_init(); 124 rc = tpm2_spi_start_transaction(tpm_reg, is_write, len); 125 if (rc != 0) { 126 tpm2_spi_end_transaction(); 127 return rc; 128 } 129 130 rc = tpm2_spi_transfer( 131 is_write ? val : NULL, 132 is_write ? NULL : val, 133 len); 134 if (rc != 0) { 135 tpm2_spi_end_transaction(); 136 return rc; 137 } 138 139 tpm2_spi_end_transaction(); 140 141 return TPM_SUCCESS; 142 } 143 144 int tpm2_fifo_write_byte(uint16_t tpm_reg, uint8_t val) 145 { 146 return tpm2_fifo_io(tpm_reg, TPM_WRITE, BYTE, &val); 147 } 148 149 int tpm2_fifo_read_byte(uint16_t tpm_reg, uint8_t *val) 150 { 151 return tpm2_fifo_io(tpm_reg, TPM_READ, BYTE, val); 152 } 153 154 int tpm2_fifo_read_chunk(uint16_t tpm_reg, uint8_t len, void *val) 155 { 156 if ((len != BYTE) && (len != WORD) && (len != DWORD)) { 157 return TPM_INVALID_PARAM; 158 } 159 160 return tpm2_fifo_io(tpm_reg, TPM_READ, len, val); 161 } 162