1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * QTests for the Xilinx Versal CANFD controller. 5 * 6 * Copyright (c) 2022 AMD Inc. 7 * 8 * Written-by: Vikram Garhwal<vikram.garhwal@amd.com> 9 * 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: 16 * 17 * The above copyright notice and this permission notice shall be included in 18 * all copies or substantial portions of the Software. 19 * 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. 27 */ 28 29 #include "qemu/osdep.h" 30 #include "libqtest.h" 31 32 /* Base address. */ 33 #define CANFD0_BASE_ADDR 0xff060000 34 #define CANFD1_BASE_ADDR 0xff070000 35 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 56 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) 62 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) 69 70 #define ENABLE_ALL_FILTERS 0xffffffff 71 #define ENABLE_ALL_INTERRUPTS 0xffffffff 72 73 /* We are sending one canfd message. */ 74 #define TX_READY_REG_VAL 0x1 75 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 83 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 88 89 /* Set the filters for CANFD controller. */ 90 static void enable_filters(QTestState *qts) 91 { 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 }; 103 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 }; 115 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]); 123 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]); 129 } 130 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); 136 } 137 138 static void configure_canfd(QTestState *qts, uint8_t mode) 139 { 140 uint32_t status = 0; 141 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); 145 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); 149 150 enable_filters(qts); 151 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); 156 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); 160 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); 163 164 qtest_writel(qts, CANFD0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD); 165 qtest_writel(qts, CANFD1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CANFD); 166 } 167 168 static void generate_random_data(uint32_t *buf_tx, bool is_canfd_frame) 169 { 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] = rand(); 174 } 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] = rand(); 179 } 180 } 181 } 182 183 static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx) 184 { 185 uint32_t int_status; 186 uint32_t fifo_status_reg_value; 187 /* At which RX FIFO the received data is stored. */ 188 uint8_t store_ind = 0; 189 bool is_canfd_frame = false; 190 191 /* Read the interrupt on CANFD rx. */ 192 int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK; 193 194 g_assert_cmpint(int_status, ==, ISR_RXOK); 195 196 /* Find the fill level and read index. */ 197 fifo_status_reg_value = qtest_readl(qts, can_base_addr + 198 RX_FIFO_STATUS_REGISTER); 199 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); 203 204 g_assert_cmpint(store_ind, ==, FIRST_RX_STORE_INDEX); 205 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); 209 210 is_canfd_frame = (buf_rx[1] >> DLC_FD_BIT_SHIFT) & 1; 211 212 if (is_canfd_frame) { 213 for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) { 214 buf_rx[i + 2] = qtest_readl(qts, 215 can_base_addr + R_RX0_DATA1_OFFSET + 4 * i); 216 } 217 } else { 218 buf_rx[2] = qtest_readl(qts, can_base_addr + R_RX0_DATA1_OFFSET); 219 buf_rx[3] = qtest_readl(qts, can_base_addr + R_RX0_DATA2_OFFSET); 220 } 221 222 /* Clear the RX interrupt. */ 223 qtest_writel(qts, CANFD1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK); 224 } 225 226 static void write_data(QTestState *qts, uint64_t can_base_addr, 227 const uint32_t *buf_tx, bool is_canfd_frame) 228 { 229 /* Write the TX register data for CANFD. */ 230 qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]); 231 qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]); 232 233 if (is_canfd_frame) { 234 for (int i = 0; i < CANFD_FRAME_SIZE - 2; i++) { 235 qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET + 4 * i, 236 buf_tx[2 + i]); 237 } 238 } else { 239 qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]); 240 qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]); 241 } 242 } 243 244 static void send_data(QTestState *qts, uint64_t can_base_addr) 245 { 246 uint32_t int_status; 247 248 qtest_writel(qts, can_base_addr + R_TX_READY_REQ_REGISTER, 249 TX_READY_REG_VAL); 250 251 /* Read the interrupt on CANFD for tx. */ 252 int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK; 253 254 g_assert_cmpint(int_status, ==, ISR_TXOK); 255 256 /* Clear the interrupt for tx. */ 257 qtest_writel(qts, CANFD0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK); 258 } 259 260 static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx, 261 bool is_canfd_frame) 262 { 263 uint16_t size = 0; 264 uint8_t len = CAN_FRAME_SIZE; 265 266 if (is_canfd_frame) { 267 len = CANFD_FRAME_SIZE; 268 } 269 270 while (size < len) { 271 if (R_RX0_ID_OFFSET + 4 * size == R_RX0_DLC_OFFSET) { 272 g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), ==, 273 (buf_tx[size] & DLC_FD_BIT_MASK)); 274 } else { 275 if (!is_canfd_frame && size == 4) { 276 break; 277 } 278 279 g_assert_cmpint(buf_rx[size], ==, buf_tx[size]); 280 } 281 282 size++; 283 } 284 } 285 /* 286 * Xilinx CANFD supports both CAN and CANFD frames. This test will be 287 * transferring CAN frame i.e. 8 bytes of data from CANFD0 and CANFD1 through 288 * canbus. CANFD0 initiate the data transfer to can-bus, CANFD1 receives the 289 * data. Test compares the can frame data sent from CANFD0 and received on 290 * CANFD1. 291 */ 292 static void test_can_data_transfer(void) 293 { 294 uint32_t buf_tx[CAN_FRAME_SIZE] = { 0x5a5bb9a4, 0x80000000, 295 0x12345678, 0x87654321 }; 296 uint32_t buf_rx[CAN_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 }; 297 uint32_t status = 0; 298 299 generate_random_data(buf_tx, false); 300 301 QTestState *qts = qtest_init("-machine xlnx-versal-virt" 302 " -object can-bus,id=canbus" 303 " -machine canbus0=canbus" 304 " -machine canbus1=canbus" 305 ); 306 307 configure_canfd(qts, MSR_NORMAL_MODE); 308 309 /* Check if CANFD0 and CANFD1 are in Normal mode. */ 310 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); 311 status = status & STATUS_REG_MASK; 312 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 313 314 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); 315 status = status & STATUS_REG_MASK; 316 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 317 318 write_data(qts, CANFD0_BASE_ADDR, buf_tx, false); 319 320 send_data(qts, CANFD0_BASE_ADDR); 321 read_data(qts, CANFD1_BASE_ADDR, buf_rx); 322 match_rx_tx_data(buf_tx, buf_rx, false); 323 324 qtest_quit(qts); 325 } 326 327 /* 328 * This test will be transferring CANFD frame i.e. 64 bytes of data from CANFD0 329 * and CANFD1 through canbus. CANFD0 initiate the data transfer to can-bus, 330 * CANFD1 receives the data. Test compares the CANFD frame data sent from CANFD0 331 * with received on CANFD1. 332 */ 333 static void test_canfd_data_transfer(void) 334 { 335 uint32_t buf_tx[CANFD_FRAME_SIZE] = { 0x5a5bb9a4, 0xf8000000 }; 336 uint32_t buf_rx[CANFD_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 }; 337 uint32_t status = 0; 338 339 generate_random_data(buf_tx, true); 340 341 QTestState *qts = qtest_init("-machine xlnx-versal-virt" 342 " -object can-bus,id=canbus" 343 " -machine canbus0=canbus" 344 " -machine canbus1=canbus" 345 ); 346 347 configure_canfd(qts, MSR_NORMAL_MODE); 348 349 /* Check if CANFD0 and CANFD1 are in Normal mode. */ 350 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); 351 status = status & STATUS_REG_MASK; 352 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 353 354 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); 355 status = status & STATUS_REG_MASK; 356 g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 357 358 write_data(qts, CANFD0_BASE_ADDR, buf_tx, true); 359 360 send_data(qts, CANFD0_BASE_ADDR); 361 read_data(qts, CANFD1_BASE_ADDR, buf_rx); 362 match_rx_tx_data(buf_tx, buf_rx, true); 363 364 qtest_quit(qts); 365 } 366 367 /* 368 * This test is performing loopback mode on CANFD0 and CANFD1. Data sent from 369 * TX of each CANFD0 and CANFD1 are compared with RX register data for 370 * respective CANFD Controller. 371 */ 372 static void test_can_loopback(void) 373 { 374 uint32_t buf_tx[CANFD_FRAME_SIZE] = { 0x5a5bb9a4, 0xf8000000 }; 375 uint32_t buf_rx[CANFD_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 }; 376 uint32_t status = 0; 377 378 generate_random_data(buf_tx, true); 379 380 QTestState *qts = qtest_init("-machine xlnx-versal-virt" 381 " -object can-bus,id=canbus" 382 " -machine canbus0=canbus" 383 " -machine canbus1=canbus" 384 ); 385 386 configure_canfd(qts, MSR_LOOPBACK_MODE); 387 388 /* Check if CANFD0 and CANFD1 are set in correct loopback mode. */ 389 status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET); 390 status = status & STATUS_REG_MASK; 391 g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE); 392 393 status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET); 394 status = status & STATUS_REG_MASK; 395 g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE); 396 397 write_data(qts, CANFD0_BASE_ADDR, buf_tx, true); 398 399 send_data(qts, CANFD0_BASE_ADDR); 400 read_data(qts, CANFD0_BASE_ADDR, buf_rx); 401 match_rx_tx_data(buf_tx, buf_rx, true); 402 403 generate_random_data(buf_tx, true); 404 405 write_data(qts, CANFD1_BASE_ADDR, buf_tx, true); 406 407 send_data(qts, CANFD1_BASE_ADDR); 408 read_data(qts, CANFD1_BASE_ADDR, buf_rx); 409 match_rx_tx_data(buf_tx, buf_rx, true); 410 411 qtest_quit(qts); 412 } 413 414 int main(int argc, char **argv) 415 { 416 g_test_init(&argc, &argv, NULL); 417 418 qtest_add_func("/net/canfd/can_data_transfer", test_can_data_transfer); 419 qtest_add_func("/net/canfd/canfd_data_transfer", test_canfd_data_transfer); 420 qtest_add_func("/net/canfd/can_loopback", test_can_loopback); 421 422 return g_test_run(); 423 } 424