1 /* SPDX-License-Identifier: BSD-3-Clause */
4 #include <drivers/spi/tpm/tpm.h>
5 #include <security/tpm/tis.h>
10 #define CR50_DID_VID 0x00281ae0L
11 #define TI50_DT_DID_VID 0x504a6666L
12 #define TI50_OT_DID_VID 0x50666666L
14 #define CR50_BOARD_CFG_LOCKBIT_MASK 0x80000000U
15 #define CR50_BOARD_CFG_FEATUREBITS_MASK 0x3FFFFFFFU
17 #define CR50_BOARD_CFG_100US_READY_PULSE 0x00000001U
18 #define CR50_BOARD_CFG_VALUE \
19 (CONFIG(CR50_USE_LONG_INTERRUPT_PULSES) \
20 ? CR50_BOARD_CFG_100US_READY_PULSE : 0)
22 #define CR50_TIMEOUT_NOIRQ_MS 20 /* Timeout for TPM ready without IRQ */
29 #define CR50_FW_VER_REG_SPI (TPM_LOCALITY_0_SPI_BASE + 0xf90)
30 #define CR50_BOARD_CFG_REG_SPI (TPM_LOCALITY_0_SPI_BASE + 0xfe0)
32 #define CR50_FW_VER_REG_I2C 0x0f
33 #define CR50_BOARD_CFG_REG_I2C 0x1c
35 /* Return register address, which depends on the bus type, or -1 for error. */
36 static int get_reg_addr(enum cr50_register reg
)
38 if (CONFIG(SPI_TPM
)) {
41 return CR50_FW_VER_REG_SPI
;
42 case CR50_BOARD_CFG_REG
:
43 return CR50_BOARD_CFG_REG_SPI
;
49 if (CONFIG(I2C_TPM
)) {
52 return CR50_FW_VER_REG_I2C
;
53 case CR50_BOARD_CFG_REG
:
54 return CR50_BOARD_CFG_REG_I2C
;
63 static bool cr50_fw_supports_board_cfg(struct cr50_firmware_version
*version
)
65 /* Cr50 supports the CR50_BOARD_CFG register from version 0.5.5 / 0.6.5
67 if (version
->epoch
> 0 || version
->major
>= 7
68 || (version
->major
>= 5 && version
->minor
>= 5))
71 printk(BIOS_INFO
, "Cr50 firmware does not support CR50_BOARD_CFG, version: %d.%d.%d\n",
72 version
->epoch
, version
->major
, version
->minor
);
78 * Expose method to read the CR50_BOARD_CFG register, will return zero if
79 * register not supported by Cr50 firmware.
81 static uint32_t cr50_get_board_cfg(void)
83 struct cr50_firmware_version ver
;
86 if (cr50_get_firmware_version(&ver
) != CB_SUCCESS
)
89 if (!cr50_fw_supports_board_cfg(&ver
))
92 const enum cb_err ret
= tis_vendor_read(get_reg_addr(CR50_BOARD_CFG_REG
), &value
,
94 if (ret
!= CB_SUCCESS
) {
95 printk(BIOS_ERR
, "Error reading from Cr50\n");
99 return value
& CR50_BOARD_CFG_FEATUREBITS_MASK
;
102 __weak
int cr50_plat_irq_status(void)
104 static int warning_displayed
;
106 if (!warning_displayed
) {
107 printk(BIOS_WARNING
, "%s() not implemented, wasting 20ms to wait on Cr50!\n",
109 warning_displayed
= 1;
111 mdelay(CR50_TIMEOUT_NOIRQ_MS
);
117 * Set the BOARD_CFG register on the TPM chip to a particular compile-time constant value.
119 enum cb_err
cr50_set_board_cfg(void)
121 /* If we get here and we aren't cr50, then we must be ti50 which does
122 * not currently need to support a board_cfg register. */
123 if (!CONFIG(TPM_GOOGLE_CR50
))
126 struct cr50_firmware_version ver
;
130 if (cr50_get_firmware_version(&ver
) != CB_SUCCESS
)
133 if (!cr50_fw_supports_board_cfg(&ver
))
136 /* Set the CR50_BOARD_CFG register, for e.g. asking cr50 to use longer ready pulses. */
137 ret
= tis_vendor_read(get_reg_addr(CR50_BOARD_CFG_REG
), &value
, sizeof(value
));
138 if (ret
!= CB_SUCCESS
) {
139 printk(BIOS_ERR
, "Error reading from Cr50\n");
143 if ((value
& CR50_BOARD_CFG_FEATUREBITS_MASK
) == CR50_BOARD_CFG_VALUE
) {
144 printk(BIOS_INFO
, "Current CR50_BOARD_CFG = 0x%08x, matches desired = 0x%08x\n",
145 value
, CR50_BOARD_CFG_VALUE
);
149 if (value
& CR50_BOARD_CFG_LOCKBIT_MASK
) {
150 /* The high bit is set, meaning that the Cr50 is already locked on a particular
151 * value for the register, but not the one we wanted. */
152 printk(BIOS_ERR
, "Current CR50_BOARD_CFG = 0x%08x, does not match"
153 "desired = 0x%08x\n", value
, CR50_BOARD_CFG_VALUE
);
157 printk(BIOS_INFO
, "Current CR50_BOARD_CFG = 0x%08x, setting to 0x%08x\n",
158 value
, CR50_BOARD_CFG_VALUE
);
159 value
= CR50_BOARD_CFG_VALUE
;
161 ret
= tis_vendor_write(get_reg_addr(CR50_BOARD_CFG_REG
), &value
, sizeof(value
));
162 if (ret
!= CB_SUCCESS
) {
163 printk(BIOS_ERR
, "Error writing to cr50\n");
170 bool cr50_is_long_interrupt_pulse_enabled(void)
172 if (CONFIG(TPM_GOOGLE_CR50
))
173 return !!(cr50_get_board_cfg() & CR50_BOARD_CFG_100US_READY_PULSE
);
175 /* Ti50 and future GSCs will support only long interrupt pulses. */
179 static enum cb_err
cr50_parse_fw_version(const char *version_str
,
180 struct cr50_firmware_version
*ver
)
182 int epoch
, major
, minor
;
184 char *number
= strstr(version_str
, " RW_A:");
186 number
= strstr(version_str
, " RW_B:");
189 number
+= 6; /* Skip past the colon. */
191 epoch
= skip_atoi(&number
);
192 if (*number
++ != '.')
194 major
= skip_atoi(&number
);
195 if (*number
++ != '.')
197 minor
= skip_atoi(&number
);
205 enum cb_err
cr50_get_firmware_version(struct cr50_firmware_version
*version
)
207 static struct cr50_firmware_version cr50_firmware_version
;
209 if (cr50_firmware_version
.epoch
|| cr50_firmware_version
.major
||
210 cr50_firmware_version
.minor
)
214 size_t chunk_size
= 50;
215 char version_str
[301];
216 int addr
= get_reg_addr(CR50_FW_VER_REG
);
219 * Does not really matter what's written, this just makes sure
220 * the version is reported from the beginning.
222 tis_vendor_write(addr
, &chunk_size
, 1);
225 * Read chunk_size bytes at a time, last chunk will be zero padded.
228 uint8_t *buf
= (uint8_t *)version_str
+ chunk_count
* chunk_size
;
229 tis_vendor_read(addr
, buf
, chunk_size
);
230 if (!version_str
[++chunk_count
* chunk_size
- 1])
231 /* Zero padding detected: end of string. */
233 /* Check if there is enough room for reading one more chunk. */
234 } while (chunk_count
* chunk_size
< sizeof(version_str
) - chunk_size
);
236 version_str
[chunk_count
* chunk_size
] = '\0';
237 printk(BIOS_INFO
, "Firmware version: %s\n", version_str
);
239 if (cr50_parse_fw_version(version_str
, &cr50_firmware_version
) != CB_SUCCESS
) {
240 printk(BIOS_ERR
, "Did not recognize Cr50 version format\n");
246 *version
= cr50_firmware_version
;
250 enum cb_err
cr50_wait_tpm_ready(void)
254 stopwatch_init_msecs_expire(&sw
, CONFIG_GOOGLE_TPM_IRQ_TIMEOUT_MS
);
256 while (!cr50_plat_irq_status())
257 if (stopwatch_expired(&sw
)) {
258 printk(BIOS_ERR
, "Cr50 TPM IRQ timeout!\n");