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