1*ab5e842cSVikram Garhwal /* 2*ab5e842cSVikram Garhwal * QTests for the Xilinx ZynqMP CAN controller. 3*ab5e842cSVikram Garhwal * 4*ab5e842cSVikram Garhwal * Copyright (c) 2020 Xilinx Inc. 5*ab5e842cSVikram Garhwal * 6*ab5e842cSVikram Garhwal * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com> 7*ab5e842cSVikram Garhwal * 8*ab5e842cSVikram Garhwal * Permission is hereby granted, free of charge, to any person obtaining a copy 9*ab5e842cSVikram Garhwal * of this software and associated documentation files (the "Software"), to deal 10*ab5e842cSVikram Garhwal * in the Software without restriction, including without limitation the rights 11*ab5e842cSVikram Garhwal * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12*ab5e842cSVikram Garhwal * copies of the Software, and to permit persons to whom the Software is 13*ab5e842cSVikram Garhwal * furnished to do so, subject to the following conditions: 14*ab5e842cSVikram Garhwal * 15*ab5e842cSVikram Garhwal * The above copyright notice and this permission notice shall be included in 16*ab5e842cSVikram Garhwal * all copies or substantial portions of the Software. 17*ab5e842cSVikram Garhwal * 18*ab5e842cSVikram Garhwal * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19*ab5e842cSVikram Garhwal * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20*ab5e842cSVikram Garhwal * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21*ab5e842cSVikram Garhwal * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22*ab5e842cSVikram Garhwal * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23*ab5e842cSVikram Garhwal * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24*ab5e842cSVikram Garhwal * THE SOFTWARE. 25*ab5e842cSVikram Garhwal */ 26*ab5e842cSVikram Garhwal 27*ab5e842cSVikram Garhwal #include "qemu/osdep.h" 28*ab5e842cSVikram Garhwal #include "libqos/libqtest.h" 29*ab5e842cSVikram Garhwal 30*ab5e842cSVikram Garhwal /* Base address. */ 31*ab5e842cSVikram Garhwal #define CAN0_BASE_ADDR 0xFF060000 32*ab5e842cSVikram Garhwal #define CAN1_BASE_ADDR 0xFF070000 33*ab5e842cSVikram Garhwal 34*ab5e842cSVikram Garhwal /* Register addresses. */ 35*ab5e842cSVikram Garhwal #define R_SRR_OFFSET 0x00 36*ab5e842cSVikram Garhwal #define R_MSR_OFFSET 0x04 37*ab5e842cSVikram Garhwal #define R_SR_OFFSET 0x18 38*ab5e842cSVikram Garhwal #define R_ISR_OFFSET 0x1C 39*ab5e842cSVikram Garhwal #define R_ICR_OFFSET 0x24 40*ab5e842cSVikram Garhwal #define R_TXID_OFFSET 0x30 41*ab5e842cSVikram Garhwal #define R_TXDLC_OFFSET 0x34 42*ab5e842cSVikram Garhwal #define R_TXDATA1_OFFSET 0x38 43*ab5e842cSVikram Garhwal #define R_TXDATA2_OFFSET 0x3C 44*ab5e842cSVikram Garhwal #define R_RXID_OFFSET 0x50 45*ab5e842cSVikram Garhwal #define R_RXDLC_OFFSET 0x54 46*ab5e842cSVikram Garhwal #define R_RXDATA1_OFFSET 0x58 47*ab5e842cSVikram Garhwal #define R_RXDATA2_OFFSET 0x5C 48*ab5e842cSVikram Garhwal #define R_AFR 0x60 49*ab5e842cSVikram Garhwal #define R_AFMR1 0x64 50*ab5e842cSVikram Garhwal #define R_AFIR1 0x68 51*ab5e842cSVikram Garhwal #define R_AFMR2 0x6C 52*ab5e842cSVikram Garhwal #define R_AFIR2 0x70 53*ab5e842cSVikram Garhwal #define R_AFMR3 0x74 54*ab5e842cSVikram Garhwal #define R_AFIR3 0x78 55*ab5e842cSVikram Garhwal #define R_AFMR4 0x7C 56*ab5e842cSVikram Garhwal #define R_AFIR4 0x80 57*ab5e842cSVikram Garhwal 58*ab5e842cSVikram Garhwal /* CAN modes. */ 59*ab5e842cSVikram Garhwal #define CONFIG_MODE 0x00 60*ab5e842cSVikram Garhwal #define NORMAL_MODE 0x00 61*ab5e842cSVikram Garhwal #define LOOPBACK_MODE 0x02 62*ab5e842cSVikram Garhwal #define SNOOP_MODE 0x04 63*ab5e842cSVikram Garhwal #define SLEEP_MODE 0x01 64*ab5e842cSVikram Garhwal #define ENABLE_CAN (1 << 1) 65*ab5e842cSVikram Garhwal #define STATUS_NORMAL_MODE (1 << 3) 66*ab5e842cSVikram Garhwal #define STATUS_LOOPBACK_MODE (1 << 1) 67*ab5e842cSVikram Garhwal #define STATUS_SNOOP_MODE (1 << 12) 68*ab5e842cSVikram Garhwal #define STATUS_SLEEP_MODE (1 << 2) 69*ab5e842cSVikram Garhwal #define ISR_TXOK (1 << 1) 70*ab5e842cSVikram Garhwal #define ISR_RXOK (1 << 4) 71*ab5e842cSVikram Garhwal 72*ab5e842cSVikram Garhwal static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx, 73*ab5e842cSVikram Garhwal uint8_t can_timestamp) 74*ab5e842cSVikram Garhwal { 75*ab5e842cSVikram Garhwal uint16_t size = 0; 76*ab5e842cSVikram Garhwal uint8_t len = 4; 77*ab5e842cSVikram Garhwal 78*ab5e842cSVikram Garhwal while (size < len) { 79*ab5e842cSVikram Garhwal if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) { 80*ab5e842cSVikram Garhwal g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp); 81*ab5e842cSVikram Garhwal } else { 82*ab5e842cSVikram Garhwal g_assert_cmpint(buf_rx[size], ==, buf_tx[size]); 83*ab5e842cSVikram Garhwal } 84*ab5e842cSVikram Garhwal 85*ab5e842cSVikram Garhwal size++; 86*ab5e842cSVikram Garhwal } 87*ab5e842cSVikram Garhwal } 88*ab5e842cSVikram Garhwal 89*ab5e842cSVikram Garhwal static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx) 90*ab5e842cSVikram Garhwal { 91*ab5e842cSVikram Garhwal uint32_t int_status; 92*ab5e842cSVikram Garhwal 93*ab5e842cSVikram Garhwal /* Read the interrupt on CAN rx. */ 94*ab5e842cSVikram Garhwal int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK; 95*ab5e842cSVikram Garhwal 96*ab5e842cSVikram Garhwal g_assert_cmpint(int_status, ==, ISR_RXOK); 97*ab5e842cSVikram Garhwal 98*ab5e842cSVikram Garhwal /* Read the RX register data for CAN. */ 99*ab5e842cSVikram Garhwal buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET); 100*ab5e842cSVikram Garhwal buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET); 101*ab5e842cSVikram Garhwal buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET); 102*ab5e842cSVikram Garhwal buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET); 103*ab5e842cSVikram Garhwal 104*ab5e842cSVikram Garhwal /* Clear the RX interrupt. */ 105*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK); 106*ab5e842cSVikram Garhwal } 107*ab5e842cSVikram Garhwal 108*ab5e842cSVikram Garhwal static void send_data(QTestState *qts, uint64_t can_base_addr, 109*ab5e842cSVikram Garhwal const uint32_t *buf_tx) 110*ab5e842cSVikram Garhwal { 111*ab5e842cSVikram Garhwal uint32_t int_status; 112*ab5e842cSVikram Garhwal 113*ab5e842cSVikram Garhwal /* Write the TX register data for CAN. */ 114*ab5e842cSVikram Garhwal qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]); 115*ab5e842cSVikram Garhwal qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]); 116*ab5e842cSVikram Garhwal qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]); 117*ab5e842cSVikram Garhwal qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]); 118*ab5e842cSVikram Garhwal 119*ab5e842cSVikram Garhwal /* Read the interrupt on CAN for tx. */ 120*ab5e842cSVikram Garhwal int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK; 121*ab5e842cSVikram Garhwal 122*ab5e842cSVikram Garhwal g_assert_cmpint(int_status, ==, ISR_TXOK); 123*ab5e842cSVikram Garhwal 124*ab5e842cSVikram Garhwal /* Clear the interrupt for tx. */ 125*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK); 126*ab5e842cSVikram Garhwal } 127*ab5e842cSVikram Garhwal 128*ab5e842cSVikram Garhwal /* 129*ab5e842cSVikram Garhwal * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0 130*ab5e842cSVikram Garhwal * initiate the data transfer to can-bus, CAN1 receives the data. Test compares 131*ab5e842cSVikram Garhwal * the data sent from CAN0 with received on CAN1. 132*ab5e842cSVikram Garhwal */ 133*ab5e842cSVikram Garhwal static void test_can_bus(void) 134*ab5e842cSVikram Garhwal { 135*ab5e842cSVikram Garhwal const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 }; 136*ab5e842cSVikram Garhwal uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; 137*ab5e842cSVikram Garhwal uint32_t status = 0; 138*ab5e842cSVikram Garhwal uint8_t can_timestamp = 1; 139*ab5e842cSVikram Garhwal 140*ab5e842cSVikram Garhwal QTestState *qts = qtest_init("-machine xlnx-zcu102" 141*ab5e842cSVikram Garhwal " -object can-bus,id=canbus0" 142*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus0=canbus0" 143*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus1=canbus0" 144*ab5e842cSVikram Garhwal ); 145*ab5e842cSVikram Garhwal 146*ab5e842cSVikram Garhwal /* Configure the CAN0 and CAN1. */ 147*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 148*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); 149*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 150*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); 151*ab5e842cSVikram Garhwal 152*ab5e842cSVikram Garhwal /* Check here if CAN0 and CAN1 are in normal mode. */ 153*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); 154*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 155*ab5e842cSVikram Garhwal 156*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); 157*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 158*ab5e842cSVikram Garhwal 159*ab5e842cSVikram Garhwal send_data(qts, CAN0_BASE_ADDR, buf_tx); 160*ab5e842cSVikram Garhwal 161*ab5e842cSVikram Garhwal read_data(qts, CAN1_BASE_ADDR, buf_rx); 162*ab5e842cSVikram Garhwal match_rx_tx_data(buf_tx, buf_rx, can_timestamp); 163*ab5e842cSVikram Garhwal 164*ab5e842cSVikram Garhwal qtest_quit(qts); 165*ab5e842cSVikram Garhwal } 166*ab5e842cSVikram Garhwal 167*ab5e842cSVikram Garhwal /* 168*ab5e842cSVikram Garhwal * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of 169*ab5e842cSVikram Garhwal * each CAN0 and CAN1 are compared with RX register data for respective CAN. 170*ab5e842cSVikram Garhwal */ 171*ab5e842cSVikram Garhwal static void test_can_loopback(void) 172*ab5e842cSVikram Garhwal { 173*ab5e842cSVikram Garhwal uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 }; 174*ab5e842cSVikram Garhwal uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; 175*ab5e842cSVikram Garhwal uint32_t status = 0; 176*ab5e842cSVikram Garhwal 177*ab5e842cSVikram Garhwal QTestState *qts = qtest_init("-machine xlnx-zcu102" 178*ab5e842cSVikram Garhwal " -object can-bus,id=canbus0" 179*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus0=canbus0" 180*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus1=canbus0" 181*ab5e842cSVikram Garhwal ); 182*ab5e842cSVikram Garhwal 183*ab5e842cSVikram Garhwal /* Configure the CAN0 in loopback mode. */ 184*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); 185*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE); 186*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 187*ab5e842cSVikram Garhwal 188*ab5e842cSVikram Garhwal /* Check here if CAN0 is set in loopback mode. */ 189*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); 190*ab5e842cSVikram Garhwal 191*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE); 192*ab5e842cSVikram Garhwal 193*ab5e842cSVikram Garhwal send_data(qts, CAN0_BASE_ADDR, buf_tx); 194*ab5e842cSVikram Garhwal read_data(qts, CAN0_BASE_ADDR, buf_rx); 195*ab5e842cSVikram Garhwal match_rx_tx_data(buf_tx, buf_rx, 0); 196*ab5e842cSVikram Garhwal 197*ab5e842cSVikram Garhwal /* Configure the CAN1 in loopback mode. */ 198*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); 199*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE); 200*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 201*ab5e842cSVikram Garhwal 202*ab5e842cSVikram Garhwal /* Check here if CAN1 is set in loopback mode. */ 203*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); 204*ab5e842cSVikram Garhwal 205*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE); 206*ab5e842cSVikram Garhwal 207*ab5e842cSVikram Garhwal send_data(qts, CAN1_BASE_ADDR, buf_tx); 208*ab5e842cSVikram Garhwal read_data(qts, CAN1_BASE_ADDR, buf_rx); 209*ab5e842cSVikram Garhwal match_rx_tx_data(buf_tx, buf_rx, 0); 210*ab5e842cSVikram Garhwal 211*ab5e842cSVikram Garhwal qtest_quit(qts); 212*ab5e842cSVikram Garhwal } 213*ab5e842cSVikram Garhwal 214*ab5e842cSVikram Garhwal /* 215*ab5e842cSVikram Garhwal * Enable filters for CAN1. This will filter incoming messages with ID. In this 216*ab5e842cSVikram Garhwal * test message will pass through filter 2. 217*ab5e842cSVikram Garhwal */ 218*ab5e842cSVikram Garhwal static void test_can_filter(void) 219*ab5e842cSVikram Garhwal { 220*ab5e842cSVikram Garhwal uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 }; 221*ab5e842cSVikram Garhwal uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; 222*ab5e842cSVikram Garhwal uint32_t status = 0; 223*ab5e842cSVikram Garhwal uint8_t can_timestamp = 1; 224*ab5e842cSVikram Garhwal 225*ab5e842cSVikram Garhwal QTestState *qts = qtest_init("-machine xlnx-zcu102" 226*ab5e842cSVikram Garhwal " -object can-bus,id=canbus0" 227*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus0=canbus0" 228*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus1=canbus0" 229*ab5e842cSVikram Garhwal ); 230*ab5e842cSVikram Garhwal 231*ab5e842cSVikram Garhwal /* Configure the CAN0 and CAN1. */ 232*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 233*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); 234*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 235*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); 236*ab5e842cSVikram Garhwal 237*ab5e842cSVikram Garhwal /* Check here if CAN0 and CAN1 are in normal mode. */ 238*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); 239*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 240*ab5e842cSVikram Garhwal 241*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); 242*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 243*ab5e842cSVikram Garhwal 244*ab5e842cSVikram Garhwal /* Set filter for CAN1 for incoming messages. */ 245*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0); 246*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7); 247*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F); 248*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431); 249*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14); 250*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234); 251*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431); 252*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF); 253*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234); 254*ab5e842cSVikram Garhwal 255*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF); 256*ab5e842cSVikram Garhwal 257*ab5e842cSVikram Garhwal send_data(qts, CAN0_BASE_ADDR, buf_tx); 258*ab5e842cSVikram Garhwal 259*ab5e842cSVikram Garhwal read_data(qts, CAN1_BASE_ADDR, buf_rx); 260*ab5e842cSVikram Garhwal match_rx_tx_data(buf_tx, buf_rx, can_timestamp); 261*ab5e842cSVikram Garhwal 262*ab5e842cSVikram Garhwal qtest_quit(qts); 263*ab5e842cSVikram Garhwal } 264*ab5e842cSVikram Garhwal 265*ab5e842cSVikram Garhwal /* Testing sleep mode on CAN0 while CAN1 is in normal mode. */ 266*ab5e842cSVikram Garhwal static void test_can_sleepmode(void) 267*ab5e842cSVikram Garhwal { 268*ab5e842cSVikram Garhwal uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 }; 269*ab5e842cSVikram Garhwal uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; 270*ab5e842cSVikram Garhwal uint32_t status = 0; 271*ab5e842cSVikram Garhwal uint8_t can_timestamp = 1; 272*ab5e842cSVikram Garhwal 273*ab5e842cSVikram Garhwal QTestState *qts = qtest_init("-machine xlnx-zcu102" 274*ab5e842cSVikram Garhwal " -object can-bus,id=canbus0" 275*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus0=canbus0" 276*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus1=canbus0" 277*ab5e842cSVikram Garhwal ); 278*ab5e842cSVikram Garhwal 279*ab5e842cSVikram Garhwal /* Configure the CAN0. */ 280*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); 281*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE); 282*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 283*ab5e842cSVikram Garhwal 284*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 285*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); 286*ab5e842cSVikram Garhwal 287*ab5e842cSVikram Garhwal /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */ 288*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); 289*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_SLEEP_MODE); 290*ab5e842cSVikram Garhwal 291*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); 292*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 293*ab5e842cSVikram Garhwal 294*ab5e842cSVikram Garhwal send_data(qts, CAN1_BASE_ADDR, buf_tx); 295*ab5e842cSVikram Garhwal 296*ab5e842cSVikram Garhwal /* 297*ab5e842cSVikram Garhwal * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode. 298*ab5e842cSVikram Garhwal * Check the CAN0 status now. It should exit the sleep mode and receive the 299*ab5e842cSVikram Garhwal * incoming data. 300*ab5e842cSVikram Garhwal */ 301*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); 302*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 303*ab5e842cSVikram Garhwal 304*ab5e842cSVikram Garhwal read_data(qts, CAN0_BASE_ADDR, buf_rx); 305*ab5e842cSVikram Garhwal 306*ab5e842cSVikram Garhwal match_rx_tx_data(buf_tx, buf_rx, can_timestamp); 307*ab5e842cSVikram Garhwal 308*ab5e842cSVikram Garhwal qtest_quit(qts); 309*ab5e842cSVikram Garhwal } 310*ab5e842cSVikram Garhwal 311*ab5e842cSVikram Garhwal /* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */ 312*ab5e842cSVikram Garhwal static void test_can_snoopmode(void) 313*ab5e842cSVikram Garhwal { 314*ab5e842cSVikram Garhwal uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 }; 315*ab5e842cSVikram Garhwal uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 }; 316*ab5e842cSVikram Garhwal uint32_t status = 0; 317*ab5e842cSVikram Garhwal uint8_t can_timestamp = 1; 318*ab5e842cSVikram Garhwal 319*ab5e842cSVikram Garhwal QTestState *qts = qtest_init("-machine xlnx-zcu102" 320*ab5e842cSVikram Garhwal " -object can-bus,id=canbus0" 321*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus0=canbus0" 322*ab5e842cSVikram Garhwal " -machine xlnx-zcu102.canbus1=canbus0" 323*ab5e842cSVikram Garhwal ); 324*ab5e842cSVikram Garhwal 325*ab5e842cSVikram Garhwal /* Configure the CAN0. */ 326*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE); 327*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE); 328*ab5e842cSVikram Garhwal qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 329*ab5e842cSVikram Garhwal 330*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN); 331*ab5e842cSVikram Garhwal qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE); 332*ab5e842cSVikram Garhwal 333*ab5e842cSVikram Garhwal /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */ 334*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET); 335*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_SNOOP_MODE); 336*ab5e842cSVikram Garhwal 337*ab5e842cSVikram Garhwal status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET); 338*ab5e842cSVikram Garhwal g_assert_cmpint(status, ==, STATUS_NORMAL_MODE); 339*ab5e842cSVikram Garhwal 340*ab5e842cSVikram Garhwal send_data(qts, CAN1_BASE_ADDR, buf_tx); 341*ab5e842cSVikram Garhwal 342*ab5e842cSVikram Garhwal read_data(qts, CAN0_BASE_ADDR, buf_rx); 343*ab5e842cSVikram Garhwal 344*ab5e842cSVikram Garhwal match_rx_tx_data(buf_tx, buf_rx, can_timestamp); 345*ab5e842cSVikram Garhwal 346*ab5e842cSVikram Garhwal qtest_quit(qts); 347*ab5e842cSVikram Garhwal } 348*ab5e842cSVikram Garhwal 349*ab5e842cSVikram Garhwal int main(int argc, char **argv) 350*ab5e842cSVikram Garhwal { 351*ab5e842cSVikram Garhwal g_test_init(&argc, &argv, NULL); 352*ab5e842cSVikram Garhwal 353*ab5e842cSVikram Garhwal qtest_add_func("/net/can/can_bus", test_can_bus); 354*ab5e842cSVikram Garhwal qtest_add_func("/net/can/can_loopback", test_can_loopback); 355*ab5e842cSVikram Garhwal qtest_add_func("/net/can/can_filter", test_can_filter); 356*ab5e842cSVikram Garhwal qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode); 357*ab5e842cSVikram Garhwal qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode); 358*ab5e842cSVikram Garhwal 359*ab5e842cSVikram Garhwal return g_test_run(); 360*ab5e842cSVikram Garhwal } 361