master
c 102 lines 2.81 KB
Raw
1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * QTest utilities for TPM TIS over I2C
5 *
6 * Copyright (c) 2018, 2026 IBM Corporation
7 *
8 * Authors:
9 * Stefan Berger <stefanb@linux.ibm.com>
10 *
11 */
12
13 #include "qemu/osdep.h"
14 #include "hw/acpi/tpm.h"
15 #include "libqtest-single.h"
16 #include "qtest_aspeed.h"
17 #include "tpm-tis-i2c-util.h"
18 #include "tpm-emu.h"
19
20 uint32_t aspeed_bus_addr;
21
22 static uint8_t cur_locty = 0xff;
23
24 static void tpm_tis_i2c_set_locty(QTestState *s, uint8_t locty)
25 {
26 if (cur_locty != locty) {
27 cur_locty = locty;
28 aspeed_i2c_writeb(s, aspeed_bus_addr, I2C_SLAVE_ADDR,
29 TPM_I2C_REG_LOC_SEL, locty);
30 }
31 }
32
33 uint8_t tpm_tis_i2c_readb(QTestState *s, uint8_t locty, uint8_t reg)
34 {
35 tpm_tis_i2c_set_locty(s, locty);
36 return aspeed_i2c_readb(s, aspeed_bus_addr, I2C_SLAVE_ADDR, reg);
37 }
38
39 uint16_t tpm_tis_i2c_readw(QTestState *s, uint8_t locty, uint8_t reg)
40 {
41 tpm_tis_i2c_set_locty(s, locty);
42 return aspeed_i2c_readw(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg);
43 }
44
45 uint32_t tpm_tis_i2c_readl(QTestState *s, uint8_t locty, uint8_t reg)
46 {
47 tpm_tis_i2c_set_locty(s, locty);
48 return aspeed_i2c_readl(s, aspeed_bus_addr, I2C_SLAVE_ADDR, reg);
49 }
50
51 void tpm_tis_i2c_writeb(QTestState *s, uint8_t locty, uint8_t reg, uint8_t v)
52 {
53 if (reg != TPM_I2C_REG_LOC_SEL) {
54 tpm_tis_i2c_set_locty(s, locty);
55 }
56 aspeed_i2c_writeb(s, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v);
57 }
58
59 void tpm_tis_i2c_writel(QTestState *s, uint8_t locty, uint8_t reg, uint32_t v)
60 {
61 if (reg != TPM_I2C_REG_LOC_SEL) {
62 tpm_tis_i2c_set_locty(s, locty);
63 }
64 aspeed_i2c_writel(s, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v);
65 }
66
67 void tpm_tis_i2c_transfer(QTestState *s,
68 const unsigned char *req, size_t req_size,
69 unsigned char *rsp, size_t rsp_size)
70 {
71 uint32_t sts;
72 size_t i;
73
74 /* request use of locality 0 */
75 tpm_tis_i2c_writeb(s, 0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
76
77 tpm_tis_i2c_writel(s, 0, TPM_I2C_REG_STS, TPM_TIS_STS_COMMAND_READY);
78
79 /* transmit command */
80 for (i = 0; i < req_size; i++) {
81 tpm_tis_i2c_writeb(s, 0, TPM_I2C_REG_DATA_FIFO, req[i]);
82 }
83
84 /* start processing */
85 tpm_tis_i2c_writeb(s, 0, TPM_I2C_REG_STS, TPM_TIS_STS_TPM_GO);
86
87 uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND;
88 do {
89 sts = tpm_tis_i2c_readl(s, 0, TPM_I2C_REG_STS);
90 if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
91 break;
92 }
93 } while (g_get_monotonic_time() < end_time);
94
95 /* read response */
96 for (i = 0; i < rsp_size; i++) {
97 rsp[i] = tpm_tis_i2c_readb(s, 0, TPM_I2C_REG_DATA_FIFO);
98 }
99 /* relinquish use of locality 0 */
100 tpm_tis_i2c_writeb(s, 0,
101 TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY);
102 }