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