migration/rdma: Drop qemu_rdma_search_ram_block() error handling
[qemu/kevin.git] / tests / qtest / xlnx-canfd-test.c
blob78ec9ef2a76404703c3eccbe3dcc63f12a55eb23
1 /*
2 * SPDX-License-Identifier: MIT
4 * QTests for the Xilinx Versal CANFD controller.
6 * Copyright (c) 2022 AMD Inc.
8 * Written-by: Vikram Garhwal<vikram.garhwal@amd.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
29 #include "qemu/osdep.h"
30 #include "libqtest.h"
32 /* Base address. */
33 #define CANFD0_BASE_ADDR 0xff060000
34 #define CANFD1_BASE_ADDR 0xff070000
36 /* Register addresses. */
37 #define R_SRR_OFFSET 0x00
38 #define R_MSR_OFFSET 0x04
39 #define R_FILTER_CONTROL_REGISTER 0xe0
40 #define R_SR_OFFSET 0x18
41 #define R_ISR_OFFSET 0x1c
42 #define R_IER_OFFSET 0x20
43 #define R_ICR_OFFSET 0x24
44 #define R_TX_READY_REQ_REGISTER 0x90
45 #define RX_FIFO_STATUS_REGISTER 0xe8
46 #define R_TXID_OFFSET 0x100
47 #define R_TXDLC_OFFSET 0x104
48 #define R_TXDATA1_OFFSET 0x108
49 #define R_TXDATA2_OFFSET 0x10c
50 #define R_AFMR_REGISTER0 0xa00
51 #define R_AFIR_REGISTER0 0xa04
52 #define R_RX0_ID_OFFSET 0x2100
53 #define R_RX0_DLC_OFFSET 0x2104
54 #define R_RX0_DATA1_OFFSET 0x2108
55 #define R_RX0_DATA2_OFFSET 0x210c
57 /* CANFD modes. */
58 #define SRR_CONFIG_MODE 0x00
59 #define MSR_NORMAL_MODE 0x00
60 #define MSR_LOOPBACK_MODE (1 << 1)
61 #define ENABLE_CANFD (1 << 1)
63 /* CANFD status. */
64 #define STATUS_CONFIG_MODE (1 << 0)
65 #define STATUS_NORMAL_MODE (1 << 3)
66 #define STATUS_LOOPBACK_MODE (1 << 1)
67 #define ISR_TXOK (1 << 1)
68 #define ISR_RXOK (1 << 4)
70 #define ENABLE_ALL_FILTERS 0xffffffff
71 #define ENABLE_ALL_INTERRUPTS 0xffffffff
73 /* We are sending one canfd message. */
74 #define TX_READY_REG_VAL 0x1
76 #define FIRST_RX_STORE_INDEX 0x1
77 #define STATUS_REG_MASK 0xf
78 #define DLC_FD_BIT_SHIFT 0x1b
79 #define DLC_FD_BIT_MASK 0xf8000000
80 #define FIFO_STATUS_READ_INDEX_MASK 0x3f
81 #define FIFO_STATUS_FILL_LEVEL_MASK 0x7f00
82 #define FILL_LEVEL_SHIFT 0x8
84 /* CANFD frame size ID, DLC and 16 DATA word. */
85 #define CANFD_FRAME_SIZE 18
86 /* CAN frame size ID, DLC and 2 DATA word. */
87 #define CAN_FRAME_SIZE 4
89 /* Set the filters for CANFD controller. */
90 static void enable_filters(QTestState *qts)
92 const uint32_t arr_afmr[32] = { 0xb423deaa, 0xa2a40bdc, 0x1b64f486,
93 0x95c0d4ee, 0xe0c44528, 0x4b407904,
94 0xd2673f46, 0x9fc638d6, 0x8844f3d8,
95 0xa607d1e8, 0x67871bf4, 0xc2557dc,
96 0x9ea5b53e, 0x3643c0cc, 0x5a05ea8e,
97 0x83a46d84, 0x4a25c2b8, 0x93a66008,
98 0x2e467470, 0xedc66118, 0x9086f9f2,
99 0xfa23dd36, 0xb6654b90, 0xb221b8ca,
100 0x3467d1e2, 0xa3a55542, 0x5b26a012,
101 0x2281ea7e, 0xcea0ece8, 0xdc61e588,
102 0x2e5676a, 0x16821320 };
104 const uint32_t arr_afir[32] = { 0xa833dfa1, 0x255a477e, 0x3a4bb1c5,
105 0x8f560a6c, 0x27f38903, 0x2fecec4d,
106 0xa014c66d, 0xec289b8, 0x7e52dead,
107 0x82e94f3c, 0xcf3e3c5c, 0x66059871,
108 0x3f213df4, 0x25ac3959, 0xa12e9bef,
109 0xa3ad3af, 0xbafd7fe, 0xb3cb40fd,
110 0x5d9caa81, 0x2ed61902, 0x7cd64a0,
111 0x4b1fa538, 0x9b5ced8c, 0x150de059,
112 0xd2794227, 0x635e820a, 0xbb6b02cf,
113 0xbb58176, 0x570025bb, 0xa78d9658,
114 0x49d735df, 0xe5399d2f };
116 /* Passing the respective array values to all the AFMR and AFIR pairs. */
117 for (int i = 0; i < 32; i++) {
118 /* For CANFD0. */
119 qtest_writel(qts, CANFD0_BASE_ADDR + R_AFMR_REGISTER0 + 8 * i,
120 arr_afmr[i]);
121 qtest_writel(qts, CANFD0_BASE_ADDR + R_AFIR_REGISTER0 + 8 * i,
122 arr_afir[i]);
124 /* For CANFD1. */
125 qtest_writel(qts, CANFD1_BASE_ADDR + R_AFMR_REGISTER0 + 8 * i,
126 arr_afmr[i]);
127 qtest_writel(qts, CANFD1_BASE_ADDR + R_AFIR_REGISTER0 + 8 * i,
128 arr_afir[i]);
131 /* Enable all the pairs from AFR register. */
132 qtest_writel(qts, CANFD0_BASE_ADDR + R_FILTER_CONTROL_REGISTER,
133 ENABLE_ALL_FILTERS);
134 qtest_writel(qts, CANFD1_BASE_ADDR + R_FILTER_CONTROL_REGISTER,
135 ENABLE_ALL_FILTERS);
138 static void configure_canfd(QTestState *qts, uint8_t mode)
140 uint32_t status = 0;
142 /* Put CANFD0 and CANFD1 in config mode. */
143 qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, SRR_CONFIG_MODE);
144 qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, SRR_CONFIG_MODE);
146 /* Write mode of operation in Mode select register. */
147 qtest_writel(qts, CANFD0_BASE_ADDR + R_MSR_OFFSET, mode);
148 qtest_writel(qts, CANFD1_BASE_ADDR + R_MSR_OFFSET, mode);
150 enable_filters(qts);
152 /* Check here if CANFD0 and CANFD1 are in config mode. */
153 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
154 status = status & STATUS_REG_MASK;
155 g_assert_cmpint(status, ==, STATUS_CONFIG_MODE);
157 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
158 status = status & STATUS_REG_MASK;
159 g_assert_cmpint(status, ==, STATUS_CONFIG_MODE);
161 qtest_writel(qts, CANFD1_BASE_ADDR + R_IER_OFFSET, ENABLE_ALL_INTERRUPTS);
162 qtest_writel(qts, CANFD1_BASE_ADDR + R_IER_OFFSET, ENABLE_ALL_INTERRUPTS);
164 qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD);
165 qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD);
168 static void generate_random_data(uint32_t *buf_tx, bool is_canfd_frame)
170 /* Generate random TX data for CANFD frame. */
171 if (is_canfd_frame) {
172 for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
173 buf_tx[2 + i] = g_random_int();
175 } else {
176 /* Generate random TX data for CAN frame. */
177 for (int i = 0; i < CAN_FRAME_SIZE - 2; i++) {
178 buf_tx[2 + i] = g_random_int();
183 static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx,
184 uint32_t frame_size)
186 uint32_t int_status;
187 uint32_t fifo_status_reg_value;
188 /* At which RX FIFO the received data is stored. */
189 uint8_t store_ind = 0;
191 /* Read the interrupt on CANFD rx. */
192 int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
194 g_assert_cmpint(int_status, ==, ISR_RXOK);
196 /* Find the fill level and read index. */
197 fifo_status_reg_value = qtest_readl(qts, can_base_addr +
198 RX_FIFO_STATUS_REGISTER);
200 store_ind = (fifo_status_reg_value & FIFO_STATUS_READ_INDEX_MASK) +
201 ((fifo_status_reg_value & FIFO_STATUS_FILL_LEVEL_MASK) >>
202 FILL_LEVEL_SHIFT);
204 g_assert_cmpint(store_ind, ==, FIRST_RX_STORE_INDEX);
206 /* Read the RX register data for CANFD. */
207 buf_rx[0] = qtest_readl(qts, can_base_addr + R_RX0_ID_OFFSET);
208 buf_rx[1] = qtest_readl(qts, can_base_addr + R_RX0_DLC_OFFSET);
210 for (int i = 0; i < frame_size - 2; i++) {
211 buf_rx[i + 2] = qtest_readl(qts,
212 can_base_addr + R_RX0_DATA1_OFFSET + 4 * i);
215 /* Clear the RX interrupt. */
216 qtest_writel(qts, CANFD1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
219 static void write_data(QTestState *qts, uint64_t can_base_addr,
220 const uint32_t *buf_tx, bool is_canfd_frame)
222 /* Write the TX register data for CANFD. */
223 qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
224 qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
226 if (is_canfd_frame) {
227 for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) {
228 qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET + 4 * i,
229 buf_tx[2 + i]);
231 } else {
232 qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
233 qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
237 static void send_data(QTestState *qts, uint64_t can_base_addr)
239 uint32_t int_status;
241 qtest_writel(qts, can_base_addr + R_TX_READY_REQ_REGISTER,
242 TX_READY_REG_VAL);
244 /* Read the interrupt on CANFD for tx. */
245 int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
247 g_assert_cmpint(int_status, ==, ISR_TXOK);
249 /* Clear the interrupt for tx. */
250 qtest_writel(qts, CANFD0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
253 static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
254 bool is_canfd_frame)
256 uint16_t size = 0;
257 uint8_t len = CAN_FRAME_SIZE;
259 if (is_canfd_frame) {
260 len = CANFD_FRAME_SIZE;
263 while (size < len) {
264 if (R_RX0_ID_OFFSET + 4 * size == R_RX0_DLC_OFFSET) {
265 g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), ==,
266 (buf_tx[size] & DLC_FD_BIT_MASK));
267 } else {
268 g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
271 size++;
275 * Xilinx CANFD supports both CAN and CANFD frames. This test will be
276 * transferring CAN frame i.e. 8 bytes of data from CANFD0 and CANFD1 through
277 * canbus. CANFD0 initiate the data transfer to can-bus, CANFD1 receives the
278 * data. Test compares the can frame data sent from CANFD0 and received on
279 * CANFD1.
281 static void test_can_data_transfer(void)
283 uint32_t buf_tx[CAN_FRAME_SIZE] = { 0x5a5bb9a4, 0x80000000,
284 0x12345678, 0x87654321 };
285 uint32_t buf_rx[CAN_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };
286 uint32_t status = 0;
288 generate_random_data(buf_tx, false);
290 QTestState *qts = qtest_init("-machine xlnx-versal-virt"
291 " -object can-bus,id=canbus"
292 " -machine canbus0=canbus"
293 " -machine canbus1=canbus"
296 configure_canfd(qts, MSR_NORMAL_MODE);
298 /* Check if CANFD0 and CANFD1 are in Normal mode. */
299 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
300 status = status & STATUS_REG_MASK;
301 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
303 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
304 status = status & STATUS_REG_MASK;
305 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
307 write_data(qts, CANFD0_BASE_ADDR, buf_tx, false);
309 send_data(qts, CANFD0_BASE_ADDR);
310 read_data(qts, CANFD1_BASE_ADDR, buf_rx, CAN_FRAME_SIZE);
311 match_rx_tx_data(buf_tx, buf_rx, false);
313 qtest_quit(qts);
317 * This test will be transferring CANFD frame i.e. 64 bytes of data from CANFD0
318 * and CANFD1 through canbus. CANFD0 initiate the data transfer to can-bus,
319 * CANFD1 receives the data. Test compares the CANFD frame data sent from CANFD0
320 * with received on CANFD1.
322 static void test_canfd_data_transfer(void)
324 uint32_t buf_tx[CANFD_FRAME_SIZE] = { 0x5a5bb9a4, 0xf8000000 };
325 uint32_t buf_rx[CANFD_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };
326 uint32_t status = 0;
328 generate_random_data(buf_tx, true);
330 QTestState *qts = qtest_init("-machine xlnx-versal-virt"
331 " -object can-bus,id=canbus"
332 " -machine canbus0=canbus"
333 " -machine canbus1=canbus"
336 configure_canfd(qts, MSR_NORMAL_MODE);
338 /* Check if CANFD0 and CANFD1 are in Normal mode. */
339 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
340 status = status & STATUS_REG_MASK;
341 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
343 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
344 status = status & STATUS_REG_MASK;
345 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
347 write_data(qts, CANFD0_BASE_ADDR, buf_tx, true);
349 send_data(qts, CANFD0_BASE_ADDR);
350 read_data(qts, CANFD1_BASE_ADDR, buf_rx, CANFD_FRAME_SIZE);
351 match_rx_tx_data(buf_tx, buf_rx, true);
353 qtest_quit(qts);
357 * This test is performing loopback mode on CANFD0 and CANFD1. Data sent from
358 * TX of each CANFD0 and CANFD1 are compared with RX register data for
359 * respective CANFD Controller.
361 static void test_can_loopback(void)
363 uint32_t buf_tx[CANFD_FRAME_SIZE] = { 0x5a5bb9a4, 0xf8000000 };
364 uint32_t buf_rx[CANFD_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };
365 uint32_t status = 0;
367 generate_random_data(buf_tx, true);
369 QTestState *qts = qtest_init("-machine xlnx-versal-virt"
370 " -object can-bus,id=canbus"
371 " -machine canbus0=canbus"
372 " -machine canbus1=canbus"
375 configure_canfd(qts, MSR_LOOPBACK_MODE);
377 /* Check if CANFD0 and CANFD1 are set in correct loopback mode. */
378 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
379 status = status & STATUS_REG_MASK;
380 g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
382 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
383 status = status & STATUS_REG_MASK;
384 g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
386 write_data(qts, CANFD0_BASE_ADDR, buf_tx, true);
388 send_data(qts, CANFD0_BASE_ADDR);
389 read_data(qts, CANFD0_BASE_ADDR, buf_rx, CANFD_FRAME_SIZE);
390 match_rx_tx_data(buf_tx, buf_rx, true);
392 generate_random_data(buf_tx, true);
394 write_data(qts, CANFD1_BASE_ADDR, buf_tx, true);
396 send_data(qts, CANFD1_BASE_ADDR);
397 read_data(qts, CANFD1_BASE_ADDR, buf_rx, CANFD_FRAME_SIZE);
398 match_rx_tx_data(buf_tx, buf_rx, true);
400 qtest_quit(qts);
403 int main(int argc, char **argv)
405 g_test_init(&argc, &argv, NULL);
407 qtest_add_func("/net/canfd/can_data_transfer", test_can_data_transfer);
408 qtest_add_func("/net/canfd/canfd_data_transfer", test_canfd_data_transfer);
409 qtest_add_func("/net/canfd/can_loopback", test_can_loopback);
411 return g_test_run();