1 /*
2  * Copyright (c) 2025 Silicon Laboratories Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT silabs_usart_uart
8 
9 #include <errno.h>
10 #include <zephyr/drivers/clock_control.h>
11 #include <zephyr/drivers/clock_control/clock_control_silabs.h>
12 #include <zephyr/drivers/pinctrl.h>
13 #include <zephyr/drivers/uart.h>
14 #include <zephyr/irq.h>
15 #include <zephyr/logging/log.h>
16 #include <zephyr/pm/device.h>
17 #include <zephyr/pm/policy.h>
18 #include <em_usart.h>
19 #ifdef CONFIG_UART_SILABS_USART_ASYNC
20 #include <zephyr/drivers/dma.h>
21 #include <zephyr/drivers/dma/dma_silabs_ldma.h>
22 #endif
23 
24 LOG_MODULE_REGISTER(uart_silabs_usart, CONFIG_UART_LOG_LEVEL);
25 
26 #define SILABS_USART_TIMER_COMPARE_VALUE 0xff
27 #define SILABS_USART_TIMEOUT_TO_TIMERCOUNTER(timeout, baudrate)                                    \
28 	((timeout * NSEC_PER_USEC) / ((NSEC_PER_SEC / baudrate) * SILABS_USART_TIMER_COMPARE_VALUE))
29 
30 #ifdef CONFIG_UART_SILABS_USART_ASYNC
31 struct uart_dma_channel {
32 	const struct device *dma_dev;
33 	uint32_t dma_channel;
34 	struct dma_block_config blk_cfg;
35 	struct dma_config dma_cfg;
36 	uint8_t priority;
37 	uint8_t *buffer;
38 	size_t buffer_length;
39 	volatile size_t counter;
40 	size_t offset;
41 	int32_t timeout_cnt;
42 	int32_t timeout;
43 	bool enabled;
44 };
45 #endif
46 struct uart_silabs_config {
47 	const struct pinctrl_dev_config *pcfg;
48 	const struct device *clock_dev;
49 	const struct silabs_clock_control_cmu_config clock_cfg;
50 	USART_TypeDef *base;
51 	void (*irq_config_func)(const struct device *dev);
52 };
53 
54 enum uart_silabs_pm_lock {
55 	UART_SILABS_PM_LOCK_TX,
56 	UART_SILABS_PM_LOCK_TX_POLL,
57 	UART_SILABS_PM_LOCK_RX,
58 	UART_SILABS_PM_LOCK_COUNT,
59 };
60 
61 struct uart_silabs_data {
62 	struct uart_config *uart_cfg;
63 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
64 	uart_irq_callback_user_data_t callback;
65 	void *cb_data;
66 #endif
67 #ifdef CONFIG_UART_SILABS_USART_ASYNC
68 	const struct device *uart_dev;
69 	uart_callback_t async_cb;
70 	void *async_user_data;
71 	struct uart_dma_channel dma_rx;
72 	struct uart_dma_channel dma_tx;
73 	uint8_t *rx_next_buffer;
74 	size_t rx_next_buffer_len;
75 #endif
76 #ifdef CONFIG_PM
77 	ATOMIC_DEFINE(pm_lock, UART_SILABS_PM_LOCK_COUNT);
78 #endif
79 };
80 
81 static int uart_silabs_pm_action(const struct device *dev, enum pm_device_action action);
82 
83 /**
84  * @brief Get PM lock on low power states
85  *
86  * @param dev  UART device struct
87  * @param lock UART PM lock type
88  *
89  * @return true if lock was taken, false otherwise
90  */
uart_silabs_pm_lock_get(const struct device * dev,enum uart_silabs_pm_lock lock)91 static bool uart_silabs_pm_lock_get(const struct device *dev, enum uart_silabs_pm_lock lock)
92 {
93 #ifdef CONFIG_PM
94 	struct uart_silabs_data *data = dev->data;
95 	bool was_locked = atomic_test_and_set_bit(data->pm_lock, lock);
96 
97 	if (!was_locked) {
98 		/* Lock out low-power states that would interfere with UART traffic */
99 		pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
100 		pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
101 	}
102 
103 	return !was_locked;
104 #else
105 	return false;
106 #endif
107 }
108 
109 /**
110  * @brief Release PM lock on low power states
111  *
112  * @param dev  UART device struct
113  * @param lock UART PM lock type
114  *
115  * @return true if lock was released, false otherwise
116  */
uart_silabs_pm_lock_put(const struct device * dev,enum uart_silabs_pm_lock lock)117 static bool uart_silabs_pm_lock_put(const struct device *dev, enum uart_silabs_pm_lock lock)
118 {
119 #ifdef CONFIG_PM
120 	struct uart_silabs_data *data = dev->data;
121 	bool was_locked = atomic_test_and_clear_bit(data->pm_lock, lock);
122 
123 	if (was_locked) {
124 		/* Unlock low-power states that would interfere with UART traffic */
125 		pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
126 		pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
127 	}
128 
129 	return was_locked;
130 #else
131 	return false;
132 #endif
133 }
134 
uart_silabs_poll_in(const struct device * dev,unsigned char * c)135 static int uart_silabs_poll_in(const struct device *dev, unsigned char *c)
136 {
137 	const struct uart_silabs_config *config = dev->config;
138 	uint32_t flags = USART_StatusGet(config->base);
139 
140 	if (flags & USART_STATUS_RXDATAV) {
141 		*c = USART_Rx(config->base);
142 		return 0;
143 	}
144 
145 	return -1;
146 }
147 
uart_silabs_poll_out(const struct device * dev,unsigned char c)148 static void uart_silabs_poll_out(const struct device *dev, unsigned char c)
149 {
150 	const struct uart_silabs_config *config = dev->config;
151 
152 	if (uart_silabs_pm_lock_get(dev, UART_SILABS_PM_LOCK_TX_POLL)) {
153 		USART_IntEnable(config->base, USART_IF_TXC);
154 	}
155 
156 	USART_Tx(config->base, c);
157 }
158 
uart_silabs_err_check(const struct device * dev)159 static int uart_silabs_err_check(const struct device *dev)
160 {
161 	const struct uart_silabs_config *config = dev->config;
162 	uint32_t flags = USART_IntGet(config->base);
163 	int err = 0;
164 
165 	if (flags & USART_IF_RXOF) {
166 		err |= UART_ERROR_OVERRUN;
167 	}
168 
169 	if (flags & USART_IF_PERR) {
170 		err |= UART_ERROR_PARITY;
171 	}
172 
173 	if (flags & USART_IF_FERR) {
174 		err |= UART_ERROR_FRAMING;
175 	}
176 
177 	USART_IntClear(config->base, USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR);
178 
179 	return err;
180 }
181 
182 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_silabs_fifo_fill(const struct device * dev,const uint8_t * tx_data,int len)183 static int uart_silabs_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
184 {
185 	const struct uart_silabs_config *config = dev->config;
186 	int i = 0;
187 
188 	while ((i < len) && (config->base->STATUS & USART_STATUS_TXBL)) {
189 		config->base->TXDATA = tx_data[i++];
190 	}
191 
192 	return i;
193 }
194 
uart_silabs_fifo_read(const struct device * dev,uint8_t * rx_data,const int len)195 static int uart_silabs_fifo_read(const struct device *dev, uint8_t *rx_data, const int len)
196 {
197 	const struct uart_silabs_config *config = dev->config;
198 	int i = 0;
199 
200 	while ((i < len) && (config->base->STATUS & USART_STATUS_RXDATAV)) {
201 		rx_data[i++] = (uint8_t)config->base->RXDATA;
202 	}
203 
204 	return i;
205 }
206 
uart_silabs_irq_tx_enable(const struct device * dev)207 static void uart_silabs_irq_tx_enable(const struct device *dev)
208 {
209 	const struct uart_silabs_config *config = dev->config;
210 
211 	(void)uart_silabs_pm_lock_get(dev, UART_SILABS_PM_LOCK_TX);
212 	USART_IntEnable(config->base, USART_IEN_TXBL | USART_IEN_TXC);
213 }
214 
uart_silabs_irq_tx_disable(const struct device * dev)215 static void uart_silabs_irq_tx_disable(const struct device *dev)
216 {
217 	const struct uart_silabs_config *config = dev->config;
218 
219 	USART_IntDisable(config->base, USART_IEN_TXBL | USART_IEN_TXC);
220 	(void)uart_silabs_pm_lock_put(dev, UART_SILABS_PM_LOCK_TX);
221 }
222 
uart_silabs_irq_tx_complete(const struct device * dev)223 static int uart_silabs_irq_tx_complete(const struct device *dev)
224 {
225 	const struct uart_silabs_config *config = dev->config;
226 	uint32_t flags = USART_IntGet(config->base);
227 
228 	USART_IntClear(config->base, USART_IF_TXC);
229 
230 	return !!(flags & USART_IF_TXC);
231 }
232 
uart_silabs_irq_tx_ready(const struct device * dev)233 static int uart_silabs_irq_tx_ready(const struct device *dev)
234 {
235 	const struct uart_silabs_config *config = dev->config;
236 	uint32_t flags = USART_IntGetEnabled(config->base);
237 
238 	return !!(flags & USART_IF_TXBL);
239 }
240 
uart_silabs_irq_rx_enable(const struct device * dev)241 static void uart_silabs_irq_rx_enable(const struct device *dev)
242 {
243 	const struct uart_silabs_config *config = dev->config;
244 
245 	(void)uart_silabs_pm_lock_get(dev, UART_SILABS_PM_LOCK_RX);
246 	USART_IntEnable(config->base, USART_IEN_RXDATAV);
247 }
248 
uart_silabs_irq_rx_disable(const struct device * dev)249 static void uart_silabs_irq_rx_disable(const struct device *dev)
250 {
251 	const struct uart_silabs_config *config = dev->config;
252 
253 	USART_IntDisable(config->base, USART_IEN_RXDATAV);
254 	(void)uart_silabs_pm_lock_put(dev, UART_SILABS_PM_LOCK_RX);
255 }
256 
uart_silabs_irq_rx_full(const struct device * dev)257 static int uart_silabs_irq_rx_full(const struct device *dev)
258 {
259 	const struct uart_silabs_config *config = dev->config;
260 	uint32_t flags = USART_IntGet(config->base);
261 
262 	return !!(flags & USART_IF_RXDATAV);
263 }
264 
uart_silabs_irq_rx_ready(const struct device * dev)265 static int uart_silabs_irq_rx_ready(const struct device *dev)
266 {
267 	const struct uart_silabs_config *config = dev->config;
268 
269 	return (config->base->IEN & USART_IEN_RXDATAV) && uart_silabs_irq_rx_full(dev);
270 }
271 
uart_silabs_irq_err_enable(const struct device * dev)272 static void uart_silabs_irq_err_enable(const struct device *dev)
273 {
274 	const struct uart_silabs_config *config = dev->config;
275 
276 	USART_IntEnable(config->base, USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR);
277 }
278 
uart_silabs_irq_err_disable(const struct device * dev)279 static void uart_silabs_irq_err_disable(const struct device *dev)
280 {
281 	const struct uart_silabs_config *config = dev->config;
282 
283 	USART_IntDisable(config->base, USART_IF_RXOF | USART_IF_PERR | USART_IF_FERR);
284 }
285 
uart_silabs_irq_is_pending(const struct device * dev)286 static int uart_silabs_irq_is_pending(const struct device *dev)
287 {
288 	return uart_silabs_irq_tx_ready(dev) || uart_silabs_irq_rx_ready(dev);
289 }
290 
uart_silabs_irq_update(const struct device * dev)291 static int uart_silabs_irq_update(const struct device *dev)
292 {
293 	return 1;
294 }
295 
uart_silabs_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)296 static void uart_silabs_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb,
297 					 void *cb_data)
298 {
299 	struct uart_silabs_data *data = dev->data;
300 
301 	data->callback = cb;
302 	data->cb_data = cb_data;
303 }
304 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
305 
306 #ifdef CONFIG_UART_SILABS_USART_ASYNC
async_user_callback(struct uart_silabs_data * data,struct uart_event * event)307 static inline void async_user_callback(struct uart_silabs_data *data, struct uart_event *event)
308 {
309 	if (data->async_cb) {
310 		data->async_cb(data->uart_dev, event, data->async_user_data);
311 	}
312 }
313 
async_evt_rx_rdy(struct uart_silabs_data * data)314 static inline void async_evt_rx_rdy(struct uart_silabs_data *data)
315 {
316 	struct uart_event event = {
317 		.type = UART_RX_RDY,
318 		.data.rx.buf = data->dma_rx.buffer,
319 		.data.rx.len = data->dma_rx.counter - data->dma_rx.offset,
320 		.data.rx.offset = data->dma_rx.offset
321 	};
322 
323 	data->dma_rx.offset = data->dma_rx.counter;
324 
325 	if (event.data.rx.len > 0) {
326 		async_user_callback(data, &event);
327 	}
328 }
329 
async_evt_tx_done(struct uart_silabs_data * data)330 static inline void async_evt_tx_done(struct uart_silabs_data *data)
331 {
332 	struct uart_event event = {
333 		.type = UART_TX_DONE,
334 		.data.tx.buf = data->dma_tx.buffer,
335 		.data.tx.len = data->dma_tx.counter
336 	};
337 
338 	data->dma_tx.buffer_length = 0;
339 	data->dma_tx.counter = 0;
340 
341 	async_user_callback(data, &event);
342 }
343 
async_evt_tx_abort(struct uart_silabs_data * data)344 static inline void async_evt_tx_abort(struct uart_silabs_data *data)
345 {
346 	struct uart_event event = {
347 		.type = UART_TX_ABORTED,
348 		.data.tx.buf = data->dma_tx.buffer,
349 		.data.tx.len = data->dma_tx.counter
350 	};
351 
352 	data->dma_tx.buffer_length = 0;
353 	data->dma_tx.counter = 0;
354 
355 	async_user_callback(data, &event);
356 }
357 
async_evt_rx_err(struct uart_silabs_data * data,int err_code)358 static inline void async_evt_rx_err(struct uart_silabs_data *data, int err_code)
359 {
360 	struct uart_event event = {
361 		.type = UART_RX_STOPPED,
362 		.data.rx_stop.reason = err_code,
363 		.data.rx_stop.data.len = data->dma_rx.counter,
364 		.data.rx_stop.data.offset = 0,
365 		.data.rx_stop.data.buf = data->dma_rx.buffer
366 	};
367 
368 	async_user_callback(data, &event);
369 }
370 
async_evt_rx_buf_release(struct uart_silabs_data * data)371 static inline void async_evt_rx_buf_release(struct uart_silabs_data *data)
372 {
373 	struct uart_event evt = {
374 		.type = UART_RX_BUF_RELEASED,
375 		.data.rx_buf.buf = data->dma_rx.buffer,
376 	};
377 
378 	async_user_callback(data, &evt);
379 }
380 
async_evt_rx_buf_request(struct uart_silabs_data * data)381 static inline void async_evt_rx_buf_request(struct uart_silabs_data *data)
382 {
383 	struct uart_event evt = {
384 		.type = UART_RX_BUF_REQUEST,
385 	};
386 
387 	async_user_callback(data, &evt);
388 }
389 
uart_silabs_async_callback_set(const struct device * dev,uart_callback_t callback,void * user_data)390 static int uart_silabs_async_callback_set(const struct device *dev, uart_callback_t callback,
391 					  void *user_data)
392 {
393 	struct uart_silabs_data *data = dev->data;
394 
395 	data->async_cb = callback;
396 	data->async_user_data = user_data;
397 
398 	return 0;
399 }
400 
uart_silabs_dma_replace_buffer(const struct device * dev)401 static void uart_silabs_dma_replace_buffer(const struct device *dev)
402 {
403 	struct uart_silabs_data *data = dev->data;
404 
405 	data->dma_rx.offset = 0;
406 	data->dma_rx.counter = 0;
407 	data->dma_rx.buffer = data->rx_next_buffer;
408 	data->dma_rx.buffer_length = data->rx_next_buffer_len;
409 	data->rx_next_buffer = NULL;
410 	data->rx_next_buffer_len = 0;
411 
412 	async_evt_rx_buf_request(data);
413 }
414 
uart_silabs_dma_rx_flush(struct uart_silabs_data * data)415 static void uart_silabs_dma_rx_flush(struct uart_silabs_data *data)
416 {
417 	struct dma_status stat;
418 	size_t rx_rcv_len;
419 
420 	if (!dma_get_status(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &stat)) {
421 		rx_rcv_len = data->dma_rx.buffer_length - stat.pending_length;
422 		if (rx_rcv_len > data->dma_rx.offset) {
423 			data->dma_rx.counter = rx_rcv_len;
424 			async_evt_rx_rdy(data);
425 		}
426 	}
427 }
428 
uart_silabs_dma_rx_cb(const struct device * dma_dev,void * user_data,uint32_t channel,int status)429 void uart_silabs_dma_rx_cb(const struct device *dma_dev, void *user_data, uint32_t channel,
430 			   int status)
431 {
432 	const struct device *uart_dev = user_data;
433 	struct uart_silabs_data *data = uart_dev->data;
434 	struct uart_event disabled_event = {.type = UART_RX_DISABLED};
435 
436 	if (status < 0) {
437 		async_evt_rx_err(data, status);
438 		return;
439 	}
440 
441 	data->dma_rx.counter = data->dma_rx.buffer_length;
442 
443 	async_evt_rx_rdy(data);
444 
445 	if (data->rx_next_buffer) {
446 		async_evt_rx_buf_release(data);
447 		uart_silabs_dma_replace_buffer(uart_dev);
448 	} else {
449 		dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
450 		data->dma_rx.enabled = false;
451 		async_evt_rx_buf_release(data);
452 		async_user_callback(data, &disabled_event);
453 	}
454 }
455 
uart_silabs_dma_tx_cb(const struct device * dma_dev,void * user_data,uint32_t channel,int status)456 void uart_silabs_dma_tx_cb(const struct device *dma_dev, void *user_data, uint32_t channel,
457 			   int status)
458 {
459 	const struct device *uart_dev = user_data;
460 	struct uart_silabs_data *data = uart_dev->data;
461 
462 	dma_stop(data->dma_tx.dma_dev, data->dma_tx.dma_channel);
463 	data->dma_tx.enabled = false;
464 }
465 
uart_silabs_async_tx(const struct device * dev,const uint8_t * tx_data,size_t buf_size,int32_t timeout)466 static int uart_silabs_async_tx(const struct device *dev, const uint8_t *tx_data, size_t buf_size,
467 				int32_t timeout)
468 {
469 	const struct uart_silabs_config *config = dev->config;
470 	struct uart_silabs_data *data = dev->data;
471 	int ret;
472 
473 	if (!data->dma_tx.dma_dev) {
474 		return -ENODEV;
475 	}
476 
477 	if (data->dma_tx.buffer_length) {
478 		return -EBUSY;
479 	}
480 
481 	data->dma_tx.buffer = (uint8_t *)tx_data;
482 	data->dma_tx.buffer_length = buf_size;
483 
484 	/* User timeout is expressed as number of TCMP2 interrupt which occurs every
485 	 * SILABS_USART_TIMER_COMPARE_VALUE baud-times
486 	 */
487 	if (data->uart_cfg->baudrate > 0 && timeout >= 0) {
488 		data->dma_tx.timeout =
489 			SILABS_USART_TIMEOUT_TO_TIMERCOUNTER(timeout, data->uart_cfg->baudrate);
490 	} else {
491 		data->dma_tx.timeout = 0;
492 	}
493 
494 	data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.buffer;
495 	data->dma_tx.blk_cfg.block_size = data->dma_tx.buffer_length;
496 
497 	(void)uart_silabs_pm_lock_get(dev, UART_SILABS_PM_LOCK_TX);
498 	USART_IntClear(config->base, USART_IF_TXC | USART_IF_TCMP2);
499 	USART_IntEnable(config->base, USART_IF_TXC);
500 	if (timeout >= 0) {
501 		USART_IntEnable(config->base, USART_IF_TCMP2);
502 	}
503 
504 	ret = dma_config(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &data->dma_tx.dma_cfg);
505 	if (ret) {
506 		LOG_ERR("dma tx config error!");
507 		return ret;
508 	}
509 
510 	ret = dma_start(data->dma_tx.dma_dev, data->dma_tx.dma_channel);
511 	if (ret) {
512 		LOG_ERR("UART err: TX DMA start failed!");
513 		return ret;
514 	}
515 
516 	data->dma_tx.enabled = true;
517 
518 	return 0;
519 }
520 
uart_silabs_async_tx_abort(const struct device * dev)521 static int uart_silabs_async_tx_abort(const struct device *dev)
522 {
523 	const struct uart_silabs_config *config = dev->config;
524 	struct uart_silabs_data *data = dev->data;
525 	size_t tx_buffer_length = data->dma_tx.buffer_length;
526 	struct dma_status stat;
527 
528 	if (!tx_buffer_length) {
529 		return -EFAULT;
530 	}
531 
532 	USART_IntDisable(config->base, USART_IF_TXC);
533 	USART_IntDisable(config->base, USART_IF_TCMP2);
534 	USART_IntClear(config->base, USART_IF_TXC | USART_IF_TCMP2);
535 	(void)uart_silabs_pm_lock_put(dev, UART_SILABS_PM_LOCK_TX);
536 
537 	if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) {
538 		data->dma_tx.counter = tx_buffer_length - stat.pending_length;
539 	}
540 
541 	dma_stop(data->dma_tx.dma_dev, data->dma_tx.dma_channel);
542 	data->dma_tx.enabled = false;
543 
544 	async_evt_tx_abort(data);
545 
546 	return 0;
547 }
548 
uart_silabs_async_rx_enable(const struct device * dev,uint8_t * rx_buf,size_t buf_size,int32_t timeout)549 static int uart_silabs_async_rx_enable(const struct device *dev, uint8_t *rx_buf, size_t buf_size,
550 				       int32_t timeout)
551 {
552 	const struct uart_silabs_config *config = dev->config;
553 	struct uart_silabs_data *data = dev->data;
554 	int ret;
555 
556 	if (!data->dma_rx.dma_dev) {
557 		return -ENODEV;
558 	}
559 
560 	if (data->dma_rx.enabled) {
561 		LOG_WRN("RX was already enabled");
562 		return -EBUSY;
563 	}
564 
565 	data->dma_rx.offset = 0;
566 	data->dma_rx.buffer = rx_buf;
567 	data->dma_rx.buffer_length = buf_size;
568 	data->dma_rx.counter = 0;
569 
570 	/* User timeout is expressed as number of TCMP1 interrupt which occurs every
571 	 * SILABS_USART_TIMER_COMPARE_VALUE baud-times
572 	 */
573 	if (data->uart_cfg->baudrate > 0 && timeout >= 0) {
574 		data->dma_rx.timeout =
575 			SILABS_USART_TIMEOUT_TO_TIMERCOUNTER(timeout, data->uart_cfg->baudrate);
576 	} else {
577 		data->dma_rx.timeout = 0;
578 	}
579 
580 	data->dma_rx.blk_cfg.block_size = buf_size;
581 	data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer;
582 
583 	ret = dma_config(data->dma_rx.dma_dev, data->dma_rx.dma_channel, &data->dma_rx.dma_cfg);
584 
585 	if (ret) {
586 		LOG_ERR("UART ERR: RX DMA config failed!");
587 		return -EINVAL;
588 	}
589 
590 	if (dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel)) {
591 		LOG_ERR("UART ERR: RX DMA start failed!");
592 		return -EFAULT;
593 	}
594 
595 	(void)uart_silabs_pm_lock_get(dev, UART_SILABS_PM_LOCK_RX);
596 	USART_IntClear(config->base, USART_IF_RXOF | USART_IF_TCMP1);
597 	USART_IntEnable(config->base, USART_IF_RXOF);
598 
599 	if (timeout >= 0) {
600 		USART_IntEnable(config->base, USART_IF_TCMP1);
601 	}
602 
603 	data->dma_rx.enabled = true;
604 
605 	async_evt_rx_buf_request(data);
606 
607 	return ret;
608 }
609 
uart_silabs_async_rx_disable(const struct device * dev)610 static int uart_silabs_async_rx_disable(const struct device *dev)
611 {
612 	const struct uart_silabs_config *config = dev->config;
613 	USART_TypeDef *usart = config->base;
614 	struct uart_silabs_data *data = dev->data;
615 	struct uart_event disabled_event = {.type = UART_RX_DISABLED};
616 
617 	if (!data->dma_rx.enabled) {
618 		return -EFAULT;
619 	}
620 
621 	dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
622 
623 	USART_IntDisable(usart, USART_IF_RXOF);
624 	USART_IntDisable(usart, USART_IF_TCMP1);
625 	USART_IntClear(usart, USART_IF_RXOF | USART_IF_TCMP1);
626 	(void)uart_silabs_pm_lock_put(dev, UART_SILABS_PM_LOCK_RX);
627 
628 	if (!data->dma_rx.enabled) {
629 		usart->CMD = USART_CMD_CLEARRX;
630 	}
631 
632 	uart_silabs_dma_rx_flush(data);
633 
634 	async_evt_rx_buf_release(data);
635 
636 	if (data->rx_next_buffer) {
637 		struct uart_event rx_next_buf_release_evt = {
638 			.type = UART_RX_BUF_RELEASED,
639 			.data.rx_buf.buf = data->rx_next_buffer,
640 		};
641 		async_user_callback(data, &rx_next_buf_release_evt);
642 	}
643 
644 	data->rx_next_buffer = NULL;
645 	data->rx_next_buffer_len = 0;
646 
647 	data->dma_rx.enabled = false;
648 
649 	async_user_callback(data, &disabled_event);
650 
651 	return 0;
652 }
653 
uart_silabs_async_rx_buf_rsp(const struct device * dev,uint8_t * buf,size_t len)654 static int uart_silabs_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, size_t len)
655 {
656 	struct uart_silabs_data *data = dev->data;
657 	unsigned int key;
658 	int ret;
659 
660 	key = irq_lock();
661 
662 	if (data->rx_next_buffer) {
663 		return -EBUSY;
664 	} else if (!data->dma_rx.enabled) {
665 		return -EACCES;
666 	}
667 
668 	data->rx_next_buffer = buf;
669 	data->rx_next_buffer_len = len;
670 	data->dma_rx.blk_cfg.dest_address = (uint32_t)buf;
671 	data->dma_rx.blk_cfg.block_size = len;
672 
673 	irq_unlock(key);
674 
675 	ret = silabs_ldma_append_block(data->dma_rx.dma_dev, data->dma_rx.dma_channel,
676 				       &data->dma_rx.dma_cfg);
677 	if (ret) {
678 		LOG_ERR("UART ERR: RX DMA append failed!");
679 		return -EINVAL;
680 	}
681 
682 	return ret;
683 }
684 
uart_silabs_async_init(const struct device * dev)685 static int uart_silabs_async_init(const struct device *dev)
686 {
687 	const struct uart_silabs_config *config = dev->config;
688 	USART_TypeDef *usart = config->base;
689 	struct uart_silabs_data *data = dev->data;
690 
691 	data->uart_dev = dev;
692 
693 	if (data->dma_rx.dma_dev) {
694 		if (!device_is_ready(data->dma_rx.dma_dev)) {
695 			return -ENODEV;
696 		}
697 		data->dma_rx.dma_channel = dma_request_channel(data->dma_rx.dma_dev, NULL);
698 	}
699 
700 	if (data->dma_tx.dma_dev) {
701 		if (!device_is_ready(data->dma_tx.dma_dev)) {
702 			return -ENODEV;
703 		}
704 		data->dma_tx.dma_channel = dma_request_channel(data->dma_tx.dma_dev, NULL);
705 	}
706 
707 	data->dma_rx.enabled = false;
708 	data->dma_tx.enabled = false;
709 
710 	memset(&data->dma_rx.blk_cfg, 0, sizeof(data->dma_rx.blk_cfg));
711 	data->dma_rx.blk_cfg.source_address = (uintptr_t)&(usart->RXDATA);
712 	data->dma_rx.blk_cfg.dest_address = 0;
713 	data->dma_rx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
714 	data->dma_rx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
715 	data->dma_rx.dma_cfg.complete_callback_en = 1;
716 	data->dma_rx.dma_cfg.channel_priority = 3;
717 	data->dma_rx.dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
718 	data->dma_rx.dma_cfg.head_block = &data->dma_rx.blk_cfg;
719 	data->dma_rx.dma_cfg.user_data = (void *)dev;
720 	data->rx_next_buffer = NULL;
721 	data->rx_next_buffer_len = 0;
722 
723 	memset(&data->dma_tx.blk_cfg, 0, sizeof(data->dma_tx.blk_cfg));
724 	data->dma_tx.blk_cfg.dest_address = (uintptr_t)&(usart->TXDATA);
725 	data->dma_tx.blk_cfg.source_address = 0;
726 	data->dma_tx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
727 	data->dma_tx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
728 	data->dma_tx.dma_cfg.complete_callback_en = 1;
729 	data->dma_tx.dma_cfg.channel_direction = MEMORY_TO_PERIPHERAL;
730 	data->dma_tx.dma_cfg.head_block = &data->dma_tx.blk_cfg;
731 	data->dma_tx.dma_cfg.user_data = (void *)dev;
732 
733 	config->base->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
734 	config->base->TIMECMP1 =
735 		USART_TIMECMP1_TSTOP_RXACT | USART_TIMECMP1_TSTART_RXEOF |
736 		USART_TIMECMP1_RESTARTEN |
737 		(SILABS_USART_TIMER_COMPARE_VALUE << _USART_TIMECMP1_TCMPVAL_SHIFT);
738 	config->base->TIMECMP2 =
739 		USART_TIMECMP2_TSTOP_TXST | USART_TIMECMP2_TSTART_TXEOF | USART_TIMECMP2_RESTARTEN |
740 		(SILABS_USART_TIMER_COMPARE_VALUE << _USART_TIMECMP2_TCMPVAL_SHIFT);
741 
742 	return 0;
743 }
744 #endif /* CONFIG_UART_SILABS_USART_ASYNC */
745 
uart_silabs_isr(const struct device * dev)746 static void uart_silabs_isr(const struct device *dev)
747 {
748 	__maybe_unused struct uart_silabs_data *data = dev->data;
749 	const struct uart_silabs_config *config = dev->config;
750 	USART_TypeDef *usart = config->base;
751 	uint32_t flags = USART_IntGet(usart);
752 #ifdef CONFIG_UART_SILABS_USART_ASYNC
753 	struct dma_status stat;
754 #endif
755 
756 	if (flags & USART_IF_TXC) {
757 		if (uart_silabs_pm_lock_put(dev, UART_SILABS_PM_LOCK_TX_POLL)) {
758 			USART_IntDisable(usart, USART_IEN_TXC);
759 			USART_IntClear(usart, USART_IF_TXC);
760 		}
761 	}
762 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
763 	if (data->callback) {
764 		data->callback(dev, data->cb_data);
765 	}
766 #endif
767 #ifdef CONFIG_UART_SILABS_USART_ASYNC
768 	if (flags & USART_IF_TCMP1) {
769 
770 		data->dma_rx.timeout_cnt++;
771 		if (data->dma_rx.timeout_cnt >= data->dma_rx.timeout) {
772 			uart_silabs_dma_rx_flush(data);
773 
774 			usart->TIMECMP1 &= ~_USART_TIMECMP1_TSTART_MASK;
775 			usart->TIMECMP1 |= USART_TIMECMP1_TSTART_RXEOF;
776 			data->dma_rx.timeout_cnt = 0;
777 		}
778 
779 		USART_IntClear(usart, USART_IF_TCMP1);
780 	}
781 	if (flags & USART_IF_RXOF) {
782 		async_evt_rx_err(data, UART_ERROR_OVERRUN);
783 
784 		uart_silabs_async_rx_disable(dev);
785 
786 		USART_IntClear(usart, USART_IF_RXOF);
787 	}
788 	if (flags & USART_IF_TXC) {
789 		if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) {
790 			data->dma_tx.counter = data->dma_tx.buffer_length - stat.pending_length;
791 		}
792 
793 		if (data->dma_tx.counter == data->dma_tx.buffer_length) {
794 			USART_IntDisable(config->base, USART_IF_TXC);
795 			USART_IntDisable(config->base, USART_IF_TCMP2);
796 			USART_IntClear(usart, USART_IF_TXC | USART_IF_TCMP2);
797 			(void)uart_silabs_pm_lock_put(dev, UART_SILABS_PM_LOCK_TX);
798 
799 			usart->TIMECMP2 &= ~_USART_TIMECMP2_TSTART_MASK;
800 			usart->TIMECMP2 |= USART_TIMECMP2_TSTART_DISABLE;
801 		}
802 
803 		async_evt_tx_done(data);
804 	}
805 	if (flags & USART_IF_TCMP2) {
806 		data->dma_tx.timeout_cnt++;
807 		if (data->dma_tx.timeout_cnt >= data->dma_tx.timeout) {
808 			usart->TIMECMP2 &= ~_USART_TIMECMP2_TSTART_MASK;
809 			usart->TIMECMP2 |= USART_TIMECMP2_TSTART_DISABLE;
810 			data->dma_tx.timeout_cnt = 0;
811 
812 			uart_silabs_async_tx_abort(dev);
813 		}
814 
815 		USART_IntClear(usart, USART_IF_TCMP2);
816 	}
817 #endif /* CONFIG_UART_SILABS_USART_ASYNC */
818 }
819 
uart_silabs_cfg2ll_parity(enum uart_config_parity parity)820 static inline USART_Parity_TypeDef uart_silabs_cfg2ll_parity(
821 	enum uart_config_parity parity)
822 {
823 	switch (parity) {
824 	case UART_CFG_PARITY_ODD:
825 		return usartOddParity;
826 	case UART_CFG_PARITY_EVEN:
827 		return usartEvenParity;
828 	case UART_CFG_PARITY_NONE:
829 	default:
830 		return usartNoParity;
831 	}
832 }
833 
uart_silabs_cfg2ll_stopbits(enum uart_config_stop_bits sb)834 static inline USART_Stopbits_TypeDef uart_silabs_cfg2ll_stopbits(
835 	enum uart_config_stop_bits sb)
836 {
837 	switch (sb) {
838 	case UART_CFG_STOP_BITS_0_5:
839 		return usartStopbits0p5;
840 	case UART_CFG_STOP_BITS_1:
841 		return usartStopbits1;
842 	case UART_CFG_STOP_BITS_2:
843 		return usartStopbits2;
844 	case UART_CFG_STOP_BITS_1_5:
845 		return usartStopbits1p5;
846 	default:
847 		return usartStopbits1;
848 	}
849 }
850 
uart_silabs_cfg2ll_databits(enum uart_config_data_bits db,enum uart_config_parity p)851 static inline USART_Databits_TypeDef uart_silabs_cfg2ll_databits(
852 	enum uart_config_data_bits db, enum uart_config_parity p)
853 {
854 	switch (db) {
855 	case UART_CFG_DATA_BITS_7:
856 		if (p == UART_CFG_PARITY_NONE) {
857 			return usartDatabits7;
858 		} else {
859 			return usartDatabits8;
860 		}
861 	case UART_CFG_DATA_BITS_9:
862 		return usartDatabits9;
863 	case UART_CFG_DATA_BITS_8:
864 	default:
865 		if (p == UART_CFG_PARITY_NONE) {
866 			return usartDatabits8;
867 		} else {
868 			return usartDatabits9;
869 		}
870 		return usartDatabits8;
871 	}
872 }
873 
uart_silabs_cfg2ll_hwctrl(enum uart_config_flow_control fc)874 static inline USART_HwFlowControl_TypeDef uart_silabs_cfg2ll_hwctrl(
875 	enum uart_config_flow_control fc)
876 {
877 	if (fc == UART_CFG_FLOW_CTRL_RTS_CTS) {
878 		return usartHwFlowControlCtsAndRts;
879 	}
880 
881 	return usartHwFlowControlNone;
882 }
883 
uart_silabs_ll2cfg_parity(USART_Parity_TypeDef parity)884 static inline enum uart_config_parity uart_silabs_ll2cfg_parity(USART_Parity_TypeDef parity)
885 {
886 	switch (parity) {
887 	case usartOddParity:
888 		return UART_CFG_PARITY_ODD;
889 	case usartEvenParity:
890 		return UART_CFG_PARITY_EVEN;
891 	case usartNoParity:
892 	default:
893 		return UART_CFG_PARITY_NONE;
894 	}
895 }
896 
uart_silabs_ll2cfg_stopbits(USART_Stopbits_TypeDef sb)897 static inline enum uart_config_stop_bits uart_silabs_ll2cfg_stopbits(USART_Stopbits_TypeDef sb)
898 {
899 	switch (sb) {
900 	case usartStopbits0p5:
901 		return UART_CFG_STOP_BITS_0_5;
902 	case usartStopbits1:
903 		return UART_CFG_STOP_BITS_1;
904 	case usartStopbits1p5:
905 		return UART_CFG_STOP_BITS_1_5;
906 	case usartStopbits2:
907 		return UART_CFG_STOP_BITS_2;
908 	default:
909 		return UART_CFG_STOP_BITS_1;
910 	}
911 }
912 
uart_silabs_ll2cfg_databits(USART_Databits_TypeDef db,USART_Parity_TypeDef p)913 static inline enum uart_config_data_bits uart_silabs_ll2cfg_databits(USART_Databits_TypeDef db,
914 								    USART_Parity_TypeDef p)
915 {
916 	switch (db) {
917 	case usartDatabits7:
918 		if (p == usartNoParity) {
919 			return UART_CFG_DATA_BITS_7;
920 		} else {
921 			return UART_CFG_DATA_BITS_6;
922 		}
923 	case usartDatabits9:
924 		if (p == usartNoParity) {
925 			return UART_CFG_DATA_BITS_9;
926 		} else {
927 			return UART_CFG_DATA_BITS_8;
928 		}
929 	case usartDatabits8:
930 	default:
931 		if (p == usartNoParity) {
932 			return UART_CFG_DATA_BITS_8;
933 		} else {
934 			return UART_CFG_DATA_BITS_7;
935 		}
936 	}
937 }
938 
uart_silabs_ll2cfg_hwctrl(USART_HwFlowControl_TypeDef fc)939 static inline enum uart_config_flow_control uart_silabs_ll2cfg_hwctrl(
940 	USART_HwFlowControl_TypeDef fc)
941 {
942 	if (fc == usartHwFlowControlCtsAndRts) {
943 		return UART_CFG_FLOW_CTRL_RTS_CTS;
944 	}
945 
946 	return UART_CFG_FLOW_CTRL_NONE;
947 }
948 
uart_silabs_configure_peripheral(const struct device * dev,bool enable)949 static void uart_silabs_configure_peripheral(const struct device *dev, bool enable)
950 {
951 	const struct uart_silabs_config *config = dev->config;
952 	const struct uart_silabs_data *data = dev->data;
953 	USART_InitAsync_TypeDef usartInit = USART_INITASYNC_DEFAULT;
954 
955 	usartInit.baudrate = data->uart_cfg->baudrate;
956 	usartInit.parity = uart_silabs_cfg2ll_parity(data->uart_cfg->parity);
957 	usartInit.stopbits = uart_silabs_cfg2ll_stopbits(data->uart_cfg->stop_bits);
958 	usartInit.databits = uart_silabs_cfg2ll_databits(data->uart_cfg->data_bits,
959 							 data->uart_cfg->parity);
960 	usartInit.hwFlowControl = uart_silabs_cfg2ll_hwctrl(data->uart_cfg->flow_ctrl);
961 	usartInit.enable = enable ? usartEnable : usartDisable;
962 
963 	USART_InitAsync(config->base, &usartInit);
964 }
965 
966 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
uart_silabs_configure(const struct device * dev,const struct uart_config * cfg)967 static int uart_silabs_configure(const struct device *dev,
968 				const struct uart_config *cfg)
969 {
970 	const struct uart_silabs_config *config = dev->config;
971 	USART_TypeDef *base = config->base;
972 	struct uart_silabs_data *data = dev->data;
973 
974 #ifdef CONFIG_UART_SILABS_USART_ASYNC
975 	if (data->dma_rx.enabled || data->dma_tx.enabled) {
976 		return -EBUSY;
977 	}
978 #endif
979 
980 	if ((cfg->parity == UART_CFG_PARITY_MARK) ||
981 	    (cfg->parity == UART_CFG_PARITY_SPACE)) {
982 		return -ENOSYS;
983 	}
984 
985 	if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_DTR_DSR ||
986 	    cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RS485) {
987 		return -ENOSYS;
988 	}
989 
990 	*data->uart_cfg = *cfg;
991 	USART_Enable(base, usartDisable);
992 
993 	uart_silabs_configure_peripheral(dev, true);
994 
995 	return 0;
996 };
997 
uart_silabs_config_get(const struct device * dev,struct uart_config * cfg)998 static int uart_silabs_config_get(const struct device *dev,
999 				 struct uart_config *cfg)
1000 {
1001 	struct uart_silabs_data *data = dev->data;
1002 	struct uart_config *uart_cfg = data->uart_cfg;
1003 
1004 	cfg->baudrate = uart_cfg->baudrate;
1005 	cfg->parity = uart_cfg->parity;
1006 	cfg->stop_bits = uart_cfg->stop_bits;
1007 	cfg->data_bits = uart_cfg->data_bits;
1008 	cfg->flow_ctrl = uart_cfg->flow_ctrl;
1009 
1010 	return 0;
1011 }
1012 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
1013 
uart_silabs_init(const struct device * dev)1014 static int uart_silabs_init(const struct device *dev)
1015 {
1016 	int err;
1017 	const struct uart_silabs_config *config = dev->config;
1018 
1019 	/* The peripheral and gpio clock are already enabled from soc and gpio driver */
1020 	/* Enable USART clock */
1021 	err = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->clock_cfg);
1022 	if (err < 0) {
1023 		return err;
1024 	}
1025 
1026 	uart_silabs_configure_peripheral(dev, false);
1027 
1028 	config->irq_config_func(dev);
1029 
1030 #ifdef CONFIG_UART_SILABS_USART_ASYNC
1031 	err = uart_silabs_async_init(dev);
1032 	if (err < 0) {
1033 		return err;
1034 	}
1035 #endif
1036 	return pm_device_driver_init(dev, uart_silabs_pm_action);
1037 }
1038 
uart_silabs_pm_action(const struct device * dev,enum pm_device_action action)1039 static int uart_silabs_pm_action(const struct device *dev, enum pm_device_action action)
1040 {
1041 	int err;
1042 	const struct uart_silabs_config *config = dev->config;
1043 	__maybe_unused struct uart_silabs_data *data = dev->data;
1044 
1045 	if (action == PM_DEVICE_ACTION_RESUME) {
1046 		err = clock_control_on(config->clock_dev,
1047 				       (clock_control_subsys_t)&config->clock_cfg);
1048 		if (err < 0 && err != -EALREADY) {
1049 			return err;
1050 		}
1051 
1052 		err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
1053 		if (err < 0) {
1054 			return err;
1055 		}
1056 
1057 		USART_Enable(config->base, usartEnable);
1058 	} else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) {
1059 #ifdef CONFIG_UART_SILABS_USART_ASYNC
1060 		/* Entering suspend requires there to be no active asynchronous calls. */
1061 		__ASSERT_NO_MSG(!data->dma_rx.enabled);
1062 		__ASSERT_NO_MSG(!data->dma_tx.enabled);
1063 #endif
1064 		USART_Enable(config->base, usartDisable);
1065 
1066 		err = clock_control_off(config->clock_dev,
1067 					(clock_control_subsys_t)&config->clock_cfg);
1068 		if (err < 0) {
1069 			return err;
1070 		}
1071 
1072 		err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
1073 		if (err < 0 && err != -ENOENT) {
1074 			return err;
1075 		}
1076 
1077 	} else {
1078 		return -ENOTSUP;
1079 	}
1080 
1081 	return 0;
1082 }
1083 
1084 static DEVICE_API(uart, uart_silabs_driver_api) = {
1085 	.poll_in = uart_silabs_poll_in,
1086 	.poll_out = uart_silabs_poll_out,
1087 	.err_check = uart_silabs_err_check,
1088 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
1089 	.configure = uart_silabs_configure,
1090 	.config_get = uart_silabs_config_get,
1091 #endif
1092 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
1093 	.fifo_fill = uart_silabs_fifo_fill,
1094 	.fifo_read = uart_silabs_fifo_read,
1095 	.irq_tx_enable = uart_silabs_irq_tx_enable,
1096 	.irq_tx_disable = uart_silabs_irq_tx_disable,
1097 	.irq_tx_complete = uart_silabs_irq_tx_complete,
1098 	.irq_tx_ready = uart_silabs_irq_tx_ready,
1099 	.irq_rx_enable = uart_silabs_irq_rx_enable,
1100 	.irq_rx_disable = uart_silabs_irq_rx_disable,
1101 	.irq_rx_ready = uart_silabs_irq_rx_ready,
1102 	.irq_err_enable = uart_silabs_irq_err_enable,
1103 	.irq_err_disable = uart_silabs_irq_err_disable,
1104 	.irq_is_pending = uart_silabs_irq_is_pending,
1105 	.irq_update = uart_silabs_irq_update,
1106 	.irq_callback_set = uart_silabs_irq_callback_set,
1107 #endif
1108 #ifdef CONFIG_UART_SILABS_USART_ASYNC
1109 	.callback_set = uart_silabs_async_callback_set,
1110 	.tx = uart_silabs_async_tx,
1111 	.tx_abort = uart_silabs_async_tx_abort,
1112 	.rx_enable = uart_silabs_async_rx_enable,
1113 	.rx_disable = uart_silabs_async_rx_disable,
1114 	.rx_buf_rsp = uart_silabs_async_rx_buf_rsp,
1115 #endif
1116 };
1117 
1118 #ifdef CONFIG_UART_SILABS_USART_ASYNC
1119 
1120 #define UART_DMA_CHANNEL_INIT(index, dir)                                                          \
1121 	.dma_##dir = {                                                                             \
1122 		.dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(index, dir)),                   \
1123 		.dma_cfg = {                                                                       \
1124 			.dma_slot = SILABS_LDMA_REQSEL_TO_SLOT(                                    \
1125 				    DT_INST_DMAS_CELL_BY_NAME(index, dir, slot)),                  \
1126 			.source_data_size = 1,                                                     \
1127 			.dest_data_size = 1,                                                       \
1128 			.source_burst_length = 1,                                                  \
1129 			.dest_burst_length = 1,                                                    \
1130 			.dma_callback = uart_silabs_dma_##dir##_cb,                                \
1131 		}                                                                                  \
1132 	},
1133 #define UART_DMA_CHANNEL(index, dir)                                                               \
1134 	COND_CODE_1(DT_INST_NODE_HAS_PROP(index, dmas),                                            \
1135 		 (UART_DMA_CHANNEL_INIT(index, dir)), ())
1136 #else
1137 
1138 #define UART_DMA_CHANNEL(index, dir)
1139 
1140 #endif
1141 
1142 #define SILABS_USART_IRQ_HANDLER_FUNC(idx) .irq_config_func = usart_silabs_config_func_##idx,
1143 #define SILABS_USART_IRQ_HANDLER(idx)                                                              \
1144 	static void usart_silabs_config_func_##idx(const struct device *dev)                       \
1145 	{                                                                                          \
1146 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, rx, irq),                                     \
1147 			    DT_INST_IRQ_BY_NAME(idx, rx, priority), uart_silabs_isr,               \
1148 			    DEVICE_DT_INST_GET(idx), 0);                                           \
1149 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(idx, tx, irq),                                     \
1150 			    DT_INST_IRQ_BY_NAME(idx, tx, priority), uart_silabs_isr,               \
1151 			    DEVICE_DT_INST_GET(idx), 0);                                           \
1152                                                                                                    \
1153 		irq_enable(DT_INST_IRQ_BY_NAME(idx, rx, irq));                                     \
1154 		irq_enable(DT_INST_IRQ_BY_NAME(idx, tx, irq));                                     \
1155 	}
1156 
1157 #define SILABS_USART_INIT(idx)                                                                     \
1158 	SILABS_USART_IRQ_HANDLER(idx);                                                             \
1159 	PINCTRL_DT_INST_DEFINE(idx);                                                               \
1160 	PM_DEVICE_DT_INST_DEFINE(idx, uart_silabs_pm_action);                                      \
1161                                                                                                    \
1162 	static struct uart_config uart_cfg_##idx = {                                               \
1163 		.baudrate = DT_INST_PROP(idx, current_speed),                                      \
1164 		.parity = DT_INST_ENUM_IDX(idx, parity),                                           \
1165 		.stop_bits = DT_INST_ENUM_IDX(idx, stop_bits),                                     \
1166 		.data_bits = DT_INST_ENUM_IDX(idx, data_bits),                                     \
1167 		.flow_ctrl = DT_INST_PROP(idx, hw_flow_control) ? UART_CFG_FLOW_CTRL_RTS_CTS       \
1168 								: UART_CFG_FLOW_CTRL_NONE,         \
1169 	};                                                                                         \
1170                                                                                                    \
1171 	static const struct uart_silabs_config uart_silabs_cfg_##idx = {                           \
1172 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),                                       \
1173 		.base = (USART_TypeDef *)DT_INST_REG_ADDR(idx),                                    \
1174 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)),                              \
1175 		.clock_cfg = SILABS_DT_INST_CLOCK_CFG(idx),                                        \
1176 		SILABS_USART_IRQ_HANDLER_FUNC(idx)                                                 \
1177 	};                                                                                         \
1178                                                                                                    \
1179 	static struct uart_silabs_data uart_silabs_data_##idx = {                                  \
1180 		.uart_cfg = &uart_cfg_##idx,                                                       \
1181 		UART_DMA_CHANNEL(idx, rx)                                                          \
1182 		UART_DMA_CHANNEL(idx, tx)                                                          \
1183 	};                                                                                         \
1184                                                                                                    \
1185 	DEVICE_DT_INST_DEFINE(idx, uart_silabs_init, PM_DEVICE_DT_INST_GET(idx),                   \
1186 			      &uart_silabs_data_##idx, &uart_silabs_cfg_##idx, PRE_KERNEL_1,       \
1187 			      CONFIG_SERIAL_INIT_PRIORITY, &uart_silabs_driver_api);
1188 
1189 DT_INST_FOREACH_STATUS_OKAY(SILABS_USART_INIT)
1190