xref: /openbmc/qemu/tests/qtest/tpm-tis-i2c-test.c (revision 96420a30)
1bcbbd95dSStefan Berger /*
2bcbbd95dSStefan Berger  * QTest testcases for TPM TIS on I2C (derived from TPM TIS test)
3bcbbd95dSStefan Berger  *
4bcbbd95dSStefan Berger  * Copyright (c) 2023 IBM Corporation
5bcbbd95dSStefan Berger  * Copyright (c) 2023 Red Hat, Inc.
6bcbbd95dSStefan Berger  *
7bcbbd95dSStefan Berger  * Authors:
8bcbbd95dSStefan Berger  *   Stefan Berger <stefanb@linux.ibm.com>
9bcbbd95dSStefan Berger  *   Marc-André Lureau <marcandre.lureau@redhat.com>
10bcbbd95dSStefan Berger  *
11bcbbd95dSStefan Berger  * This work is licensed under the terms of the GNU GPL, version 2 or later.
12bcbbd95dSStefan Berger  * See the COPYING file in the top-level directory.
13bcbbd95dSStefan Berger  */
14bcbbd95dSStefan Berger 
15bcbbd95dSStefan Berger #include "qemu/osdep.h"
16bcbbd95dSStefan Berger #include <glib/gstdio.h>
17bcbbd95dSStefan Berger 
18bcbbd95dSStefan Berger #include "libqtest-single.h"
19bcbbd95dSStefan Berger #include "hw/acpi/tpm.h"
20bcbbd95dSStefan Berger #include "hw/pci/pci_ids.h"
21bcbbd95dSStefan Berger #include "qtest_aspeed.h"
22bcbbd95dSStefan Berger #include "tpm-emu.h"
23bcbbd95dSStefan Berger 
24bcbbd95dSStefan Berger #define DEBUG_TIS_TEST 0
25bcbbd95dSStefan Berger 
26bcbbd95dSStefan Berger #define DPRINTF(fmt, ...) do { \
27bcbbd95dSStefan Berger     if (DEBUG_TIS_TEST) { \
28bcbbd95dSStefan Berger         printf(fmt, ## __VA_ARGS__); \
29bcbbd95dSStefan Berger     } \
30bcbbd95dSStefan Berger } while (0)
31bcbbd95dSStefan Berger 
32bcbbd95dSStefan Berger #define DPRINTF_ACCESS \
33bcbbd95dSStefan Berger     DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \
34bcbbd95dSStefan Berger             __func__, __LINE__, locty, l, access, pending_request_flag)
35bcbbd95dSStefan Berger 
36bcbbd95dSStefan Berger #define DPRINTF_STS \
37bcbbd95dSStefan Berger     DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts)
38bcbbd95dSStefan Berger 
39bcbbd95dSStefan Berger #define I2C_SLAVE_ADDR   0x2e
40bcbbd95dSStefan Berger #define I2C_DEV_BUS_NUM  10
41bcbbd95dSStefan Berger 
42bcbbd95dSStefan Berger static const uint8_t TPM_CMD[12] =
43bcbbd95dSStefan Berger     "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00";
44bcbbd95dSStefan Berger 
45bcbbd95dSStefan Berger static uint32_t aspeed_bus_addr;
46bcbbd95dSStefan Berger 
47bcbbd95dSStefan Berger static uint8_t cur_locty = 0xff;
48bcbbd95dSStefan Berger 
tpm_tis_i2c_set_locty(uint8_t locty)49bcbbd95dSStefan Berger static void tpm_tis_i2c_set_locty(uint8_t locty)
50bcbbd95dSStefan Berger {
51bcbbd95dSStefan Berger     if (cur_locty != locty) {
52bcbbd95dSStefan Berger         cur_locty = locty;
53bcbbd95dSStefan Berger         aspeed_i2c_writeb(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR,
54bcbbd95dSStefan Berger                           TPM_I2C_REG_LOC_SEL, locty);
55bcbbd95dSStefan Berger     }
56bcbbd95dSStefan Berger }
57bcbbd95dSStefan Berger 
tpm_tis_i2c_readb(uint8_t locty,uint8_t reg)58bcbbd95dSStefan Berger static uint8_t tpm_tis_i2c_readb(uint8_t locty, uint8_t reg)
59bcbbd95dSStefan Berger {
60bcbbd95dSStefan Berger     tpm_tis_i2c_set_locty(locty);
61bcbbd95dSStefan Berger     return aspeed_i2c_readb(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg);
62bcbbd95dSStefan Berger }
63bcbbd95dSStefan Berger 
tpm_tis_i2c_readw(uint8_t locty,uint8_t reg)64bcbbd95dSStefan Berger static uint16_t tpm_tis_i2c_readw(uint8_t locty, uint8_t reg)
65bcbbd95dSStefan Berger {
66bcbbd95dSStefan Berger     tpm_tis_i2c_set_locty(locty);
67bcbbd95dSStefan Berger     return aspeed_i2c_readw(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg);
68bcbbd95dSStefan Berger }
69bcbbd95dSStefan Berger 
tpm_tis_i2c_readl(uint8_t locty,uint8_t reg)70bcbbd95dSStefan Berger static uint32_t tpm_tis_i2c_readl(uint8_t locty, uint8_t reg)
71bcbbd95dSStefan Berger {
72bcbbd95dSStefan Berger     tpm_tis_i2c_set_locty(locty);
73bcbbd95dSStefan Berger     return aspeed_i2c_readl(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg);
74bcbbd95dSStefan Berger }
75bcbbd95dSStefan Berger 
tpm_tis_i2c_writeb(uint8_t locty,uint8_t reg,uint8_t v)76bcbbd95dSStefan Berger static void tpm_tis_i2c_writeb(uint8_t locty, uint8_t reg, uint8_t v)
77bcbbd95dSStefan Berger {
78bcbbd95dSStefan Berger     if (reg != TPM_I2C_REG_LOC_SEL) {
79bcbbd95dSStefan Berger         tpm_tis_i2c_set_locty(locty);
80bcbbd95dSStefan Berger     }
81bcbbd95dSStefan Berger     aspeed_i2c_writeb(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v);
82bcbbd95dSStefan Berger }
83bcbbd95dSStefan Berger 
tpm_tis_i2c_writel(uint8_t locty,uint8_t reg,uint32_t v)84bcbbd95dSStefan Berger static void tpm_tis_i2c_writel(uint8_t locty, uint8_t reg, uint32_t v)
85bcbbd95dSStefan Berger {
86bcbbd95dSStefan Berger     if (reg != TPM_I2C_REG_LOC_SEL) {
87bcbbd95dSStefan Berger         tpm_tis_i2c_set_locty(locty);
88bcbbd95dSStefan Berger     }
89bcbbd95dSStefan Berger     aspeed_i2c_writel(global_qtest, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v);
90bcbbd95dSStefan Berger }
91bcbbd95dSStefan Berger 
tpm_tis_i2c_test_basic(const void * data)92bcbbd95dSStefan Berger static void tpm_tis_i2c_test_basic(const void *data)
93bcbbd95dSStefan Berger {
94bcbbd95dSStefan Berger     uint8_t access;
95bcbbd95dSStefan Berger     uint32_t v, v2;
96bcbbd95dSStefan Berger 
97bcbbd95dSStefan Berger     /*
98bcbbd95dSStefan Berger      * All register accesses below must work without locality 0 being the
99bcbbd95dSStefan Berger      * active locality. Therefore, ensure access is released.
100bcbbd95dSStefan Berger      */
101bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
102bcbbd95dSStefan Berger                        TPM_TIS_ACCESS_ACTIVE_LOCALITY);
103bcbbd95dSStefan Berger     access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
104bcbbd95dSStefan Berger     g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
105bcbbd95dSStefan Berger                                 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
106bcbbd95dSStefan Berger 
107bcbbd95dSStefan Berger     /* read interrupt capability -- none are supported */
108bcbbd95dSStefan Berger     v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY);
109bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, 0);
110bcbbd95dSStefan Berger 
111bcbbd95dSStefan Berger     /* try to enable all interrupts */
112bcbbd95dSStefan Berger     tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
113bcbbd95dSStefan Berger     v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE);
114bcbbd95dSStefan Berger     /* none could be enabled */
115bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, 0);
116bcbbd95dSStefan Berger 
117bcbbd95dSStefan Berger     /* enable csum */
118bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
119bcbbd95dSStefan Berger     /* check csum enable register has bit 0 set */
120bcbbd95dSStefan Berger     v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
121bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
122bcbbd95dSStefan Berger     /* reading it as 32bit register returns same result */
123bcbbd95dSStefan Berger     v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
124bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
125bcbbd95dSStefan Berger 
126bcbbd95dSStefan Berger     /* disable csum */
127bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
128bcbbd95dSStefan Berger     /* check csum enable register has bit 0 clear */
129bcbbd95dSStefan Berger     v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
130bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, 0);
131bcbbd95dSStefan Berger 
132bcbbd95dSStefan Berger     /* write to unsupported register '1' */
133bcbbd95dSStefan Berger     tpm_tis_i2c_writel(0, 1, 0x12345678);
134bcbbd95dSStefan Berger     v = tpm_tis_i2c_readl(0, 1);
135bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, 0xffffffff);
136bcbbd95dSStefan Berger 
137bcbbd95dSStefan Berger     /* request use of locality */
138bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
139bcbbd95dSStefan Berger 
140bcbbd95dSStefan Berger     /* read byte from STS + 3 */
141bcbbd95dSStefan Berger     v = tpm_tis_i2c_readb(0, TPM_I2C_REG_STS + 3);
142bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, 0);
143bcbbd95dSStefan Berger 
144bcbbd95dSStefan Berger     /* check STS after writing to STS + 3 */
145bcbbd95dSStefan Berger     v = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
146bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_STS + 3, 0xf);
147bcbbd95dSStefan Berger     v2 = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
148bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, v2);
149bcbbd95dSStefan Berger 
150bcbbd95dSStefan Berger     /* release access */
151bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
152bcbbd95dSStefan Berger                        TPM_TIS_ACCESS_ACTIVE_LOCALITY);
153bcbbd95dSStefan Berger 
154bcbbd95dSStefan Berger     /* select locality 5 -- must not be possible */
155bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_LOC_SEL, 5);
156bcbbd95dSStefan Berger     v = tpm_tis_i2c_readb(0, TPM_I2C_REG_LOC_SEL);
157bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, 0);
158bcbbd95dSStefan Berger }
159bcbbd95dSStefan Berger 
tpm_tis_i2c_test_check_localities(const void * data)160bcbbd95dSStefan Berger static void tpm_tis_i2c_test_check_localities(const void *data)
161bcbbd95dSStefan Berger {
162bcbbd95dSStefan Berger     uint8_t locty, l;
163bcbbd95dSStefan Berger     uint8_t access;
164bcbbd95dSStefan Berger     uint32_t capability, i2c_cap;
165bcbbd95dSStefan Berger     uint32_t didvid;
166bcbbd95dSStefan Berger     uint32_t rid;
167bcbbd95dSStefan Berger 
168bcbbd95dSStefan Berger     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
169bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
170bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
171bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
172bcbbd95dSStefan Berger 
173bcbbd95dSStefan Berger         capability = tpm_tis_i2c_readl(locty, TPM_I2C_REG_INTF_CAPABILITY);
174bcbbd95dSStefan Berger         i2c_cap = (TPM_I2C_CAP_INTERFACE_TYPE |
175bcbbd95dSStefan Berger                    TPM_I2C_CAP_INTERFACE_VER  |
176bcbbd95dSStefan Berger                    TPM_I2C_CAP_TPM2_FAMILY    |
177bcbbd95dSStefan Berger                    TPM_I2C_CAP_LOCALITY_CAP   |
178bcbbd95dSStefan Berger                    TPM_I2C_CAP_BUS_SPEED      |
179bcbbd95dSStefan Berger                    TPM_I2C_CAP_DEV_ADDR_CHANGE);
180bcbbd95dSStefan Berger         g_assert_cmpint(capability, ==, i2c_cap);
181bcbbd95dSStefan Berger 
182bcbbd95dSStefan Berger         didvid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_DID_VID);
183bcbbd95dSStefan Berger         g_assert_cmpint(didvid, ==, (1 << 16) | PCI_VENDOR_ID_IBM);
184bcbbd95dSStefan Berger 
185bcbbd95dSStefan Berger         rid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_RID);
186bcbbd95dSStefan Berger         g_assert_cmpint(rid, !=, 0);
187bcbbd95dSStefan Berger         g_assert_cmpint(rid, !=, 0xffffffff);
188bcbbd95dSStefan Berger 
189bcbbd95dSStefan Berger         /* locality selection must be at locty */
190bcbbd95dSStefan Berger         l = tpm_tis_i2c_readb(locty, TPM_I2C_REG_LOC_SEL);
191bcbbd95dSStefan Berger         g_assert_cmpint(l, ==, locty);
192bcbbd95dSStefan Berger     }
193bcbbd95dSStefan Berger }
194bcbbd95dSStefan Berger 
tpm_tis_i2c_test_check_access_reg(const void * data)195bcbbd95dSStefan Berger static void tpm_tis_i2c_test_check_access_reg(const void *data)
196bcbbd95dSStefan Berger {
197bcbbd95dSStefan Berger     uint8_t locty;
198bcbbd95dSStefan Berger     uint8_t access;
199bcbbd95dSStefan Berger 
200bcbbd95dSStefan Berger     /* do not test locality 4 (hw only) */
201bcbbd95dSStefan Berger     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) {
202bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
203bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
204bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
205bcbbd95dSStefan Berger 
206bcbbd95dSStefan Berger         /* request use of locality */
207bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
208bcbbd95dSStefan Berger                            TPM_TIS_ACCESS_REQUEST_USE);
209bcbbd95dSStefan Berger 
210bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
211bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
212bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_ACTIVE_LOCALITY |
213bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
214bcbbd95dSStefan Berger 
215bcbbd95dSStefan Berger         /* release access */
216bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
217bcbbd95dSStefan Berger                            TPM_TIS_ACCESS_ACTIVE_LOCALITY);
218bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
219bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
220bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
221bcbbd95dSStefan Berger     }
222bcbbd95dSStefan Berger }
223bcbbd95dSStefan Berger 
224bcbbd95dSStefan Berger /*
225bcbbd95dSStefan Berger  * Test case for seizing access by a higher number locality
226bcbbd95dSStefan Berger  */
tpm_tis_i2c_test_check_access_reg_seize(const void * data)227bcbbd95dSStefan Berger static void tpm_tis_i2c_test_check_access_reg_seize(const void *data)
228bcbbd95dSStefan Berger {
229bcbbd95dSStefan Berger     int locty, l;
230bcbbd95dSStefan Berger     uint8_t access;
231bcbbd95dSStefan Berger     uint8_t pending_request_flag;
232bcbbd95dSStefan Berger 
233bcbbd95dSStefan Berger     /* do not test locality 4 (hw only) */
234bcbbd95dSStefan Berger     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) {
235bcbbd95dSStefan Berger         pending_request_flag = 0;
236bcbbd95dSStefan Berger 
237bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
238bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
239bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
240bcbbd95dSStefan Berger 
241bcbbd95dSStefan Berger         /* request use of locality */
242bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(locty,
243bcbbd95dSStefan Berger                            TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
244bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
245bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
246bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_ACTIVE_LOCALITY |
247bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
248bcbbd95dSStefan Berger 
249bcbbd95dSStefan Berger         /* lower localities cannot seize access */
250bcbbd95dSStefan Berger         for (l = 0; l < locty; l++) {
251bcbbd95dSStefan Berger             /* lower locality is not active */
252bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
253bcbbd95dSStefan Berger             DPRINTF_ACCESS;
254bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
255bcbbd95dSStefan Berger                                         pending_request_flag |
256bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
257bcbbd95dSStefan Berger 
258bcbbd95dSStefan Berger             /* try to request use from 'l' */
259bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l,
260bcbbd95dSStefan Berger                                TPM_I2C_REG_ACCESS,
261bcbbd95dSStefan Berger                                TPM_TIS_ACCESS_REQUEST_USE);
262bcbbd95dSStefan Berger 
263bcbbd95dSStefan Berger             /*
264bcbbd95dSStefan Berger              * requesting use from 'l' was not possible;
265bcbbd95dSStefan Berger              * we must see REQUEST_USE and possibly PENDING_REQUEST
266bcbbd95dSStefan Berger              */
267bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
268bcbbd95dSStefan Berger             DPRINTF_ACCESS;
269bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
270bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_REQUEST_USE |
271bcbbd95dSStefan Berger                                         pending_request_flag |
272bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
273bcbbd95dSStefan Berger 
274bcbbd95dSStefan Berger             /*
275bcbbd95dSStefan Berger              * locality 'locty' must be unchanged;
276bcbbd95dSStefan Berger              * we must see PENDING_REQUEST
277bcbbd95dSStefan Berger              */
278bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
279bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
280bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
281bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_PENDING_REQUEST |
282bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
283bcbbd95dSStefan Berger 
284bcbbd95dSStefan Berger             /* try to seize from 'l' */
285bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l,
286bcbbd95dSStefan Berger                                TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
287bcbbd95dSStefan Berger             /* seize from 'l' was not possible */
288bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
289bcbbd95dSStefan Berger             DPRINTF_ACCESS;
290bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
291bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_REQUEST_USE |
292bcbbd95dSStefan Berger                                         pending_request_flag |
293bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
294bcbbd95dSStefan Berger 
295bcbbd95dSStefan Berger             /* locality 'locty' must be unchanged */
296bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
297bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
298bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
299bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_PENDING_REQUEST |
300bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
301bcbbd95dSStefan Berger 
302bcbbd95dSStefan Berger             /*
303bcbbd95dSStefan Berger              * on the next loop we will have a PENDING_REQUEST flag
304bcbbd95dSStefan Berger              * set for locality 'l'
305bcbbd95dSStefan Berger              */
306bcbbd95dSStefan Berger             pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST;
307bcbbd95dSStefan Berger         }
308bcbbd95dSStefan Berger 
309bcbbd95dSStefan Berger         /*
310bcbbd95dSStefan Berger          * higher localities can 'seize' access but not 'request use';
311bcbbd95dSStefan Berger          * note: this will activate first l+1, then l+2 etc.
312bcbbd95dSStefan Berger          */
313bcbbd95dSStefan Berger         for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
314bcbbd95dSStefan Berger             /* try to 'request use' from 'l' */
315bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
316bcbbd95dSStefan Berger                                TPM_TIS_ACCESS_REQUEST_USE);
317bcbbd95dSStefan Berger 
318bcbbd95dSStefan Berger             /*
319bcbbd95dSStefan Berger              * requesting use from 'l' was not possible; we should see
320bcbbd95dSStefan Berger              * REQUEST_USE and may see PENDING_REQUEST
321bcbbd95dSStefan Berger              */
322bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
323bcbbd95dSStefan Berger             DPRINTF_ACCESS;
324bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
325bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_REQUEST_USE |
326bcbbd95dSStefan Berger                                         pending_request_flag |
327bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
328bcbbd95dSStefan Berger 
329bcbbd95dSStefan Berger             /*
330bcbbd95dSStefan Berger              * locality 'l-1' must be unchanged; we should always
331bcbbd95dSStefan Berger              * see PENDING_REQUEST from 'l' requesting access
332bcbbd95dSStefan Berger              */
333bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l - 1, TPM_I2C_REG_ACCESS);
334bcbbd95dSStefan Berger             DPRINTF_ACCESS;
335bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
336bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
337bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_PENDING_REQUEST |
338bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
339bcbbd95dSStefan Berger 
340bcbbd95dSStefan Berger             /* try to seize from 'l' */
341bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
342bcbbd95dSStefan Berger 
343bcbbd95dSStefan Berger             /* seize from 'l' was possible */
344bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
345bcbbd95dSStefan Berger             DPRINTF_ACCESS;
346bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
347bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
348bcbbd95dSStefan Berger                                         pending_request_flag |
349bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
350bcbbd95dSStefan Berger 
351bcbbd95dSStefan Berger             /* l - 1 should show that it has BEEN_SEIZED */
352bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l - 1, TPM_I2C_REG_ACCESS);
353bcbbd95dSStefan Berger             DPRINTF_ACCESS;
354bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
355bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_BEEN_SEIZED |
356bcbbd95dSStefan Berger                                         pending_request_flag |
357bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
358bcbbd95dSStefan Berger 
359bcbbd95dSStefan Berger             /* clear the BEEN_SEIZED flag and make sure it's gone */
360bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l - 1, TPM_I2C_REG_ACCESS,
361bcbbd95dSStefan Berger                                TPM_TIS_ACCESS_BEEN_SEIZED);
362bcbbd95dSStefan Berger 
363bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l - 1, TPM_I2C_REG_ACCESS);
364bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
365bcbbd95dSStefan Berger                                         pending_request_flag |
366bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
367bcbbd95dSStefan Berger         }
368bcbbd95dSStefan Berger 
369bcbbd95dSStefan Berger         /*
370bcbbd95dSStefan Berger          * PENDING_REQUEST will not be set if locty = 0 since all localities
371bcbbd95dSStefan Berger          * were active; in case of locty = 1, locality 0 will be active
372bcbbd95dSStefan Berger          * but no PENDING_REQUEST anywhere
373bcbbd95dSStefan Berger          */
374bcbbd95dSStefan Berger         if (locty <= 1) {
375bcbbd95dSStefan Berger             pending_request_flag = 0;
376bcbbd95dSStefan Berger         }
377bcbbd95dSStefan Berger 
378bcbbd95dSStefan Berger         /* release access from l - 1; this activates locty - 1 */
379bcbbd95dSStefan Berger         l--;
380bcbbd95dSStefan Berger 
381bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
382bcbbd95dSStefan Berger         DPRINTF_ACCESS;
383bcbbd95dSStefan Berger 
384bcbbd95dSStefan Berger         DPRINTF("%s: %d: relinquishing control on l = %d\n",
385bcbbd95dSStefan Berger                 __func__, __LINE__, l);
386bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
387bcbbd95dSStefan Berger                            TPM_TIS_ACCESS_ACTIVE_LOCALITY);
388bcbbd95dSStefan Berger 
389bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
390bcbbd95dSStefan Berger         DPRINTF_ACCESS;
391bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
392bcbbd95dSStefan Berger                                     pending_request_flag |
393bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
394bcbbd95dSStefan Berger 
395bcbbd95dSStefan Berger         for (l = locty - 1; l >= 0; l--) {
396bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
397bcbbd95dSStefan Berger             DPRINTF_ACCESS;
398bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
399bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
400bcbbd95dSStefan Berger                                         pending_request_flag |
401bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
402bcbbd95dSStefan Berger 
403bcbbd95dSStefan Berger             /* release this locality */
404bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
405bcbbd95dSStefan Berger                                TPM_TIS_ACCESS_ACTIVE_LOCALITY);
406bcbbd95dSStefan Berger 
407bcbbd95dSStefan Berger             if (l == 1) {
408bcbbd95dSStefan Berger                 pending_request_flag = 0;
409bcbbd95dSStefan Berger             }
410bcbbd95dSStefan Berger         }
411bcbbd95dSStefan Berger 
412bcbbd95dSStefan Berger         /* no locality may be active now */
413bcbbd95dSStefan Berger         for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
414bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
415bcbbd95dSStefan Berger             DPRINTF_ACCESS;
416bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
417bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
418bcbbd95dSStefan Berger         }
419bcbbd95dSStefan Berger     }
420bcbbd95dSStefan Berger }
421bcbbd95dSStefan Berger 
422bcbbd95dSStefan Berger /*
423bcbbd95dSStefan Berger  * Test case for getting access when higher number locality relinquishes access
424bcbbd95dSStefan Berger  */
tpm_tis_i2c_test_check_access_reg_release(const void * data)425bcbbd95dSStefan Berger static void tpm_tis_i2c_test_check_access_reg_release(const void *data)
426bcbbd95dSStefan Berger {
427bcbbd95dSStefan Berger     int locty, l;
428bcbbd95dSStefan Berger     uint8_t access;
429bcbbd95dSStefan Berger     uint8_t pending_request_flag;
430bcbbd95dSStefan Berger 
431bcbbd95dSStefan Berger     /* do not test locality 4 (hw only) */
432bcbbd95dSStefan Berger     for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) {
433bcbbd95dSStefan Berger         pending_request_flag = 0;
434bcbbd95dSStefan Berger 
435bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
436bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
437bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
438bcbbd95dSStefan Berger 
439bcbbd95dSStefan Berger         /* request use of locality */
440bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
441bcbbd95dSStefan Berger                            TPM_TIS_ACCESS_REQUEST_USE);
442bcbbd95dSStefan Berger         access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
443bcbbd95dSStefan Berger         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
444bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_ACTIVE_LOCALITY |
445bcbbd95dSStefan Berger                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
446bcbbd95dSStefan Berger 
447bcbbd95dSStefan Berger         /* request use of all other localities */
448bcbbd95dSStefan Berger         for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
449bcbbd95dSStefan Berger             if (l == locty) {
450bcbbd95dSStefan Berger                 continue;
451bcbbd95dSStefan Berger             }
452bcbbd95dSStefan Berger             /*
453bcbbd95dSStefan Berger              * request use of locality 'l' -- we MUST see REQUEST USE and
454bcbbd95dSStefan Berger              * may see PENDING_REQUEST
455bcbbd95dSStefan Berger              */
456bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
457bcbbd95dSStefan Berger                                TPM_TIS_ACCESS_REQUEST_USE);
458bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
459bcbbd95dSStefan Berger             DPRINTF_ACCESS;
460bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
461bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_REQUEST_USE |
462bcbbd95dSStefan Berger                                         pending_request_flag |
463bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
464bcbbd95dSStefan Berger             pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST;
465bcbbd95dSStefan Berger         }
466bcbbd95dSStefan Berger         /* release locality 'locty' */
467bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
468bcbbd95dSStefan Berger                            TPM_TIS_ACCESS_ACTIVE_LOCALITY);
469bcbbd95dSStefan Berger         /*
470bcbbd95dSStefan Berger          * highest locality should now be active; release it and make sure the
471*96420a30SMichael Tokarev          * next highest locality is active afterwards
472bcbbd95dSStefan Berger          */
473bcbbd95dSStefan Berger         for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) {
474bcbbd95dSStefan Berger             if (l == locty) {
475bcbbd95dSStefan Berger                 continue;
476bcbbd95dSStefan Berger             }
477bcbbd95dSStefan Berger             /* 'l' should be active now */
478bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
479bcbbd95dSStefan Berger             DPRINTF_ACCESS;
480bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
481bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
482bcbbd95dSStefan Berger                                         pending_request_flag |
483bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
484bcbbd95dSStefan Berger             /* 'l' relinquishes access */
485bcbbd95dSStefan Berger             tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
486bcbbd95dSStefan Berger                                TPM_TIS_ACCESS_ACTIVE_LOCALITY);
487bcbbd95dSStefan Berger             access = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
488bcbbd95dSStefan Berger             DPRINTF_ACCESS;
489bcbbd95dSStefan Berger             if (l == 1 || (locty <= 1 && l == 2)) {
490bcbbd95dSStefan Berger                 pending_request_flag = 0;
491bcbbd95dSStefan Berger             }
492bcbbd95dSStefan Berger             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
493bcbbd95dSStefan Berger                                         pending_request_flag |
494bcbbd95dSStefan Berger                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
495bcbbd95dSStefan Berger         }
496bcbbd95dSStefan Berger     }
497bcbbd95dSStefan Berger }
498bcbbd95dSStefan Berger 
499bcbbd95dSStefan Berger /*
500bcbbd95dSStefan Berger  * Test case for transmitting packets
501bcbbd95dSStefan Berger  */
tpm_tis_i2c_test_check_transmit(const void * data)502bcbbd95dSStefan Berger static void tpm_tis_i2c_test_check_transmit(const void *data)
503bcbbd95dSStefan Berger {
504bcbbd95dSStefan Berger     const TPMTestState *s = data;
505bcbbd95dSStefan Berger     uint8_t access;
506bcbbd95dSStefan Berger     uint32_t sts, v;
507bcbbd95dSStefan Berger     uint16_t bcount, csum, bcount2;
508bcbbd95dSStefan Berger     size_t i;
509bcbbd95dSStefan Berger 
510bcbbd95dSStefan Berger     /* enable csum */
511bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
512bcbbd95dSStefan Berger     /* check csum enable register has bit 0 set */
513bcbbd95dSStefan Berger     v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
514bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
515bcbbd95dSStefan Berger     /* reading it as 32bit register returns same result */
516bcbbd95dSStefan Berger     v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
517bcbbd95dSStefan Berger     g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
518bcbbd95dSStefan Berger 
519bcbbd95dSStefan Berger     /* request use of locality 0 */
520bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
521bcbbd95dSStefan Berger     access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
522bcbbd95dSStefan Berger     g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
523bcbbd95dSStefan Berger                                 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
524bcbbd95dSStefan Berger                                 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
525bcbbd95dSStefan Berger 
526bcbbd95dSStefan Berger     sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
527bcbbd95dSStefan Berger     DPRINTF_STS;
528bcbbd95dSStefan Berger 
529bcbbd95dSStefan Berger     g_assert_cmpint(sts & 0xff, ==, 0);
530bcbbd95dSStefan Berger 
531bcbbd95dSStefan Berger     bcount = (sts >> 8) & 0xffff;
532bcbbd95dSStefan Berger     g_assert_cmpint(bcount, >=, 128);
533bcbbd95dSStefan Berger 
534bcbbd95dSStefan Berger     /* read bcount from STS + 1 must work also */
535bcbbd95dSStefan Berger     bcount2 = tpm_tis_i2c_readw(0, TPM_I2C_REG_STS + 1);
536bcbbd95dSStefan Berger     g_assert_cmpint(bcount, ==, bcount2);
537bcbbd95dSStefan Berger 
538bcbbd95dSStefan Berger     /* ic2 must have bits 26-31 zero */
539bcbbd95dSStefan Berger     g_assert_cmpint(sts & (0x1f << 26), ==, 0);
540bcbbd95dSStefan Berger 
541bcbbd95dSStefan Berger     tpm_tis_i2c_writel(0, TPM_I2C_REG_STS, TPM_TIS_STS_COMMAND_READY);
542bcbbd95dSStefan Berger     sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
543bcbbd95dSStefan Berger     DPRINTF_STS;
544bcbbd95dSStefan Berger     g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY);
545bcbbd95dSStefan Berger 
546bcbbd95dSStefan Berger     /* transmit command */
547bcbbd95dSStefan Berger     for (i = 0; i < sizeof(TPM_CMD); i++) {
548bcbbd95dSStefan Berger         tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_FIFO, TPM_CMD[i]);
549bcbbd95dSStefan Berger         sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
550bcbbd95dSStefan Berger         DPRINTF_STS;
551bcbbd95dSStefan Berger         if (i < sizeof(TPM_CMD) - 1) {
552bcbbd95dSStefan Berger             g_assert_cmpint(sts & 0xff, ==,
553bcbbd95dSStefan Berger                             TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
554bcbbd95dSStefan Berger         } else {
555bcbbd95dSStefan Berger             g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID);
556bcbbd95dSStefan Berger         }
557bcbbd95dSStefan Berger         g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount);
558bcbbd95dSStefan Berger     }
559bcbbd95dSStefan Berger     /* read the checksum */
560bcbbd95dSStefan Berger     csum = tpm_tis_i2c_readw(0, TPM_I2C_REG_DATA_CSUM_GET);
561bcbbd95dSStefan Berger     g_assert_cmpint(csum, ==, 0x6733);
562bcbbd95dSStefan Berger 
563bcbbd95dSStefan Berger     /* start processing */
564bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0, TPM_I2C_REG_STS, TPM_TIS_STS_TPM_GO);
565bcbbd95dSStefan Berger 
566bcbbd95dSStefan Berger     uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND;
567bcbbd95dSStefan Berger     do {
568bcbbd95dSStefan Berger         sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
569bcbbd95dSStefan Berger         if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
570bcbbd95dSStefan Berger             break;
571bcbbd95dSStefan Berger         }
572bcbbd95dSStefan Berger     } while (g_get_monotonic_time() < end_time);
573bcbbd95dSStefan Berger 
574bcbbd95dSStefan Berger     sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
575bcbbd95dSStefan Berger     DPRINTF_STS;
576bcbbd95dSStefan Berger     g_assert_cmpint(sts & 0xff, == ,
577bcbbd95dSStefan Berger                     TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
578bcbbd95dSStefan Berger     bcount = (sts >> 8) & 0xffff;
579bcbbd95dSStefan Berger 
580bcbbd95dSStefan Berger     /* read response */
581bcbbd95dSStefan Berger     uint8_t tpm_msg[sizeof(struct tpm_hdr)];
582bcbbd95dSStefan Berger     g_assert_cmpint(sizeof(tpm_msg), ==, bcount);
583bcbbd95dSStefan Berger 
584bcbbd95dSStefan Berger     for (i = 0; i < sizeof(tpm_msg); i++) {
585bcbbd95dSStefan Berger         tpm_msg[i] = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_FIFO);
586bcbbd95dSStefan Berger         sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
587bcbbd95dSStefan Berger         DPRINTF_STS;
588bcbbd95dSStefan Berger         if (sts & TPM_TIS_STS_DATA_AVAILABLE) {
589bcbbd95dSStefan Berger             g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount);
590bcbbd95dSStefan Berger         }
591bcbbd95dSStefan Berger     }
592bcbbd95dSStefan Berger     g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg));
593bcbbd95dSStefan Berger 
594bcbbd95dSStefan Berger     /* relinquish use of locality 0 */
595bcbbd95dSStefan Berger     tpm_tis_i2c_writeb(0,
596bcbbd95dSStefan Berger                        TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY);
597bcbbd95dSStefan Berger     access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
598bcbbd95dSStefan Berger }
599bcbbd95dSStefan Berger 
main(int argc,char ** argv)600bcbbd95dSStefan Berger int main(int argc, char **argv)
601bcbbd95dSStefan Berger {
602bcbbd95dSStefan Berger     int ret;
603bcbbd95dSStefan Berger     char *args;
604bcbbd95dSStefan Berger     char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-i2c-test.XXXXXX", NULL);
605bcbbd95dSStefan Berger     GThread *thread;
606bcbbd95dSStefan Berger     TPMTestState test;
607bcbbd95dSStefan Berger 
608bcbbd95dSStefan Berger     module_call_init(MODULE_INIT_QOM);
609bcbbd95dSStefan Berger     g_test_init(&argc, &argv, NULL);
610bcbbd95dSStefan Berger 
611bcbbd95dSStefan Berger     test.addr = g_new0(SocketAddress, 1);
612bcbbd95dSStefan Berger     test.addr->type = SOCKET_ADDRESS_TYPE_UNIX;
613bcbbd95dSStefan Berger     test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL);
614bcbbd95dSStefan Berger     g_mutex_init(&test.data_mutex);
615bcbbd95dSStefan Berger     g_cond_init(&test.data_cond);
616bcbbd95dSStefan Berger     test.data_cond_signal = false;
617bcbbd95dSStefan Berger     test.tpm_version = TPM_VERSION_2_0;
618bcbbd95dSStefan Berger 
619bcbbd95dSStefan Berger     thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
620bcbbd95dSStefan Berger     tpm_emu_test_wait_cond(&test);
621bcbbd95dSStefan Berger 
622bcbbd95dSStefan Berger     aspeed_bus_addr = ast2600_i2c_calc_bus_addr(I2C_DEV_BUS_NUM);
623bcbbd95dSStefan Berger 
624bcbbd95dSStefan Berger     args = g_strdup_printf(
625bcbbd95dSStefan Berger         "-machine rainier-bmc -accel tcg "
626bcbbd95dSStefan Berger         "-chardev socket,id=chr,path=%s "
627bcbbd95dSStefan Berger         "-tpmdev emulator,id=tpm0,chardev=chr "
628bcbbd95dSStefan Berger         "-device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.%d,address=0x%x",
629bcbbd95dSStefan Berger         test.addr->u.q_unix.path,
630bcbbd95dSStefan Berger         I2C_DEV_BUS_NUM,
631bcbbd95dSStefan Berger         I2C_SLAVE_ADDR);
632bcbbd95dSStefan Berger     qtest_start(args);
633bcbbd95dSStefan Berger 
634bcbbd95dSStefan Berger     qtest_add_data_func("/tpm-tis-i2c/test_basic", &test,
635bcbbd95dSStefan Berger                         tpm_tis_i2c_test_basic);
636bcbbd95dSStefan Berger 
637bcbbd95dSStefan Berger     qtest_add_data_func("/tpm-tis-i2c/test_check_localities", &test,
638bcbbd95dSStefan Berger                         tpm_tis_i2c_test_check_localities);
639bcbbd95dSStefan Berger 
640bcbbd95dSStefan Berger     qtest_add_data_func("/tpm-tis-i2c/check_access_reg", &test,
641bcbbd95dSStefan Berger                         tpm_tis_i2c_test_check_access_reg);
642bcbbd95dSStefan Berger 
643bcbbd95dSStefan Berger     qtest_add_data_func("/tpm-tis-i2c/check_access_reg_seize", &test,
644bcbbd95dSStefan Berger                         tpm_tis_i2c_test_check_access_reg_seize);
645bcbbd95dSStefan Berger 
646bcbbd95dSStefan Berger     qtest_add_data_func("/tpm-tis-i2c/check_access_reg_release", &test,
647bcbbd95dSStefan Berger                         tpm_tis_i2c_test_check_access_reg_release);
648bcbbd95dSStefan Berger 
649bcbbd95dSStefan Berger     qtest_add_data_func("/tpm-tis-i2c/test_check_transmit", &test,
650bcbbd95dSStefan Berger                         tpm_tis_i2c_test_check_transmit);
651bcbbd95dSStefan Berger 
652bcbbd95dSStefan Berger     ret = g_test_run();
653bcbbd95dSStefan Berger 
654bcbbd95dSStefan Berger     qtest_end();
655bcbbd95dSStefan Berger 
656bcbbd95dSStefan Berger     g_thread_join(thread);
657bcbbd95dSStefan Berger     g_unlink(test.addr->u.q_unix.path);
658bcbbd95dSStefan Berger     qapi_free_SocketAddress(test.addr);
659bcbbd95dSStefan Berger     g_rmdir(tmp_path);
660bcbbd95dSStefan Berger     g_free(tmp_path);
661bcbbd95dSStefan Berger     g_free(args);
662bcbbd95dSStefan Berger     return ret;
663bcbbd95dSStefan Berger }
664