1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/uart.h>
8 #include <zephyr/device.h>
9 #include <zephyr/pm/device.h>
10 #include <zephyr/ztest.h>
11 
12 #define UART_NODE DT_NODELABEL(dut)
13 #define DISABLED_RX DT_PROP(UART_NODE, disable_rx)
14 
polling_verify(const struct device * dev,bool is_async,bool active)15 static void polling_verify(const struct device *dev, bool is_async, bool active)
16 {
17 	char c;
18 	char outs[] = "abc";
19 	int err;
20 
21 	if (DISABLED_RX || is_async) {
22 		/* If no RX pin just run few poll outs to check that it does
23 		 * not hang.
24 		 */
25 		for (int i = 0; i < ARRAY_SIZE(outs); i++) {
26 			uart_poll_out(dev, outs[i]);
27 		}
28 
29 		return;
30 	}
31 
32 	err = uart_poll_in(dev, &c);
33 	zassert_equal(err, -1);
34 
35 	for (int i = 0; i < ARRAY_SIZE(outs); i++) {
36 		uart_poll_out(dev, outs[i]);
37 		/* We need to wait until receiver gets the data. Receiver may have
38 		 * RX timeout so data is not received instantly.
39 		 */
40 		k_busy_wait(5000);
41 
42 		if (active) {
43 			err = uart_poll_in(dev, &c);
44 			zassert_equal(err, 0, "Unexpected err: %d", err);
45 			zassert_equal(c, outs[i]);
46 		}
47 
48 		err = uart_poll_in(dev, &c);
49 		zassert_equal(err, -1);
50 	}
51 }
52 
async_callback(const struct device * dev,struct uart_event * evt,void * ctx)53 static void async_callback(const struct device *dev, struct uart_event *evt, void *ctx)
54 {
55 	bool *done = ctx;
56 
57 	switch (evt->type) {
58 	case UART_TX_DONE:
59 		*done = true;
60 		break;
61 	default:
62 		break;
63 	}
64 }
65 
async_verify(const struct device * dev,bool active)66 static bool async_verify(const struct device *dev, bool active)
67 {
68 	char txbuf[] = "test";
69 	uint8_t rxbuf[32] = { 0 };
70 	volatile bool tx_done = false;
71 	int err;
72 
73 	err = uart_callback_set(dev, async_callback, (void *)&tx_done);
74 	if (err == -ENOTSUP) {
75 		return false;
76 	}
77 
78 	if (!active) {
79 		return true;
80 	}
81 
82 	zassert_equal(err, 0, "Unexpected err: %d", err);
83 
84 	/* Wait a bit to ensure that polling transfer is already finished otherwise
85 	 * receiver might be enabled when there is an ongoing transfer and bytes
86 	 * will get corrupted.
87 	 */
88 	k_busy_wait(1000);
89 
90 	if (!DISABLED_RX) {
91 		err = uart_rx_enable(dev, rxbuf, sizeof(rxbuf), 1 * USEC_PER_MSEC);
92 		zassert_equal(err, 0, "Unexpected err: %d", err);
93 	}
94 
95 	err = uart_tx(dev, txbuf, sizeof(txbuf), 10 * USEC_PER_MSEC);
96 	zassert_equal(err, 0, "Unexpected err: %d", err);
97 
98 	k_busy_wait(10000);
99 
100 	if (!DISABLED_RX) {
101 		err = uart_rx_disable(dev);
102 		zassert_true((err == 0) || (err == -EFAULT));
103 
104 		k_busy_wait(10000);
105 
106 		err = memcmp(txbuf, rxbuf, sizeof(txbuf));
107 		zassert_equal(err, 0, "Unexpected err: %d", err);
108 	}
109 
110 	zassert_true(tx_done);
111 
112 	return true;
113 }
114 
communication_verify(const struct device * dev,bool active)115 static void communication_verify(const struct device *dev, bool active)
116 {
117 	bool is_async = async_verify(dev, active);
118 
119 	polling_verify(dev, is_async, active);
120 }
121 
122 #define state_verify(dev, exp_state) do {\
123 	enum pm_device_state power_state; \
124 	int error = pm_device_state_get(dev, &power_state); \
125 	zassert_equal(error, 0, "Unexpected err: %d", error); \
126 	zassert_equal(power_state, exp_state); \
127 } while (0)
128 
action_run(const struct device * dev,enum pm_device_action action,int exp_err)129 static void action_run(const struct device *dev, enum pm_device_action action,
130 		      int exp_err)
131 {
132 	int err;
133 	enum pm_device_state prev_state, exp_state;
134 
135 	err = pm_device_state_get(dev, &prev_state);
136 	zassert_equal(err, 0, "Unexpected err: %d", err);
137 
138 	err = pm_device_action_run(dev, action);
139 	zassert_equal(err, exp_err, "Unexpected err: %d", err);
140 
141 	if (err == 0) {
142 		switch (action) {
143 		case PM_DEVICE_ACTION_SUSPEND:
144 			exp_state = PM_DEVICE_STATE_SUSPENDED;
145 			break;
146 		case PM_DEVICE_ACTION_RESUME:
147 			exp_state = PM_DEVICE_STATE_ACTIVE;
148 			break;
149 		default:
150 			exp_state = prev_state;
151 			break;
152 		}
153 	} else {
154 		exp_state = prev_state;
155 	}
156 
157 	state_verify(dev, exp_state);
158 }
159 
ZTEST(uart_pm,test_uart_pm_in_idle)160 ZTEST(uart_pm, test_uart_pm_in_idle)
161 {
162 	const struct device *dev;
163 
164 	dev = DEVICE_DT_GET(UART_NODE);
165 	zassert_true(device_is_ready(dev), "uart device is not ready");
166 
167 	state_verify(dev, PM_DEVICE_STATE_ACTIVE);
168 	communication_verify(dev, true);
169 
170 	action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
171 	communication_verify(dev, false);
172 
173 	action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
174 	communication_verify(dev, true);
175 
176 	action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
177 	communication_verify(dev, false);
178 
179 	action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
180 	communication_verify(dev, true);
181 
182 	/* Let's give enough time for the last byte to be transmitted out */
183 	k_busy_wait(500);
184 }
185 
ZTEST(uart_pm,test_uart_pm_poll_tx)186 ZTEST(uart_pm, test_uart_pm_poll_tx)
187 {
188 	const struct device *dev;
189 
190 	dev = DEVICE_DT_GET(UART_NODE);
191 	zassert_true(device_is_ready(dev), "uart device is not ready");
192 
193 	communication_verify(dev, true);
194 
195 	uart_poll_out(dev, 'a');
196 	action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
197 
198 	communication_verify(dev, false);
199 
200 	action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
201 
202 	communication_verify(dev, true);
203 
204 	/* Now same thing but with callback */
205 	uart_poll_out(dev, 'a');
206 	action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
207 
208 	communication_verify(dev, false);
209 
210 	action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
211 
212 	communication_verify(dev, true);
213 }
214 
work_handler(struct k_work * work)215 static void work_handler(struct k_work *work)
216 {
217 	const struct device *dev = DEVICE_DT_GET(UART_NODE);
218 
219 	action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
220 }
221 
222 /* Test going into low power state after interrupting poll out. Use various
223  * delays to test interruption at multiple places.
224  */
ZTEST(uart_pm,test_uart_pm_poll_tx_interrupted)225 ZTEST(uart_pm, test_uart_pm_poll_tx_interrupted)
226 {
227 	static struct k_work_delayable dwork;
228 	static struct k_work_sync sync;
229 	const struct device *dev;
230 	char str[] = "test";
231 
232 	dev = DEVICE_DT_GET(UART_NODE);
233 	zassert_true(device_is_ready(dev), "uart device is not ready");
234 
235 	k_work_init_delayable(&dwork, work_handler);
236 
237 	for (int i = 1; i < 100; i++) {
238 		k_work_schedule(&dwork, K_USEC(i * 10));
239 
240 		for (int j = 0; j < sizeof(str); j++) {
241 			uart_poll_out(dev, str[j]);
242 		}
243 
244 		k_work_flush_delayable(&dwork, &sync);
245 
246 		action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
247 
248 		communication_verify(dev, true);
249 	}
250 }
251 
uart_pm_setup(void)252 void *uart_pm_setup(void)
253 {
254 	if (DISABLED_RX) {
255 		PRINT("RX is disabled\n");
256 	}
257 
258 	return NULL;
259 }
260 
261 ZTEST_SUITE(uart_pm, NULL, uart_pm_setup, NULL, NULL, NULL);
262