xref: /qemu/tests/qtest/xlnx-can-test.c (revision ab5e842c4ba9cc543ce86729a042fa444e49de61)
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