xref: /openbmc/qemu/tests/qtest/remote-i3c-test.c (revision ee53f8a6e48f8e35e13cff7846b3d9a1c47581ab)
1 /*
2  * QTest testcase for the remote I3C device, using the AST2600 I3C controller.
3  *
4  * Copyright 2023 Google LLC
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14  * for more details.
15  */
16 
17 #include "qemu/osdep.h"
18 #include "libqtest-single.h"
19 #include "hw/registerfields.h"
20 #include "hw/i3c/i3c.h"
21 #include "hw/i3c/remote-i3c.h"
22 #include "hw/i3c/aspeed_i3c.h"
23 
24 /* Starting address of the AST2600 I3C block. */
25 #define ASPEED_I3C_BASE 0x1e7a0000
26 /* Offset to the first controller in the block. */
27 #define ASPEED_I3C_CONTROLLER_OFFSET 0x2000
28 #define I3C(x) (ASPEED_I3C_BASE + ASPEED_I3C_CONTROLLER_OFFSET + ((x) * 0x1000))
29 #define TARGET_ADDR 0x10
30 
31 /* I3C Device Registers */
32 REG32(DEVICE_CTRL,                  0x00)
33     FIELD(DEVICE_CTRL, I3C_BROADCAST_ADDR_INC,    0, 1)
34     FIELD(DEVICE_CTRL, I2C_SLAVE_PRESENT,         7, 1)
35     FIELD(DEVICE_CTRL, HOT_JOIN_ACK_NACK_CTRL,    8, 1)
36     FIELD(DEVICE_CTRL, IDLE_CNT_MULTIPLIER,       24, 2)
37     FIELD(DEVICE_CTRL, SLV_ADAPT_TO_I2C_I3C_MODE, 27, 1)
38     FIELD(DEVICE_CTRL, DMA_HANDSHAKE_EN,          28, 1)
39     FIELD(DEVICE_CTRL, I3C_ABORT,                 29, 1)
40     FIELD(DEVICE_CTRL, I3C_RESUME,                30, 1)
41     FIELD(DEVICE_CTRL, I3C_EN,                    31, 1)
42 REG32(COMMAND_QUEUE_PORT,           0x0c)
43     FIELD(COMMAND_QUEUE_PORT, CMD_ATTR, 0, 3)
44     /* Transfer command structure */
45     FIELD(COMMAND_QUEUE_PORT, TID, 3, 4)
46     FIELD(COMMAND_QUEUE_PORT, CMD, 7, 8)
47     FIELD(COMMAND_QUEUE_PORT, CP, 15, 1)
48     FIELD(COMMAND_QUEUE_PORT, DEV_INDEX, 16, 5)
49     FIELD(COMMAND_QUEUE_PORT, SPEED, 21, 3)
50     FIELD(COMMAND_QUEUE_PORT, ROC, 26, 1)
51     FIELD(COMMAND_QUEUE_PORT, SDAP, 27, 1)
52     FIELD(COMMAND_QUEUE_PORT, RNW, 28, 1)
53     FIELD(COMMAND_QUEUE_PORT, TOC, 30, 1)
54     FIELD(COMMAND_QUEUE_PORT, PEC, 31, 1)
55     /* Transfer argument data structure */
56     FIELD(COMMAND_QUEUE_PORT, DB, 8, 8)
57     FIELD(COMMAND_QUEUE_PORT, DL, 16, 16)
58     /* Short data argument data structure */
59     FIELD(COMMAND_QUEUE_PORT, BYTE_STRB, 3, 3)
60     FIELD(COMMAND_QUEUE_PORT, BYTE0, 8, 8)
61     FIELD(COMMAND_QUEUE_PORT, BYTE1, 16, 8)
62     FIELD(COMMAND_QUEUE_PORT, BYTE2, 24, 8)
63     /* Address assignment command structure */
64     /*
65      * bits 3..21 and 26..31 are the same as the transfer command structure, or
66      * marked as reserved.
67      */
68     FIELD(COMMAND_QUEUE_PORT, DEV_COUNT, 21, 3)
69 REG32(RESPONSE_QUEUE_PORT,          0x10)
70     FIELD(RESPONSE_QUEUE_PORT, DL, 0, 16)
71     FIELD(RESPONSE_QUEUE_PORT, CCCT, 16, 8)
72     FIELD(RESPONSE_QUEUE_PORT, TID, 24, 4)
73     FIELD(RESPONSE_QUEUE_PORT, ERR_STATUS, 28, 4)
74 REG32(RX_TX_DATA_PORT,              0x14)
75 REG32(IBI_QUEUE_STATUS,             0x18)
76     FIELD(IBI_QUEUE_STATUS, IBI_DATA_LEN,   0, 8)
77     FIELD(IBI_QUEUE_STATUS, IBI_ID,         8, 8)
78     FIELD(IBI_QUEUE_STATUS, IBI_RX_STATUS,  28, 4)
79 REG32(IBI_QUEUE_DATA,               0x18)
80 REG32(QUEUE_STATUS_LEVEL,           0x4c)
81     FIELD(QUEUE_STATUS_LEVEL, CMD_QUEUE_EMPTY_LOC,  0, 8)
82     FIELD(QUEUE_STATUS_LEVEL, RESP_BUF_BLR,         8, 8)
83     FIELD(QUEUE_STATUS_LEVEL, IBI_BUF_BLR,          16, 8)
84     FIELD(QUEUE_STATUS_LEVEL, IBI_STATUS_CNT,       24, 5)
85 REG32(DATA_BUFFER_STATUS_LEVEL,     0x50)
86     FIELD(DATA_BUFFER_STATUS_LEVEL, TX_BUF_EMPTY_LOC, 0, 8)
87     FIELD(DATA_BUFFER_STATUS_LEVEL, RX_BUF_BLR,       16, 8)
88 /* Dev addr table fields */
89 REG32(DEVICE_ADDR_TABLE_LOC1, 0x280)
90     FIELD(DEVICE_ADDR_TABLE_LOC1, DEV_DYNAMIC_ADDR, 16, 8)
91 
92 typedef union AspeedI3CResponse {
93     uint32_t word;
94     uint16_t data_len;
95     uint8_t ccc_type;
96     uint8_t tid:4;
97     uint8_t err:4;
98 } AspeedI3CResponse;
99 
100 static int sock;
101 static int fd;
102 
open_socket(void)103 static in_port_t open_socket(void)
104 {
105     struct sockaddr_in myaddr;
106     struct timeval timeout = { .tv_sec = 1, };
107     socklen_t addrlen;
108 
109     myaddr.sin_family = AF_INET;
110     myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
111     myaddr.sin_port = 0;
112     sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
113     g_assert(sock != -1);
114     g_assert(bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) != -1);
115     setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
116 
117     addrlen = sizeof(myaddr);
118     g_assert(getsockname(sock, (struct sockaddr *) &myaddr , &addrlen) != -1);
119     g_assert(listen(sock, 1) != -1);
120     return ntohs(myaddr.sin_port);
121 }
122 
setup_fd(void)123 static void setup_fd(void)
124 {
125     fd_set readfds;
126 
127     FD_ZERO(&readfds);
128     FD_SET(sock, &readfds);
129     g_assert(select(sock + 1, &readfds, NULL, NULL, NULL) == 1);
130 
131     fd = accept(sock, NULL, 0);
132 }
133 
aspeed_i3c_create_xfer_cmd(uint8_t cmd,uint8_t dev_index,bool rnw,bool dbp)134 static AspeedI3CTransferCmd aspeed_i3c_create_xfer_cmd(uint8_t cmd,
135                                                        uint8_t dev_index,
136                                                        bool rnw,
137                                                        bool dbp)
138 {
139     return ((AspeedI3CTransferCmd) {
140         .cmd_attr = ASPEED_I3C_CMD_ATTR_TRANSFER_CMD,
141         .tid = 0x01,
142         .cmd = cmd,
143         .cp = (cmd != 0) ? 1 : 0,
144         .dev_index = dev_index,
145         .speed = 0, /* SDR */
146         .dbp = dbp,
147         .roc = 1,
148         .sdap = (cmd == 0x02) ? 1 : 0, /* Short data arg present. */
149         .rnw = rnw,
150         .toc = 1,
151         .pec = 0
152     });
153 }
154 
aspeed_i3c_create_xfer_arg(uint8_t db,uint16_t data_len)155 static AspeedI3CTransferArg aspeed_i3c_create_xfer_arg(uint8_t db,
156                                                        uint16_t data_len)
157 {
158     return ((AspeedI3CTransferArg) {
159         .cmd_attr = ASPEED_I3C_CMD_ATTR_TRANSFER_ARG,
160         .db = db,
161         .data_len = data_len,
162     });
163 }
164 
aspeed_i3c_enable(uint32_t base)165 static void aspeed_i3c_enable(uint32_t base)
166 {
167     uint32_t val = readl(base + A_DEVICE_CTRL);
168     val = FIELD_DP32(val, DEVICE_CTRL, I3C_RESUME, 1);
169     val = FIELD_DP32(val, DEVICE_CTRL, I3C_EN, 1);
170     writel(base + A_DEVICE_CTRL, val);
171     /*
172      * Sanity check the enable write. I3C_RESUME is auto-cleared so don't
173      * check it.
174      */
175     g_assert(readl(base + A_DEVICE_CTRL) & R_DEVICE_CTRL_I3C_EN_MASK);
176 }
177 
aspeed_i3c_read_resp(uint32_t base)178 static AspeedI3CResponse aspeed_i3c_read_resp(uint32_t base)
179 {
180     AspeedI3CResponse resp;
181     uint32_t queue_status = readl(base + A_QUEUE_STATUS_LEVEL);
182     /* No response to read. */
183     if (FIELD_EX32(queue_status, QUEUE_STATUS_LEVEL, RESP_BUF_BLR) == 0) {
184         resp.word = 0;
185     } else {
186         resp.word = readl(base + A_DEVICE_CTRL);
187     }
188     return resp;
189 }
190 
aspeed_i3c_send(uint32_t base,uint8_t dev_index,const uint32_t * data,uint16_t len)191 static void aspeed_i3c_send(uint32_t base, uint8_t dev_index,
192                             const uint32_t *data, uint16_t len)
193 {
194     AspeedI3CCmdQueueData cmd;
195     AspeedI3CCmdQueueData arg;
196     uint16_t words_txed = 0;
197 
198     /* Start doing the transfer. */
199     while (words_txed < len) {
200         /* Push data to the TX queue. */
201         uint32_t tx_num_empty = FIELD_EX32(readl(base +
202                                                  A_DATA_BUFFER_STATUS_LEVEL),
203                                            DATA_BUFFER_STATUS_LEVEL,
204                                            TX_BUF_EMPTY_LOC);
205         for (uint16_t i = 0; i < tx_num_empty; i++) {
206             writel(base + A_RX_TX_DATA_PORT, data[words_txed]);
207             words_txed++;
208             /* We have no more to transfer, bail early. */
209             if (words_txed >= len) {
210                 break;
211             }
212         }
213 
214         /* Now that the data is in the queue, we can start our transfer. */
215         /*
216          * CMD is ignored due to this not being a CCC, and there is no defining
217          * byte, also because this isn't a CCC.
218          */
219         cmd.transfer_cmd = aspeed_i3c_create_xfer_cmd(0, dev_index, false,
220                                                       false);
221         arg.transfer_arg = aspeed_i3c_create_xfer_arg(0, len * sizeof(*data));
222         /* Order to push is arg then command. */
223         writel(base + A_COMMAND_QUEUE_PORT, arg.word);
224         writel(base + A_COMMAND_QUEUE_PORT, cmd.word);
225     }
226 }
227 
aspeed_i3c_send_ccc(uint32_t base,uint8_t ccc_cmd)228 static void aspeed_i3c_send_ccc(uint32_t base, uint8_t ccc_cmd)
229 {
230     AspeedI3CCmdQueueData cmd;
231     AspeedI3CCmdQueueData arg;
232 
233     cmd.transfer_cmd = aspeed_i3c_create_xfer_cmd(ccc_cmd, 0, false,
234                                                   false);
235     arg.transfer_arg = aspeed_i3c_create_xfer_arg(0, 0);
236     /* Order to push is arg then command. */
237     writel(base + A_COMMAND_QUEUE_PORT, arg.word);
238     writel(base + A_COMMAND_QUEUE_PORT, cmd.word);
239 }
240 
aspeed_i3c_recv(uint32_t base,uint8_t dev_index,uint8_t * data,uint16_t len)241 static void aspeed_i3c_recv(uint32_t base, uint8_t dev_index, uint8_t *data,
242                             uint16_t len)
243 {
244     AspeedI3CCmdQueueData cmd;
245     AspeedI3CCmdQueueData arg;
246     uint16_t bytes_rxed = 0;
247     uint32_t *p32_data = (uint32_t *)data;
248 
249     /* Start doing the transfer. */
250     while (bytes_rxed < len) {
251         /* Send the RX request. */
252         /*
253          * CMD is ignored due to this not being a CCC, and there is no defining
254          * byte, also because this isn't a CCC.
255          */
256         cmd.transfer_cmd = aspeed_i3c_create_xfer_cmd(0, dev_index, true,
257                                                       false);
258         uint16_t num_to_rx = (len - bytes_rxed) > ASPEED_I3C_RX_QUEUE_CAPACITY ?
259             ASPEED_I3C_RX_QUEUE_CAPACITY : (len - bytes_rxed);
260         arg.transfer_arg = aspeed_i3c_create_xfer_arg(0, num_to_rx);
261         /* Order to push is arg then command. */
262         writel(base + A_COMMAND_QUEUE_PORT, arg.word);
263         writel(base + A_COMMAND_QUEUE_PORT, cmd.word);
264 
265         /* Read the data from the data RX queue. */
266         uint32_t rx_word_num =
267             FIELD_EX32(readl(base + A_DATA_BUFFER_STATUS_LEVEL),
268                              DATA_BUFFER_STATUS_LEVEL, RX_BUF_BLR);
269         for (uint16_t i = 0; i < rx_word_num; i++) {
270             *p32_data = readl(base + A_RX_TX_DATA_PORT);
271             p32_data++;
272             bytes_rxed += 4;
273         }
274     }
275 }
276 
assert_good_resp(uint32_t base)277 static void assert_good_resp(uint32_t base)
278 {
279     /* We expect a good response from this. */
280     AspeedI3CResponse resp = aspeed_i3c_read_resp(base);
281     g_assert(resp.err == ASPEED_I3C_RESP_QUEUE_ERR_NONE);
282 }
283 
read_data(uint8_t * data,size_t len)284 static void read_data(uint8_t *data, size_t len)
285 {
286     ssize_t ret;
287     size_t len_read = 0;
288 
289     while (len_read < len) {
290         ret = read(fd, &data[len_read], len);
291         g_assert(ret != -1);
292         len_read += ret;
293     }
294 }
295 
remote_i3c_read_and_verify(const uint8_t * expected_data,size_t len)296 static void remote_i3c_read_and_verify(const uint8_t *expected_data, size_t len)
297 {
298     g_autofree uint8_t *data_read = g_new0(uint8_t, len);
299 
300     read_data(data_read, len);
301     g_assert(memcmp(data_read, expected_data, len) == 0);
302 }
303 
add_targets_to_bus(uint32_t base)304 static void add_targets_to_bus(uint32_t base)
305 {
306     /* Arbitrary large enough size. */
307     uint8_t remote_target_expected_data[8];
308 
309     /* Send SATAASA to the remote target. */
310     aspeed_i3c_send_ccc(base, I3C_CCC_SETAASA);
311     /*
312      * Verify everything is good.
313      * The remote target should receive:
314      * - an I3C_START event
315      * - the size of the CCC packet as a LE uint32
316      * - the CCC
317      * - then an I3C_STOP event.
318      * The controller should have a good response in the queue.
319      */
320     assert_good_resp(base);
321     remote_target_expected_data[0] = REMOTE_I3C_START_SEND;
322     remote_target_expected_data[1] = REMOTE_I3C_HANDLE_CCC_WRITE;
323     uint32_t *p32 = (uint32_t *)&remote_target_expected_data[2];
324     *p32 = htole32(1);
325     remote_target_expected_data[6] = I3C_CCC_SETAASA;
326     remote_target_expected_data[7] = REMOTE_I3C_STOP;
327     remote_i3c_read_and_verify(remote_target_expected_data, 8);
328 
329     /*
330      * Populate the device table. On a real system we would either:
331      * - populate the table and send ENTDAA, then probe the addresses to see who
332      *   exists.
333      * - SETAASA and then go through a list addresses to see who exists, probe
334      *   them, and add them to the table.
335      * We're doing the SETAASA way, minus the probing portion, so just add the
336      * known address to the table.
337      */
338     uint32_t val = 0;
339     val = FIELD_DP32(val, DEVICE_ADDR_TABLE_LOC1, DEV_DYNAMIC_ADDR,
340                      TARGET_ADDR);
341     writel(base + A_DEVICE_ADDR_TABLE_LOC1, val);
342 }
343 
send_and_verify(uint32_t i3c_base,const uint32_t * data,size_t len)344 static void send_and_verify(uint32_t i3c_base, const uint32_t *data, size_t len)
345 {
346     /*
347      * Add padding to the data_read packet, since the remote target will receive
348      * extra bytes that include the I3C START and STOP events, along with the
349      * length of the packet, and the data packet itself.
350      */
351     uint32_t data_size = len * sizeof(*data);
352     size_t expected_data_len = data_size + 7;
353     g_autofree uint8_t *remote_target_expected_data = g_new0(uint8_t,
354                                                              expected_data_len);
355     remote_target_expected_data[0] = REMOTE_I3C_START_SEND;
356     remote_target_expected_data[1] = REMOTE_I3C_SEND;
357     uint32_t *p32 = (uint32_t *)&remote_target_expected_data[2];
358     *p32 = htole32(data_size);
359     memcpy(&remote_target_expected_data[6], data, data_size);
360     remote_target_expected_data[data_size + 6] = REMOTE_I3C_STOP;
361 
362     aspeed_i3c_send(i3c_base, 0, data, len);
363     assert_good_resp(i3c_base);
364     remote_i3c_read_and_verify(remote_target_expected_data, expected_data_len);
365 }
366 
367 /* Remote target RX, e.g. controller -> target. */
test_remote_i3c_rx(gconstpointer test_data)368 static void test_remote_i3c_rx(gconstpointer test_data)
369 {
370     uint32_t controller_num = *(uint32_t *)test_data;
371     uint32_t i3c_base = I3C(controller_num);
372     /*
373      * The Aspeed controller expects data in 32-bit words, so make this 32-bits.
374      */
375     const uint32_t data[] = {7, 6, 5, 4, 3, 2, 1, 0};
376     /* Enable the controller. */
377     aspeed_i3c_enable(i3c_base);
378     /*
379      * Tell the target to use its static address as its dynamic address, and
380      * populate the device table.
381      */
382     add_targets_to_bus(i3c_base);
383     /* Now we can test sending data to the target. */
384     send_and_verify(i3c_base, data, ARRAY_SIZE(data));
385 }
386 
read_and_verify(uint32_t i3c_base,const uint8_t * data,size_t len)387 static void read_and_verify(uint32_t i3c_base, const uint8_t *data, size_t len)
388 {
389     g_autofree uint8_t *data_received = g_new0(uint8_t, len);
390 
391     /* Send the I3C recv request. */
392     aspeed_i3c_recv(i3c_base, 0, data_received, len);
393     /*
394      * Verify everything is okay. Anything on the remote I3C protocol level is
395      * handled by the remote target thread. We just need to check that we
396      * received what we expected.
397      */
398     assert_good_resp(i3c_base);
399     g_assert(memcmp(data_received, data, len) == 0);
400 }
401 
remote_target_thread(void * arg)402 static void *remote_target_thread(void *arg)
403 {
404     uint8_t byte;
405     uint32_t bytes_to_send;
406     uint32_t bytes_to_send_le;
407     const uint8_t *data = (const uint8_t *)arg;
408 
409     /* Loop forever reading and parsing incoming data. */
410     while (1) {
411         /*
412          * We can error out during program teardown due to the socket closing,
413          * so don't assert.
414          * If this has a proper error during test, the main thread will error
415          * due to the target thread (this one) not sending anything.
416          */
417         if (read(fd, &byte, 1) != 1) {
418             break;
419         }
420 
421         switch (byte) {
422         case REMOTE_I3C_START_RECV:
423         case REMOTE_I3C_STOP:
424             /* Don't care, do nothing. */
425             break;
426         case REMOTE_I3C_RECV:
427             /* Read in the number of bytes the controller wants. */
428             g_assert(read(fd, &bytes_to_send_le, sizeof(bytes_to_send_le)) ==
429                           sizeof(bytes_to_send_le));
430             bytes_to_send = le32toh(bytes_to_send_le);
431 
432             /*
433              * Send the data. We first send the number of bytes we're sending as
434              * a uint32 LE word (which is the same as the number of bytes the
435              * controller is expecting), followed by the data.
436              */
437             g_assert(write(fd, (uint8_t *)&bytes_to_send_le,
438                            sizeof(bytes_to_send_le)) ==
439                      sizeof(bytes_to_send_le));
440             g_assert(write(fd, data, bytes_to_send) == bytes_to_send);
441             break;
442         default:
443             g_printerr("Remote target received unknown byte 0x%.2x\n", byte);
444             g_assert_not_reached();
445         }
446     }
447 
448     return NULL;
449 }
450 
451 /* Remote target TX, e.g. target -> controller. */
test_remote_i3c_tx(gconstpointer test_data)452 static void test_remote_i3c_tx(gconstpointer test_data)
453 {
454     uint32_t controller_num = *(uint32_t *)test_data;
455     uint32_t i3c_base = I3C(controller_num);
456     /* Non-const since the thread prototype needs a non-const pointer. */
457     uint8_t data[] = {7, 6, 5, 4, 3, 2, 1, 0};
458     GThread *target_thread;
459     /* Enable the controller. */
460     aspeed_i3c_enable(i3c_base);
461     /*
462      * Tell the target to use its static address as its dynamic address, and
463      * populate the device table.
464      */
465     add_targets_to_bus(i3c_base);
466 
467     /*
468      * Now we can test receiving data from the target.
469      * The target will need to respond while the controller is doing the I3C
470      * receive (meaning we will be blocked on the remote target sending data to
471      * us), so we need to make a separate thread for the remote target to send
472      * data to the controller.
473      */
474     target_thread = g_thread_new("remote-target", remote_target_thread, data);
475     read_and_verify(i3c_base, data, ARRAY_SIZE(data));
476     g_thread_join(target_thread);
477 }
478 
remote_i3c_ibi(const uint32_t * data,uint32_t len)479 static void remote_i3c_ibi(const uint32_t *data, uint32_t len)
480 {
481     /* Convert len to bytes to make math cleaner. */
482     len *= sizeof(uint32_t);
483     /*
484      * IBI format is:
485      * - 1-byte REMOTE_I3C_IBI request.
486      * - 1-byte address of target sending the IBI.
487      * - 1-byte RnW bit.
488      * - 4-byte size of IBI payload.
489      * - n-byte IBI payload.
490      */
491     size_t ibi_req_size = 7 + len;
492     g_autofree uint8_t *ibi_req = g_new0(uint8_t, ibi_req_size);
493     uint32_t len_le;
494     uint8_t ibi_resp;
495 
496     ibi_req[0] = REMOTE_I3C_IBI;
497     ibi_req[1] = TARGET_ADDR;
498     ibi_req[2] = 0; /* RnW = 0 to make this a target interrupt request. */
499     len_le = htole32(len);
500     memcpy(&ibi_req[3], &len_le, sizeof(len_le));
501     memcpy(&ibi_req[7], data, len);
502 
503     /* Send the request and read back the ACK. */
504     g_assert(write(fd, ibi_req, ibi_req_size) == ibi_req_size);
505     g_assert(read(fd, &ibi_resp, sizeof(ibi_resp)) == sizeof(ibi_resp));
506     g_assert(ibi_resp == REMOTE_I3C_IBI_ACK);
507 }
508 
aspeed_i3c_read_ibi_and_verify(uint32_t i3c_base,const uint32_t * data,size_t len)509 static void aspeed_i3c_read_ibi_and_verify(uint32_t i3c_base,
510                                            const uint32_t *data, size_t len)
511 {
512     g_autofree uint32_t *ibi_data = g_new0(uint32_t, len * sizeof(uint32_t));
513 
514     /* Make sure there's actually something to read in the IBI queue. */
515     uint8_t ibi_buf_lvl = FIELD_EX32(readl(i3c_base + A_QUEUE_STATUS_LEVEL),
516                                      QUEUE_STATUS_LEVEL, IBI_BUF_BLR);
517     /*
518      * ibi_buf_level should have 1-byte for IBI status, plus data size in words.
519      */
520     g_assert(ibi_buf_lvl == 1 + len);
521     uint32_t ibi_status = readl(i3c_base + A_IBI_QUEUE_STATUS);
522     /* IBI_ID is target address << 1 | RnW bit (which is 0) */
523     g_assert(FIELD_EX32(ibi_status, IBI_QUEUE_STATUS, IBI_ID) ==
524              (TARGET_ADDR << 1));
525     /* IBI data length in the register is stored in bytes. */
526     uint32_t ibi_data_len = FIELD_EX32(ibi_status, IBI_QUEUE_STATUS,
527                                        IBI_DATA_LEN);
528     g_assert(ibi_data_len == len * sizeof(uint32_t));
529 
530     /*
531      * Read in the IBI bytes, if they aren't word-aligned, read in an extra
532      * word.
533      */
534     for (size_t i = 0; i < (ibi_data_len / 4) +
535                            (ibi_data_len & 0x03) ? 1 : 0; i++) {
536         ibi_data[i] = readl(i3c_base + A_IBI_QUEUE_DATA);
537     }
538     /* Make sure the data matches. */
539     g_assert(memcmp(ibi_data, data, len) == 0);
540 }
541 
ibi_and_verify(uint32_t i3c_base,const uint32_t * data,size_t len)542 static void ibi_and_verify(uint32_t i3c_base, const uint32_t *data, size_t len)
543 {
544     /* Send the IBI request. */
545     remote_i3c_ibi(data, len);
546     /* Read it and verify it matches what we expect. */
547     aspeed_i3c_read_ibi_and_verify(i3c_base, data, len);
548 }
549 
550 /* Remote target IBI. */
test_remote_i3c_ibi(gconstpointer test_data)551 static void test_remote_i3c_ibi(gconstpointer test_data)
552 {
553     uint32_t controller_num = *(uint32_t *)test_data;
554     uint32_t i3c_base = I3C(controller_num);
555     uint32_t data = 0xaa55cc33;
556     /* Enable the controller. */
557     aspeed_i3c_enable(i3c_base);
558     /*
559      * Tell the target to use its static address as its dynamic address, and
560      * populate the device table.
561      */
562     add_targets_to_bus(i3c_base);
563 
564     /*
565      * To test IBIing, we will:
566      * - Have the target IBI the controller by writing to the socket.
567      * - The controller ACKs and enqueues the IBI request.
568      * - The ACK is sent over socket, we verify it's there.
569      * - We read the request from the controller IBI queue.
570      */
571     ibi_and_verify(i3c_base, &data, 1);
572 }
573 
main(int argc,char ** argv)574 int main(int argc, char **argv)
575 {
576     int ret;
577     int port;
578     /* Global register base address + offset of first controller. */
579     uint32_t i3c_controller_num = 0;
580     g_test_init(&argc, &argv, NULL);
581     port = open_socket();
582 
583     global_qtest = qtest_initf("-machine ast2600-evb "
584                 "-chardev socket,id=remote-i3c-chr,port=%d,host=localhost "
585                 "-device %s,"
586                 "chardev=remote-i3c-chr,"
587                 "device-name=remote-target,"
588                 "bus=aspeed.i3c.device.0,"
589                 "pid=0xfeedf00dd00d,"
590                 "dcr=0xaa,"
591                 "bcr=0x55,"
592                 "static-address=%d",
593                 port, TYPE_REMOTE_I3C, TARGET_ADDR);
594     setup_fd();
595 
596     /* Remote target RXing, i.e. controller -> target. */
597     qtest_add_data_func("remote-i3c-rx", (void *)&i3c_controller_num,
598                         test_remote_i3c_rx);
599     /* Remote target TXing, i.e. controller -> target. */
600     qtest_add_data_func("remote-i3c-tx", (void *)&i3c_controller_num,
601                         test_remote_i3c_tx);
602     /* Remote target IBIing. */
603     qtest_add_data_func("remote-i3c-ibi", (void *)&i3c_controller_num,
604                         test_remote_i3c_ibi);
605 
606     ret = g_test_run();
607     qtest_end();
608 
609     return ret;
610 }
611