2 * QTests for the Xilinx ZynqMP CAN controller.
4 * Copyright (c) 2020 Xilinx Inc.
6 * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include "qemu/osdep.h"
28 #include "libqos/libqtest.h"
31 #define CAN0_BASE_ADDR 0xFF060000
32 #define CAN1_BASE_ADDR 0xFF070000
34 /* Register addresses. */
35 #define R_SRR_OFFSET 0x00
36 #define R_MSR_OFFSET 0x04
37 #define R_SR_OFFSET 0x18
38 #define R_ISR_OFFSET 0x1C
39 #define R_ICR_OFFSET 0x24
40 #define R_TXID_OFFSET 0x30
41 #define R_TXDLC_OFFSET 0x34
42 #define R_TXDATA1_OFFSET 0x38
43 #define R_TXDATA2_OFFSET 0x3C
44 #define R_RXID_OFFSET 0x50
45 #define R_RXDLC_OFFSET 0x54
46 #define R_RXDATA1_OFFSET 0x58
47 #define R_RXDATA2_OFFSET 0x5C
59 #define CONFIG_MODE 0x00
60 #define NORMAL_MODE 0x00
61 #define LOOPBACK_MODE 0x02
62 #define SNOOP_MODE 0x04
63 #define SLEEP_MODE 0x01
64 #define ENABLE_CAN (1 << 1)
65 #define STATUS_NORMAL_MODE (1 << 3)
66 #define STATUS_LOOPBACK_MODE (1 << 1)
67 #define STATUS_SNOOP_MODE (1 << 12)
68 #define STATUS_SLEEP_MODE (1 << 2)
69 #define ISR_TXOK (1 << 1)
70 #define ISR_RXOK (1 << 4)
72 static void match_rx_tx_data(const uint32_t *buf_tx
, const uint32_t *buf_rx
,
73 uint8_t can_timestamp
)
79 if (R_RXID_OFFSET
+ 4 * size
== R_RXDLC_OFFSET
) {
80 g_assert_cmpint(buf_rx
[size
], ==, buf_tx
[size
] + can_timestamp
);
82 g_assert_cmpint(buf_rx
[size
], ==, buf_tx
[size
]);
89 static void read_data(QTestState
*qts
, uint64_t can_base_addr
, uint32_t *buf_rx
)
93 /* Read the interrupt on CAN rx. */
94 int_status
= qtest_readl(qts
, can_base_addr
+ R_ISR_OFFSET
) & ISR_RXOK
;
96 g_assert_cmpint(int_status
, ==, ISR_RXOK
);
98 /* Read the RX register data for CAN. */
99 buf_rx
[0] = qtest_readl(qts
, can_base_addr
+ R_RXID_OFFSET
);
100 buf_rx
[1] = qtest_readl(qts
, can_base_addr
+ R_RXDLC_OFFSET
);
101 buf_rx
[2] = qtest_readl(qts
, can_base_addr
+ R_RXDATA1_OFFSET
);
102 buf_rx
[3] = qtest_readl(qts
, can_base_addr
+ R_RXDATA2_OFFSET
);
104 /* Clear the RX interrupt. */
105 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_ICR_OFFSET
, ISR_RXOK
);
108 static void send_data(QTestState
*qts
, uint64_t can_base_addr
,
109 const uint32_t *buf_tx
)
113 /* Write the TX register data for CAN. */
114 qtest_writel(qts
, can_base_addr
+ R_TXID_OFFSET
, buf_tx
[0]);
115 qtest_writel(qts
, can_base_addr
+ R_TXDLC_OFFSET
, buf_tx
[1]);
116 qtest_writel(qts
, can_base_addr
+ R_TXDATA1_OFFSET
, buf_tx
[2]);
117 qtest_writel(qts
, can_base_addr
+ R_TXDATA2_OFFSET
, buf_tx
[3]);
119 /* Read the interrupt on CAN for tx. */
120 int_status
= qtest_readl(qts
, can_base_addr
+ R_ISR_OFFSET
) & ISR_TXOK
;
122 g_assert_cmpint(int_status
, ==, ISR_TXOK
);
124 /* Clear the interrupt for tx. */
125 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_ICR_OFFSET
, ISR_TXOK
);
129 * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
130 * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
131 * the data sent from CAN0 with received on CAN1.
133 static void test_can_bus(void)
135 const uint32_t buf_tx
[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
136 uint32_t buf_rx
[4] = { 0x00, 0x00, 0x00, 0x00 };
138 uint8_t can_timestamp
= 1;
140 QTestState
*qts
= qtest_init("-machine xlnx-zcu102"
141 " -object can-bus,id=canbus0"
142 " -machine xlnx-zcu102.canbus0=canbus0"
143 " -machine xlnx-zcu102.canbus1=canbus0"
146 /* Configure the CAN0 and CAN1. */
147 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
148 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_MSR_OFFSET
, NORMAL_MODE
);
149 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
150 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_MSR_OFFSET
, NORMAL_MODE
);
152 /* Check here if CAN0 and CAN1 are in normal mode. */
153 status
= qtest_readl(qts
, CAN0_BASE_ADDR
+ R_SR_OFFSET
);
154 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
156 status
= qtest_readl(qts
, CAN1_BASE_ADDR
+ R_SR_OFFSET
);
157 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
159 send_data(qts
, CAN0_BASE_ADDR
, buf_tx
);
161 read_data(qts
, CAN1_BASE_ADDR
, buf_rx
);
162 match_rx_tx_data(buf_tx
, buf_rx
, can_timestamp
);
168 * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
169 * each CAN0 and CAN1 are compared with RX register data for respective CAN.
171 static void test_can_loopback(void)
173 uint32_t buf_tx
[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
174 uint32_t buf_rx
[4] = { 0x00, 0x00, 0x00, 0x00 };
177 QTestState
*qts
= qtest_init("-machine xlnx-zcu102"
178 " -object can-bus,id=canbus0"
179 " -machine xlnx-zcu102.canbus0=canbus0"
180 " -machine xlnx-zcu102.canbus1=canbus0"
183 /* Configure the CAN0 in loopback mode. */
184 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, CONFIG_MODE
);
185 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_MSR_OFFSET
, LOOPBACK_MODE
);
186 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
188 /* Check here if CAN0 is set in loopback mode. */
189 status
= qtest_readl(qts
, CAN0_BASE_ADDR
+ R_SR_OFFSET
);
191 g_assert_cmpint(status
, ==, STATUS_LOOPBACK_MODE
);
193 send_data(qts
, CAN0_BASE_ADDR
, buf_tx
);
194 read_data(qts
, CAN0_BASE_ADDR
, buf_rx
);
195 match_rx_tx_data(buf_tx
, buf_rx
, 0);
197 /* Configure the CAN1 in loopback mode. */
198 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_SRR_OFFSET
, CONFIG_MODE
);
199 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_MSR_OFFSET
, LOOPBACK_MODE
);
200 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
202 /* Check here if CAN1 is set in loopback mode. */
203 status
= qtest_readl(qts
, CAN1_BASE_ADDR
+ R_SR_OFFSET
);
205 g_assert_cmpint(status
, ==, STATUS_LOOPBACK_MODE
);
207 send_data(qts
, CAN1_BASE_ADDR
, buf_tx
);
208 read_data(qts
, CAN1_BASE_ADDR
, buf_rx
);
209 match_rx_tx_data(buf_tx
, buf_rx
, 0);
215 * Enable filters for CAN1. This will filter incoming messages with ID. In this
216 * test message will pass through filter 2.
218 static void test_can_filter(void)
220 uint32_t buf_tx
[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
221 uint32_t buf_rx
[4] = { 0x00, 0x00, 0x00, 0x00 };
223 uint8_t can_timestamp
= 1;
225 QTestState
*qts
= qtest_init("-machine xlnx-zcu102"
226 " -object can-bus,id=canbus0"
227 " -machine xlnx-zcu102.canbus0=canbus0"
228 " -machine xlnx-zcu102.canbus1=canbus0"
231 /* Configure the CAN0 and CAN1. */
232 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
233 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_MSR_OFFSET
, NORMAL_MODE
);
234 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
235 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_MSR_OFFSET
, NORMAL_MODE
);
237 /* Check here if CAN0 and CAN1 are in normal mode. */
238 status
= qtest_readl(qts
, CAN0_BASE_ADDR
+ R_SR_OFFSET
);
239 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
241 status
= qtest_readl(qts
, CAN1_BASE_ADDR
+ R_SR_OFFSET
);
242 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
244 /* Set filter for CAN1 for incoming messages. */
245 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFR
, 0x0);
246 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFMR1
, 0xF7);
247 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFIR1
, 0x121F);
248 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFMR2
, 0x5431);
249 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFIR2
, 0x14);
250 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFMR3
, 0x1234);
251 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFIR3
, 0x5431);
252 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFMR4
, 0xFFF);
253 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFIR4
, 0x1234);
255 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_AFR
, 0xF);
257 send_data(qts
, CAN0_BASE_ADDR
, buf_tx
);
259 read_data(qts
, CAN1_BASE_ADDR
, buf_rx
);
260 match_rx_tx_data(buf_tx
, buf_rx
, can_timestamp
);
265 /* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
266 static void test_can_sleepmode(void)
268 uint32_t buf_tx
[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
269 uint32_t buf_rx
[4] = { 0x00, 0x00, 0x00, 0x00 };
271 uint8_t can_timestamp
= 1;
273 QTestState
*qts
= qtest_init("-machine xlnx-zcu102"
274 " -object can-bus,id=canbus0"
275 " -machine xlnx-zcu102.canbus0=canbus0"
276 " -machine xlnx-zcu102.canbus1=canbus0"
279 /* Configure the CAN0. */
280 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, CONFIG_MODE
);
281 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_MSR_OFFSET
, SLEEP_MODE
);
282 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
284 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
285 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_MSR_OFFSET
, NORMAL_MODE
);
287 /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
288 status
= qtest_readl(qts
, CAN0_BASE_ADDR
+ R_SR_OFFSET
);
289 g_assert_cmpint(status
, ==, STATUS_SLEEP_MODE
);
291 status
= qtest_readl(qts
, CAN1_BASE_ADDR
+ R_SR_OFFSET
);
292 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
294 send_data(qts
, CAN1_BASE_ADDR
, buf_tx
);
297 * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
298 * Check the CAN0 status now. It should exit the sleep mode and receive the
301 status
= qtest_readl(qts
, CAN0_BASE_ADDR
+ R_SR_OFFSET
);
302 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
304 read_data(qts
, CAN0_BASE_ADDR
, buf_rx
);
306 match_rx_tx_data(buf_tx
, buf_rx
, can_timestamp
);
311 /* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
312 static void test_can_snoopmode(void)
314 uint32_t buf_tx
[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
315 uint32_t buf_rx
[4] = { 0x00, 0x00, 0x00, 0x00 };
317 uint8_t can_timestamp
= 1;
319 QTestState
*qts
= qtest_init("-machine xlnx-zcu102"
320 " -object can-bus,id=canbus0"
321 " -machine xlnx-zcu102.canbus0=canbus0"
322 " -machine xlnx-zcu102.canbus1=canbus0"
325 /* Configure the CAN0. */
326 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, CONFIG_MODE
);
327 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_MSR_OFFSET
, SNOOP_MODE
);
328 qtest_writel(qts
, CAN0_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
330 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_SRR_OFFSET
, ENABLE_CAN
);
331 qtest_writel(qts
, CAN1_BASE_ADDR
+ R_MSR_OFFSET
, NORMAL_MODE
);
333 /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
334 status
= qtest_readl(qts
, CAN0_BASE_ADDR
+ R_SR_OFFSET
);
335 g_assert_cmpint(status
, ==, STATUS_SNOOP_MODE
);
337 status
= qtest_readl(qts
, CAN1_BASE_ADDR
+ R_SR_OFFSET
);
338 g_assert_cmpint(status
, ==, STATUS_NORMAL_MODE
);
340 send_data(qts
, CAN1_BASE_ADDR
, buf_tx
);
342 read_data(qts
, CAN0_BASE_ADDR
, buf_rx
);
344 match_rx_tx_data(buf_tx
, buf_rx
, can_timestamp
);
349 int main(int argc
, char **argv
)
351 g_test_init(&argc
, &argv
, NULL
);
353 qtest_add_func("/net/can/can_bus", test_can_bus
);
354 qtest_add_func("/net/can/can_loopback", test_can_loopback
);
355 qtest_add_func("/net/can/can_filter", test_can_filter
);
356 qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode
);
357 qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode
);