1 /*
2  * Copyright 2022 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/drivers/watchdog.h>
9 
10 
11 /*
12  * To use this test, either the devicetree's /aliases must have a
13  * 'watchdog0' property, or one of the following watchdog compatibles
14  * must have an enabled node.
15  */
16 #if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(watchdog0))
17 #define WDT_NODE DT_ALIAS(watchdog0)
18 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_swt)
19 #define WDT_NODE DT_INST(0, nxp_s32_swt)
20 #endif
21 
22 #define WDT_FEED_TRIES		2
23 #define WDT_MAX_WINDOW		1000
24 #define WDT_TIMEOUT		K_MSEC(1100)
25 #define SLEEP_TIME		K_MSEC(500)
26 #define WDT_TEST_CB_TEST_VALUE	0xCB
27 
28 static struct wdt_timeout_cfg m_cfg_wdt0;
29 static volatile int wdt_interrupted_flag;
30 static volatile int wdt_feed_flag;
31 
32 
wdt_callback(const struct device * dev,int channel_id)33 static void wdt_callback(const struct device *dev, int channel_id)
34 {
35 	wdt_interrupted_flag += WDT_TEST_CB_TEST_VALUE;
36 	zassert_equal(WDT_FEED_TRIES, wdt_feed_flag,
37 			"%d: Invalid number of feeding (expected: %d)",
38 			wdt_feed_flag, WDT_FEED_TRIES);
39 }
40 
test_wdt_callback_reset_none(void)41 static int test_wdt_callback_reset_none(void)
42 {
43 	int err;
44 	const struct device *const wdt = DEVICE_DT_GET(WDT_NODE);
45 
46 	if (!device_is_ready(wdt)) {
47 		TC_PRINT("WDT device is not ready\n");
48 		return TC_FAIL;
49 	}
50 
51 	m_cfg_wdt0.window.min = 0U;
52 	m_cfg_wdt0.window.max = WDT_MAX_WINDOW;
53 	m_cfg_wdt0.flags = WDT_FLAG_RESET_NONE;
54 	m_cfg_wdt0.callback = wdt_callback;
55 
56 	err = wdt_install_timeout(wdt, &m_cfg_wdt0);
57 	if (err == -ENOTSUP) {
58 		TC_PRINT("Some of the options are not supported, skip\n");
59 		return TC_SKIP;
60 	} else if (err != 0) {
61 		TC_PRINT("Watchdog install error\n");
62 		return TC_FAIL;
63 	}
64 
65 	err = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG);
66 	if (err != 0) {
67 		TC_PRINT("Watchdog setup error\n");
68 		return TC_FAIL;
69 	}
70 
71 	TC_PRINT("Feeding watchdog %d times\n", WDT_FEED_TRIES);
72 	wdt_feed_flag = 0;
73 	wdt_interrupted_flag = 0;
74 	for (int i = 0; i < WDT_FEED_TRIES; ++i) {
75 		TC_PRINT("Feeding %d\n", i+1);
76 		wdt_feed(wdt, 0);
77 		wdt_feed_flag++;
78 		k_sleep(SLEEP_TIME);
79 	}
80 
81 	k_timeout_t timeout = WDT_TIMEOUT;
82 	uint64_t start_time = k_uptime_ticks();
83 
84 	while (wdt_interrupted_flag == 0) {
85 		if (k_uptime_ticks() - start_time >= timeout.ticks) {
86 			break;
87 		}
88 	}
89 
90 	zassert_equal(wdt_interrupted_flag, WDT_TEST_CB_TEST_VALUE,
91 			"wdt callback failed");
92 
93 	err = wdt_disable(wdt);
94 	if (err == -EPERM) {
95 		TC_PRINT("Some of the options are not permitted, skip\n");
96 		return TC_SKIP;
97 	} else if (err != 0) {
98 		TC_PRINT("Disable watchdog error\n");
99 		return TC_FAIL;
100 	}
101 
102 	return TC_PASS;
103 }
104 
test_wdt_bad_window_max(void)105 static int test_wdt_bad_window_max(void)
106 {
107 	int err;
108 	const struct device *const wdt = DEVICE_DT_GET(WDT_NODE);
109 
110 	if (!device_is_ready(wdt)) {
111 		TC_PRINT("WDT device is not ready\n");
112 		return TC_FAIL;
113 	}
114 
115 	m_cfg_wdt0.callback = NULL;
116 	m_cfg_wdt0.flags = WDT_FLAG_RESET_NONE;
117 	m_cfg_wdt0.window.max = 0U;
118 	m_cfg_wdt0.window.min = 0U;
119 	err = wdt_install_timeout(wdt, &m_cfg_wdt0);
120 	if (err == -EINVAL) {
121 		return TC_PASS;
122 	}
123 
124 	return TC_FAIL;
125 }
126 
127 
ZTEST(wdt_basic_reset_none,test_wdt_callback_reset_none)128 ZTEST(wdt_basic_reset_none, test_wdt_callback_reset_none)
129 {
130 	switch (test_wdt_callback_reset_none()) {
131 	case TC_SKIP:
132 		ztest_test_skip();
133 		break;
134 	case TC_PASS:
135 		ztest_test_pass();
136 		break;
137 	default:
138 		ztest_test_fail();
139 	}
140 }
141 
ZTEST(wdt_basic_reset_none,test_wdt_bad_window_max)142 ZTEST(wdt_basic_reset_none, test_wdt_bad_window_max)
143 {
144 	zassert_true(test_wdt_bad_window_max() == TC_PASS);
145 }
146 
147 ZTEST_SUITE(wdt_basic_reset_none, NULL, NULL, NULL, NULL, NULL);
148