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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. */ 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 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 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. */ 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 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 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 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. */ 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 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