blob: c89ea4c02bef48298f2a7309ab93003253a2473e [file] [log] [blame]
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001/*
2 * Copyright (c) 2016 Open-RnD Sp. z o.o.
Erwan Gouriou8c079e92016-11-14 11:53:52 +01003 * Copyright (c) 2016 Linaro Limited.
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01004 *
David B. Kinderac74d8b2017-01-18 17:01:01 -08005 * SPDX-License-Identifier: Apache-2.0
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01006 */
7
Kumar Gala989484b2020-03-24 14:28:48 -05008#define DT_DRV_COMPAT st_stm32_uart
9
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010010/**
Ilya Tagunov84cffc72018-03-20 20:44:45 +030011 * @brief Driver for UART port on STM32 family processor.
Georgij Cernysiov78eed342019-03-15 19:51:09 +010012 * @note LPUART and U(S)ART have the same base and
13 * majority of operations are performed the same way.
14 * Please validate for newly added series.
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010015 */
16
Flavio Santesb04cdcd2016-12-04 14:59:37 -060017#include <kernel.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010018#include <arch/cpu.h>
Anas Nashif5eb90ec2019-06-26 10:33:39 -040019#include <sys/__assert.h>
Kumar Galaaa2bdbe2018-10-31 12:44:45 -050020#include <soc.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010021#include <init.h>
Anas Nashifd1b27182019-06-25 15:54:01 -040022#include <drivers/uart.h>
Anas Nashif17ddd172019-06-25 15:53:47 -040023#include <drivers/clock_control.h>
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +020024#include <pm/pm.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010025
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +020026#ifdef CONFIG_UART_ASYNC_API
Francois Ramu30fd0222021-06-18 15:52:30 +020027#include <drivers/dma/dma_stm32.h>
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +020028#include <drivers/dma.h>
29#endif
30
Anas Nashif397d29d2017-06-17 11:30:47 -040031#include <linker/sections.h>
Peter Bigot0b0d2e642020-01-25 05:34:53 -060032#include <drivers/clock_control/stm32_clock_control.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010033#include "uart_stm32.h"
34
Gerard Marull-Paretase83fab32020-10-03 23:58:36 +020035#include <stm32_ll_usart.h>
36#include <stm32_ll_lpuart.h>
37
Francois Ramud3ffa8d2019-11-12 16:13:03 +010038#include <logging/log.h>
39LOG_MODULE_REGISTER(uart_stm32);
40
Kumar Galac2135f82020-05-07 12:22:26 -050041#define HAS_LPUART_1 (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), \
42 st_stm32_lpuart, okay))
Erwan Gouriou76313f02020-04-17 12:33:29 +020043
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010044/* convenience defines */
45#define DEV_CFG(dev) \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +020046 ((const struct uart_stm32_config *const)(dev)->config)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010047#define DEV_DATA(dev) \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +020048 ((struct uart_stm32_data *const)(dev)->data)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010049#define UART_STRUCT(dev) \
Erwan Gouriou8c079e92016-11-14 11:53:52 +010050 ((USART_TypeDef *)(DEV_CFG(dev))->uconf.base)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010051
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +080052#if HAS_LPUART_1
53#ifdef USART_PRESC_PRESCALER
54uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint16_t presc_idx,
55 const uint32_t baud_rate)
56{
57 uint64_t lpuartdiv;
58
59 lpuartdiv = clock_rate / LPUART_PRESCALER_TAB[presc_idx];
60 lpuartdiv *= LPUART_LPUARTDIV_FREQ_MUL;
61 lpuartdiv += baud_rate / 2;
62 lpuartdiv /= baud_rate;
63
64 return (uint32_t)lpuartdiv;
65}
66#else
67uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint32_t baud_rate)
68{
69 uint64_t lpuartdiv;
70
71 lpuartdiv = clock_rate * LPUART_LPUARTDIV_FREQ_MUL;
72 lpuartdiv += baud_rate / 2;
73 lpuartdiv /= baud_rate;
74
75 return (uint32_t)lpuartdiv;
76}
77#endif /* USART_PRESC_PRESCALER */
78#endif /* HAS_LPUART_1 */
79
Erwan Gouriou8c079e92016-11-14 11:53:52 +010080#define TIMEOUT 1000
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010081
Erwan Gourioua3de3df2021-09-14 09:27:56 +020082#ifdef CONFIG_PM
83static void uart_stm32_pm_constraint_set(const struct device *dev)
84{
85 struct uart_stm32_data *data = DEV_DATA(dev);
86
87 if (!data->pm_constraint_on) {
88 data->pm_constraint_on = true;
89 pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE);
90 }
91}
92
93static void uart_stm32_pm_constraint_release(const struct device *dev)
94{
95 struct uart_stm32_data *data = DEV_DATA(dev);
96
97 if (data->pm_constraint_on) {
98 data->pm_constraint_on = false;
99 pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE);
100 }
101}
102#endif /* CONFIG_PM */
103
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200104static inline void uart_stm32_set_baudrate(const struct device *dev,
105 uint32_t baud_rate)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800106{
107 const struct uart_stm32_config *config = DEV_CFG(dev);
108 struct uart_stm32_data *data = DEV_DATA(dev);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800109 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Erwan Gouriou69a28962019-05-20 17:15:02 +0200110
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500111 uint32_t clock_rate;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800112
113 /* Get clock rate */
Francois Ramud3ffa8d2019-11-12 16:13:03 +0100114 if (clock_control_get_rate(data->clock,
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800115 (clock_control_subsys_t *)&config->pclken,
Francois Ramud3ffa8d2019-11-12 16:13:03 +0100116 &clock_rate) < 0) {
117 LOG_ERR("Failed call clock_control_get_rate");
118 return;
119 }
Erwan Gouriou69a28962019-05-20 17:15:02 +0200120
Erwan Gouriou76313f02020-04-17 12:33:29 +0200121#if HAS_LPUART_1
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800122 if (IS_LPUART_INSTANCE(UartInstance)) {
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +0800123 uint32_t lpuartdiv;
124#ifdef USART_PRESC_PRESCALER
125 uint8_t presc_idx;
126 uint32_t presc_val;
127
128 for (presc_idx = 0; presc_idx < ARRAY_SIZE(LPUART_PRESCALER_TAB); presc_idx++) {
129 lpuartdiv = lpuartdiv_calc(clock_rate, presc_idx, baud_rate);
130 if (lpuartdiv >= LPUART_BRR_MIN_VALUE && lpuartdiv <= LPUART_BRR_MASK) {
131 break;
132 }
133 }
134
135 if (presc_idx == ARRAY_SIZE(LPUART_PRESCALER_TAB)) {
136 LOG_ERR("Unable to set %s to %d", dev->name, baud_rate);
137 return;
138 }
139
140 presc_val = presc_idx << USART_PRESC_PRESCALER_Pos;
141
142 LL_LPUART_SetPrescaler(UartInstance, presc_val);
143#else
144 lpuartdiv = lpuartdiv_calc(clock_rate, baud_rate);
145 if (lpuartdiv < LPUART_BRR_MIN_VALUE || lpuartdiv > LPUART_BRR_MASK) {
146 LOG_ERR("Unable to set %s to %d", dev->name, baud_rate);
147 return;
148 }
149#endif /* USART_PRESC_PRESCALER */
Erwan Gouriou69a28962019-05-20 17:15:02 +0200150 LL_LPUART_SetBaudRate(UartInstance,
151 clock_rate,
152#ifdef USART_PRESC_PRESCALER
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +0800153 presc_val,
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800154#endif
Erwan Gouriou69a28962019-05-20 17:15:02 +0200155 baud_rate);
156 } else {
Erwan Gouriou76313f02020-04-17 12:33:29 +0200157#endif /* HAS_LPUART_1 */
Erwan Gouriou37c7b892021-01-08 10:54:46 +0100158#ifdef USART_CR1_OVER8
159 LL_USART_SetOverSampling(UartInstance,
160 LL_USART_OVERSAMPLING_16);
161#endif
Erwan Gouriou69a28962019-05-20 17:15:02 +0200162 LL_USART_SetBaudRate(UartInstance,
163 clock_rate,
164#ifdef USART_PRESC_PRESCALER
165 LL_USART_PRESCALER_DIV1,
166#endif
167#ifdef USART_CR1_OVER8
168 LL_USART_OVERSAMPLING_16,
169#endif
170 baud_rate);
171
Erwan Gouriou76313f02020-04-17 12:33:29 +0200172#if HAS_LPUART_1
Erwan Gouriou69a28962019-05-20 17:15:02 +0200173 }
Erwan Gouriou76313f02020-04-17 12:33:29 +0200174#endif /* HAS_LPUART_1 */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800175}
176
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200177static inline void uart_stm32_set_parity(const struct device *dev,
178 uint32_t parity)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800179{
180 USART_TypeDef *UartInstance = UART_STRUCT(dev);
181
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800182 LL_USART_SetParity(UartInstance, parity);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800183}
184
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200185static inline uint32_t uart_stm32_get_parity(const struct device *dev)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800186{
187 USART_TypeDef *UartInstance = UART_STRUCT(dev);
188
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800189 return LL_USART_GetParity(UartInstance);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800190}
191
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200192static inline void uart_stm32_set_stopbits(const struct device *dev,
193 uint32_t stopbits)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800194{
195 USART_TypeDef *UartInstance = UART_STRUCT(dev);
196
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800197 LL_USART_SetStopBitsLength(UartInstance, stopbits);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800198}
199
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200200static inline uint32_t uart_stm32_get_stopbits(const struct device *dev)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800201{
202 USART_TypeDef *UartInstance = UART_STRUCT(dev);
203
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800204 return LL_USART_GetStopBitsLength(UartInstance);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800205}
206
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200207static inline void uart_stm32_set_databits(const struct device *dev,
208 uint32_t databits)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800209{
210 USART_TypeDef *UartInstance = UART_STRUCT(dev);
211
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800212 LL_USART_SetDataWidth(UartInstance, databits);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800213}
214
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200215static inline uint32_t uart_stm32_get_databits(const struct device *dev)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800216{
217 USART_TypeDef *UartInstance = UART_STRUCT(dev);
218
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800219 return LL_USART_GetDataWidth(UartInstance);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800220}
221
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200222static inline void uart_stm32_set_hwctrl(const struct device *dev,
223 uint32_t hwctrl)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100224{
225 USART_TypeDef *UartInstance = UART_STRUCT(dev);
226
227 LL_USART_SetHWFlowCtrl(UartInstance, hwctrl);
228}
229
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200230static inline uint32_t uart_stm32_get_hwctrl(const struct device *dev)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100231{
232 USART_TypeDef *UartInstance = UART_STRUCT(dev);
233
234 return LL_USART_GetHWFlowCtrl(UartInstance);
235}
236
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500237static inline uint32_t uart_stm32_cfg2ll_parity(enum uart_config_parity parity)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800238{
239 switch (parity) {
240 case UART_CFG_PARITY_ODD:
241 return LL_USART_PARITY_ODD;
242 case UART_CFG_PARITY_EVEN:
243 return LL_USART_PARITY_EVEN;
244 case UART_CFG_PARITY_NONE:
245 default:
246 return LL_USART_PARITY_NONE;
247 }
248}
249
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500250static inline enum uart_config_parity uart_stm32_ll2cfg_parity(uint32_t parity)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800251{
252 switch (parity) {
253 case LL_USART_PARITY_ODD:
254 return UART_CFG_PARITY_ODD;
255 case LL_USART_PARITY_EVEN:
256 return UART_CFG_PARITY_EVEN;
257 case LL_USART_PARITY_NONE:
258 default:
259 return UART_CFG_PARITY_NONE;
260 }
261}
262
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500263static inline uint32_t uart_stm32_cfg2ll_stopbits(enum uart_config_stop_bits sb)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800264{
265 switch (sb) {
266/* Some MCU's don't support 0.5 stop bits */
267#ifdef LL_USART_STOPBITS_0_5
268 case UART_CFG_STOP_BITS_0_5:
269 return LL_USART_STOPBITS_0_5;
270#endif /* LL_USART_STOPBITS_0_5 */
271 case UART_CFG_STOP_BITS_1:
272 return LL_USART_STOPBITS_1;
273/* Some MCU's don't support 1.5 stop bits */
274#ifdef LL_USART_STOPBITS_1_5
275 case UART_CFG_STOP_BITS_1_5:
276 return LL_USART_STOPBITS_1_5;
277#endif /* LL_USART_STOPBITS_1_5 */
278 case UART_CFG_STOP_BITS_2:
279 default:
280 return LL_USART_STOPBITS_2;
281 }
282}
283
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500284static inline enum uart_config_stop_bits uart_stm32_ll2cfg_stopbits(uint32_t sb)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800285{
286 switch (sb) {
287/* Some MCU's don't support 0.5 stop bits */
288#ifdef LL_USART_STOPBITS_0_5
289 case LL_USART_STOPBITS_0_5:
290 return UART_CFG_STOP_BITS_0_5;
291#endif /* LL_USART_STOPBITS_0_5 */
292 case LL_USART_STOPBITS_1:
293 return UART_CFG_STOP_BITS_1;
294/* Some MCU's don't support 1.5 stop bits */
295#ifdef LL_USART_STOPBITS_1_5
296 case LL_USART_STOPBITS_1_5:
297 return UART_CFG_STOP_BITS_1_5;
298#endif /* LL_USART_STOPBITS_1_5 */
299 case LL_USART_STOPBITS_2:
300 default:
301 return UART_CFG_STOP_BITS_2;
302 }
303}
304
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100305static inline uint32_t uart_stm32_cfg2ll_databits(enum uart_config_data_bits db,
306 enum uart_config_parity p)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800307{
308 switch (db) {
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100309/* Some MCU's don't support 7B or 9B datawidth */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800310#ifdef LL_USART_DATAWIDTH_7B
311 case UART_CFG_DATA_BITS_7:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100312 if (p == UART_CFG_PARITY_NONE) {
313 return LL_USART_DATAWIDTH_7B;
314 } else {
315 return LL_USART_DATAWIDTH_8B;
316 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800317#endif /* LL_USART_DATAWIDTH_7B */
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100318#ifdef LL_USART_DATAWIDTH_9B
319 case UART_CFG_DATA_BITS_9:
320 return LL_USART_DATAWIDTH_9B;
321#endif /* LL_USART_DATAWIDTH_9B */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800322 case UART_CFG_DATA_BITS_8:
323 default:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100324 if (p == UART_CFG_PARITY_NONE) {
325 return LL_USART_DATAWIDTH_8B;
326#ifdef LL_USART_DATAWIDTH_9B
327 } else {
328 return LL_USART_DATAWIDTH_9B;
329#endif
330 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800331 return LL_USART_DATAWIDTH_8B;
332 }
333}
334
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100335static inline enum uart_config_data_bits uart_stm32_ll2cfg_databits(uint32_t db,
336 uint32_t p)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800337{
338 switch (db) {
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100339/* Some MCU's don't support 7B or 9B datawidth */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800340#ifdef LL_USART_DATAWIDTH_7B
341 case LL_USART_DATAWIDTH_7B:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100342 if (p == LL_USART_PARITY_NONE) {
343 return UART_CFG_DATA_BITS_7;
344 } else {
345 return UART_CFG_DATA_BITS_6;
346 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800347#endif /* LL_USART_DATAWIDTH_7B */
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100348#ifdef LL_USART_DATAWIDTH_9B
349 case LL_USART_DATAWIDTH_9B:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100350 if (p == LL_USART_PARITY_NONE) {
351 return UART_CFG_DATA_BITS_9;
352 } else {
353 return UART_CFG_DATA_BITS_8;
354 }
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100355#endif /* LL_USART_DATAWIDTH_9B */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800356 case LL_USART_DATAWIDTH_8B:
357 default:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100358 if (p == LL_USART_PARITY_NONE) {
359 return UART_CFG_DATA_BITS_8;
360 } else {
361 return UART_CFG_DATA_BITS_7;
362 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800363 }
364}
365
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100366/**
367 * @brief Get LL hardware flow control define from
368 * Zephyr hardware flow control option.
369 * @note Supports only UART_CFG_FLOW_CTRL_RTS_CTS.
370 * @param fc: Zephyr hardware flow control option.
371 * @retval LL_USART_HWCONTROL_RTS_CTS, or LL_USART_HWCONTROL_NONE.
372 */
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500373static inline uint32_t uart_stm32_cfg2ll_hwctrl(enum uart_config_flow_control fc)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100374{
375 if (fc == UART_CFG_FLOW_CTRL_RTS_CTS) {
376 return LL_USART_HWCONTROL_RTS_CTS;
377 }
378
379 return LL_USART_HWCONTROL_NONE;
380}
381
382/**
Yannis Damigosa4b448e2020-02-06 20:36:03 +0200383 * @brief Get Zephyr hardware flow control option from
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100384 * LL hardware flow control define.
385 * @note Supports only LL_USART_HWCONTROL_RTS_CTS.
Yannis Damigosa4b448e2020-02-06 20:36:03 +0200386 * @param fc: LL hardware flow control definition.
Kumar Gala61153462020-02-06 11:30:05 -0600387 * @retval UART_CFG_FLOW_CTRL_RTS_CTS, or UART_CFG_FLOW_CTRL_NONE.
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100388 */
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500389static inline enum uart_config_flow_control uart_stm32_ll2cfg_hwctrl(uint32_t fc)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100390{
391 if (fc == LL_USART_HWCONTROL_RTS_CTS) {
392 return UART_CFG_FLOW_CTRL_RTS_CTS;
393 }
394
Kumar Gala61153462020-02-06 11:30:05 -0600395 return UART_CFG_FLOW_CTRL_NONE;
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100396}
397
Daniel Leung4e1692f2021-05-26 12:33:37 -0700398#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200399static int uart_stm32_configure(const struct device *dev,
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800400 const struct uart_config *cfg)
401{
402 struct uart_stm32_data *data = DEV_DATA(dev);
403 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500404 const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity);
405 const uint32_t stopbits = uart_stm32_cfg2ll_stopbits(cfg->stop_bits);
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100406 const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits,
407 cfg->parity);
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500408 const uint32_t flowctrl = uart_stm32_cfg2ll_hwctrl(cfg->flow_ctrl);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800409
410 /* Hardware doesn't support mark or space parity */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100411 if ((cfg->parity == UART_CFG_PARITY_MARK) ||
412 (cfg->parity == UART_CFG_PARITY_SPACE)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800413 return -ENOTSUP;
414 }
415
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100416 /* Driver does not supports parity + 9 databits */
417 if ((cfg->parity != UART_CFG_PARITY_NONE) &&
418 (cfg->data_bits == UART_CFG_DATA_BITS_9)) {
419 return -ENOTSUP;
420 }
421
Erwan Gouriou76313f02020-04-17 12:33:29 +0200422#if defined(LL_USART_STOPBITS_0_5) && HAS_LPUART_1
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800423 if (IS_LPUART_INSTANCE(UartInstance) &&
Erwan Gouriou5e561702021-02-11 09:55:38 +0100424 (cfg->stop_bits == UART_CFG_STOP_BITS_0_5)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800425 return -ENOTSUP;
426 }
427#else
Erwan Gouriou5e561702021-02-11 09:55:38 +0100428 if (cfg->stop_bits == UART_CFG_STOP_BITS_0_5) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800429 return -ENOTSUP;
430 }
431#endif
432
Erwan Gouriou76313f02020-04-17 12:33:29 +0200433#if defined(LL_USART_STOPBITS_1_5) && HAS_LPUART_1
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800434 if (IS_LPUART_INSTANCE(UartInstance) &&
Erwan Gouriou5e561702021-02-11 09:55:38 +0100435 (cfg->stop_bits == UART_CFG_STOP_BITS_1_5)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800436 return -ENOTSUP;
437 }
438#else
Erwan Gouriou5e561702021-02-11 09:55:38 +0100439 if (cfg->stop_bits == UART_CFG_STOP_BITS_1_5) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800440 return -ENOTSUP;
441 }
442#endif
443
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100444 /* Driver doesn't support 5 or 6 databits and potentially 7 or 9 */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100445 if ((cfg->data_bits == UART_CFG_DATA_BITS_5) ||
446 (cfg->data_bits == UART_CFG_DATA_BITS_6)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800447#ifndef LL_USART_DATAWIDTH_7B
Erwan Gouriou5e561702021-02-11 09:55:38 +0100448 || (cfg->data_bits == UART_CFG_DATA_BITS_7)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800449#endif /* LL_USART_DATAWIDTH_7B */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100450 || (cfg->data_bits == UART_CFG_DATA_BITS_9)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800451 return -ENOTSUP;
452 }
453
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100454 /* Driver supports only RTS CTS flow control */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100455 if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100456 if (!IS_UART_HWFLOW_INSTANCE(UartInstance) ||
457 UART_CFG_FLOW_CTRL_RTS_CTS != cfg->flow_ctrl) {
458 return -ENOTSUP;
459 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800460 }
461
462 LL_USART_Disable(UartInstance);
463
464 if (parity != uart_stm32_get_parity(dev)) {
465 uart_stm32_set_parity(dev, parity);
466 }
467
468 if (stopbits != uart_stm32_get_stopbits(dev)) {
469 uart_stm32_set_stopbits(dev, stopbits);
470 }
471
472 if (databits != uart_stm32_get_databits(dev)) {
473 uart_stm32_set_databits(dev, databits);
474 }
475
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100476 if (flowctrl != uart_stm32_get_hwctrl(dev)) {
477 uart_stm32_set_hwctrl(dev, flowctrl);
478 }
479
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800480 if (cfg->baudrate != data->baud_rate) {
481 uart_stm32_set_baudrate(dev, cfg->baudrate);
482 data->baud_rate = cfg->baudrate;
483 }
484
485 LL_USART_Enable(UartInstance);
486 return 0;
487};
488
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200489static int uart_stm32_config_get(const struct device *dev,
490 struct uart_config *cfg)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800491{
492 struct uart_stm32_data *data = DEV_DATA(dev);
493
494 cfg->baudrate = data->baud_rate;
495 cfg->parity = uart_stm32_ll2cfg_parity(uart_stm32_get_parity(dev));
496 cfg->stop_bits = uart_stm32_ll2cfg_stopbits(
497 uart_stm32_get_stopbits(dev));
498 cfg->data_bits = uart_stm32_ll2cfg_databits(
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100499 uart_stm32_get_databits(dev), uart_stm32_get_parity(dev));
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100500 cfg->flow_ctrl = uart_stm32_ll2cfg_hwctrl(
501 uart_stm32_get_hwctrl(dev));
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800502 return 0;
503}
Daniel Leung4e1692f2021-05-26 12:33:37 -0700504#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800505
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200506static int uart_stm32_poll_in(const struct device *dev, unsigned char *c)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100507{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200508 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100509
Kiril Zyapkov7a602fc2018-11-02 15:34:56 +0200510 /* Clear overrun error flag */
511 if (LL_USART_IsActiveFlag_ORE(UartInstance)) {
512 LL_USART_ClearFlag_ORE(UartInstance);
513 }
514
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200515 if (!LL_USART_IsActiveFlag_RXNE(UartInstance)) {
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100516 return -1;
517 }
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200518
519 *c = (unsigned char)LL_USART_ReceiveData8(UartInstance);
520
521 return 0;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100522}
523
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200524static void uart_stm32_poll_out(const struct device *dev,
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100525 unsigned char c)
526{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200527 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100528#ifdef CONFIG_PM
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100529 struct uart_stm32_data *data = DEV_DATA(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100530#endif
531 int key;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100532
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100533 /* Wait for TXE flag to be raised
534 * When TXE flag is raised, we lock interrupts to prevent interrupts (notably that of usart)
535 * or thread switch. Then, we can safely send our character. The character sent will be
536 * interlaced with the characters potentially send with interrupt transmission API
537 */
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100538 while (1) {
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100539 if (LL_USART_IsActiveFlag_TXE(UartInstance)) {
540 key = irq_lock();
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100541 if (LL_USART_IsActiveFlag_TXE(UartInstance)) {
542 break;
543 }
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100544 irq_unlock(key);
545 }
Anas Nashif4c322582019-06-04 10:52:23 -0400546 }
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200547
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200548#ifdef CONFIG_PM
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200549
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100550 /* If an interrupt transmission is in progress, the pm constraint is already managed by the
551 * call of uart_stm32_irq_tx_[en|dis]able
552 */
553 if (!data->tx_poll_stream_on && !data->tx_int_stream_on) {
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200554 data->tx_poll_stream_on = true;
555
556 /* Don't allow system to suspend until stream
557 * transmission has completed
558 */
559 uart_stm32_pm_constraint_set(dev);
560
561 /* Enable TC interrupt so we can release suspend
562 * constraint when done
563 */
564 LL_USART_EnableIT_TC(UartInstance);
565 }
566#endif /* CONFIG_PM */
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +0200567
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500568 LL_USART_TransmitData8(UartInstance, (uint8_t)c);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100569 irq_unlock(key);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100570}
571
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200572static int uart_stm32_err_check(const struct device *dev)
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100573{
574 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500575 uint32_t err = 0U;
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100576
577 /* Check for errors, but don't clear them here.
578 * Some SoC clear all error flags when at least
579 * one is cleared. (e.g. F4X, F1X, and F2X)
580 */
581 if (LL_USART_IsActiveFlag_ORE(UartInstance)) {
582 err |= UART_ERROR_OVERRUN;
583 }
584
585 if (LL_USART_IsActiveFlag_PE(UartInstance)) {
586 err |= UART_ERROR_PARITY;
587 }
588
589 if (LL_USART_IsActiveFlag_FE(UartInstance)) {
590 err |= UART_ERROR_FRAMING;
591 }
592
593 if (err & UART_ERROR_OVERRUN) {
594 LL_USART_ClearFlag_ORE(UartInstance);
595 }
596
597 if (err & UART_ERROR_PARITY) {
598 LL_USART_ClearFlag_PE(UartInstance);
599 }
600
601 if (err & UART_ERROR_FRAMING) {
602 LL_USART_ClearFlag_FE(UartInstance);
603 }
604
605 /* Clear noise error as well,
606 * it is not represented by the errors enum
607 */
608 LL_USART_ClearFlag_NE(UartInstance);
609
610 return err;
611}
612
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200613static inline void __uart_stm32_get_clock(const struct device *dev)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100614{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100615 struct uart_stm32_data *data = DEV_DATA(dev);
Kumar Galab275fec2021-02-11 11:49:24 -0600616 const struct device *clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100617
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100618 data->clock = clk;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100619}
620
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100621#ifdef CONFIG_UART_INTERRUPT_DRIVEN
622
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200623static int uart_stm32_fifo_fill(const struct device *dev,
624 const uint8_t *tx_data,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100625 int size)
626{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200627 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500628 uint8_t num_tx = 0U;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100629 int key;
630
631 if (!LL_USART_IsActiveFlag_TXE(UartInstance)) {
632 return num_tx;
633 }
634
635 /* Lock interrupts to prevent nested interrupts or thread switch */
636 key = irq_lock();
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100637
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200638 while ((size - num_tx > 0) &&
639 LL_USART_IsActiveFlag_TXE(UartInstance)) {
Georgij Cernysiov3de55da2019-02-06 23:31:24 +0100640 /* TXE flag will be cleared with byte write to DR|RDR register */
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100641
642 /* Send a character (8bit , parity none) */
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200643 LL_USART_TransmitData8(UartInstance, tx_data[num_tx++]);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100644 }
645
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100646 irq_unlock(key);
647
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100648 return num_tx;
649}
650
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200651static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100652 const int size)
653{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200654 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500655 uint8_t num_rx = 0U;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100656
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200657 while ((size - num_rx > 0) &&
658 LL_USART_IsActiveFlag_RXNE(UartInstance)) {
Georgij Cernysiov3de55da2019-02-06 23:31:24 +0100659 /* RXNE flag will be cleared upon read from DR|RDR register */
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100660
661 /* Receive a character (8bit , parity none) */
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200662 rx_data[num_rx++] = LL_USART_ReceiveData8(UartInstance);
Kiril Zyapkov7a602fc2018-11-02 15:34:56 +0200663
664 /* Clear overrun error flag */
665 if (LL_USART_IsActiveFlag_ORE(UartInstance)) {
666 LL_USART_ClearFlag_ORE(UartInstance);
667 }
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100668 }
Georgij Cernysiov3de55da2019-02-06 23:31:24 +0100669
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100670 return num_rx;
671}
672
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200673static void uart_stm32_irq_tx_enable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100674{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200675 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100676#ifdef CONFIG_PM
Julien D'ascenzio7b210502021-10-26 18:03:31 +0200677 struct uart_stm32_data *data = DEV_DATA(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100678 int key;
679#endif
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100680
681#ifdef CONFIG_PM
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100682 key = irq_lock();
Julien D'ascenzio7b210502021-10-26 18:03:31 +0200683 data->tx_poll_stream_on = false;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100684 data->tx_int_stream_on = true;
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200685 uart_stm32_pm_constraint_set(dev);
686#endif
Julien D'ascenzio7b210502021-10-26 18:03:31 +0200687 LL_USART_EnableIT_TC(UartInstance);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100688
689#ifdef CONFIG_PM
690 irq_unlock(key);
691#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100692}
693
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200694static void uart_stm32_irq_tx_disable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100695{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200696 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100697#ifdef CONFIG_PM
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100698 struct uart_stm32_data *data = DEV_DATA(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100699 int key;
700
701 key = irq_lock();
702#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100703
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200704 LL_USART_DisableIT_TC(UartInstance);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200705
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100706#ifdef CONFIG_PM
707 data->tx_int_stream_on = false;
708 uart_stm32_pm_constraint_release(dev);
709#endif
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100710
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200711#ifdef CONFIG_PM
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100712 irq_unlock(key);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200713#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100714}
715
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200716static int uart_stm32_irq_tx_ready(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100717{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200718 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100719
Nicolas VINCENTeb534d32021-01-08 15:59:53 +0100720 return LL_USART_IsActiveFlag_TXE(UartInstance) &&
721 LL_USART_IsEnabledIT_TC(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100722}
723
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200724static int uart_stm32_irq_tx_complete(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100725{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200726 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100727
Tommy Vestermark22be8642019-09-25 19:57:35 +0200728 return LL_USART_IsActiveFlag_TC(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100729}
730
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200731static void uart_stm32_irq_rx_enable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100732{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200733 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100734
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200735 LL_USART_EnableIT_RXNE(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100736}
737
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200738static void uart_stm32_irq_rx_disable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100739{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200740 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100741
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200742 LL_USART_DisableIT_RXNE(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100743}
744
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200745static int uart_stm32_irq_rx_ready(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100746{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200747 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100748
Erwan Gouriou2b0311d2021-01-15 14:10:40 +0100749 return LL_USART_IsActiveFlag_RXNE(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100750}
751
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200752static void uart_stm32_irq_err_enable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100753{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200754 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100755
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100756 /* Enable FE, ORE interruptions */
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200757 LL_USART_EnableIT_ERROR(UartInstance);
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300758#if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT)
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100759 /* Enable Line break detection */
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300760 if (IS_UART_LIN_INSTANCE(UartInstance)) {
761 LL_USART_EnableIT_LBD(UartInstance);
762 }
Maciej Debskieaff37e2017-08-09 11:23:04 +0200763#endif
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100764 /* Enable parity error interruption */
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200765 LL_USART_EnableIT_PE(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100766}
767
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200768static void uart_stm32_irq_err_disable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100769{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200770 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100771
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300772 /* Disable FE, ORE interruptions */
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200773 LL_USART_DisableIT_ERROR(UartInstance);
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300774#if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT)
775 /* Disable Line break detection */
776 if (IS_UART_LIN_INSTANCE(UartInstance)) {
777 LL_USART_DisableIT_LBD(UartInstance);
778 }
Maciej Debskieaff37e2017-08-09 11:23:04 +0200779#endif
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300780 /* Disable parity error interruption */
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200781 LL_USART_DisableIT_PE(UartInstance);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100782}
783
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200784static int uart_stm32_irq_is_pending(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100785{
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200786 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100787
Erwan Gouriou222bc602017-12-05 13:46:13 -0600788 return ((LL_USART_IsActiveFlag_RXNE(UartInstance) &&
789 LL_USART_IsEnabledIT_RXNE(UartInstance)) ||
Benoit Leforestier2a1c94c2018-11-13 15:26:06 +0100790 (LL_USART_IsActiveFlag_TC(UartInstance) &&
791 LL_USART_IsEnabledIT_TC(UartInstance)));
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100792}
793
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200794static int uart_stm32_irq_update(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100795{
796 return 1;
797}
798
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200799static void uart_stm32_irq_callback_set(const struct device *dev,
Paul Sokolovsky57286af2018-07-16 21:12:26 +0300800 uart_irq_callback_user_data_t cb,
801 void *cb_data)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100802{
803 struct uart_stm32_data *data = DEV_DATA(dev);
804
805 data->user_cb = cb;
Paul Sokolovsky57286af2018-07-16 21:12:26 +0300806 data->user_data = cb_data;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100807}
808
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200809#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
810
811#ifdef CONFIG_UART_ASYNC_API
812
813static inline void async_user_callback(struct uart_stm32_data *data,
814 struct uart_event *event)
815{
816 if (data->async_cb) {
817 data->async_cb(data->uart_dev, event, data->async_user_data);
818 }
819}
820
821static inline void async_evt_rx_rdy(struct uart_stm32_data *data)
822{
823 LOG_DBG("rx_rdy: (%d %d)", data->dma_rx.offset, data->dma_rx.counter);
824
825 struct uart_event event = {
826 .type = UART_RX_RDY,
827 .data.rx.buf = data->dma_rx.buffer,
828 .data.rx.len = data->dma_rx.counter - data->dma_rx.offset,
829 .data.rx.offset = data->dma_rx.offset
830 };
831
Alexander Shuklin6831b8b2021-02-04 12:00:49 +0300832 /* update the current pos for new data */
833 data->dma_rx.offset = data->dma_rx.counter;
834
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200835 /* send event only for new data */
836 if (event.data.rx.len > 0) {
837 async_user_callback(data, &event);
838 }
839}
840
841static inline void async_evt_rx_err(struct uart_stm32_data *data, int err_code)
842{
843 LOG_DBG("rx error: %d", err_code);
844
845 struct uart_event event = {
846 .type = UART_RX_STOPPED,
847 .data.rx_stop.reason = err_code,
848 .data.rx_stop.data.len = data->dma_rx.counter,
849 .data.rx_stop.data.offset = 0,
850 .data.rx_stop.data.buf = data->dma_rx.buffer
851 };
852
853 async_user_callback(data, &event);
854}
855
856static inline void async_evt_tx_done(struct uart_stm32_data *data)
857{
858 LOG_DBG("tx done: %d", data->dma_tx.counter);
859
860 struct uart_event event = {
861 .type = UART_TX_DONE,
862 .data.tx.buf = data->dma_tx.buffer,
863 .data.tx.len = data->dma_tx.counter
864 };
865
866 /* Reset tx buffer */
867 data->dma_tx.buffer_length = 0;
868 data->dma_tx.counter = 0;
869
870 async_user_callback(data, &event);
871}
872
873static inline void async_evt_tx_abort(struct uart_stm32_data *data)
874{
875 LOG_DBG("tx abort: %d", data->dma_tx.counter);
876
877 struct uart_event event = {
878 .type = UART_TX_ABORTED,
879 .data.tx.buf = data->dma_tx.buffer,
880 .data.tx.len = data->dma_tx.counter
881 };
882
883 /* Reset tx buffer */
884 data->dma_tx.buffer_length = 0;
885 data->dma_tx.counter = 0;
886
887 async_user_callback(data, &event);
888}
889
890static inline void async_evt_rx_buf_request(struct uart_stm32_data *data)
891{
892 struct uart_event evt = {
893 .type = UART_RX_BUF_REQUEST,
894 };
895
896 async_user_callback(data, &evt);
897}
898
899static inline void async_evt_rx_buf_release(struct uart_stm32_data *data)
900{
901 struct uart_event evt = {
902 .type = UART_RX_BUF_RELEASED,
903 .data.rx_buf.buf = data->dma_rx.buffer,
904 };
905
906 async_user_callback(data, &evt);
907}
908
Francois Ramu962d6b12021-04-08 12:09:58 +0200909static inline void async_timer_start(struct k_work_delayable *work,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200910 int32_t timeout)
911{
Krzysztof Chruscinskic590b352021-10-01 15:47:40 +0200912 if ((timeout != SYS_FOREVER_US) && (timeout != 0)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200913 /* start timer */
Krzysztof Chruscinskic590b352021-10-01 15:47:40 +0200914 LOG_DBG("async timer started for %d us", timeout);
915 k_work_reschedule(work, K_USEC(timeout));
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200916 }
917}
918
919static void uart_stm32_dma_rx_flush(const struct device *dev)
920{
921 struct dma_status stat;
922 struct uart_stm32_data *data = DEV_DATA(dev);
923
Erwan Gouriou13c23512021-03-01 11:59:57 +0100924 if (dma_get_status(data->dma_rx.dma_dev,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200925 data->dma_rx.dma_channel, &stat) == 0) {
926 size_t rx_rcv_len = data->dma_rx.buffer_length -
927 stat.pending_length;
928 if (rx_rcv_len > data->dma_rx.offset) {
929 data->dma_rx.counter = rx_rcv_len;
930
931 async_evt_rx_rdy(data);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200932 }
933 }
934}
935
936#endif /* CONFIG_UART_ASYNC_API */
937
Erwan Gouriou79ff6452021-09-21 09:34:09 +0200938#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || \
939 defined(CONFIG_UART_ASYNC_API) || \
940 defined(CONFIG_PM)
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200941
Tomasz Bursztyka4dcfb552020-06-17 14:58:56 +0200942static void uart_stm32_isr(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100943{
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100944 struct uart_stm32_data *data = DEV_DATA(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200945#if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API)
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +0200946 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200947#endif
948
949#ifdef CONFIG_PM
950 if (LL_USART_IsEnabledIT_TC(UartInstance) &&
951 LL_USART_IsActiveFlag_TC(UartInstance)) {
952
953 if (data->tx_poll_stream_on) {
954 /* A poll stream transmition just completed,
955 * allow system to suspend
956 */
957 LL_USART_DisableIT_TC(UartInstance);
958 data->tx_poll_stream_on = false;
959 uart_stm32_pm_constraint_release(dev);
960 }
961 /* Stream transmition was either async or IRQ based,
962 * constraint will be released at the same time TC IT
963 * is disabled
964 */
965 }
966#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100967
Shlomi Vaknin1b4f7e52021-05-17 23:06:51 +0300968#ifdef CONFIG_UART_INTERRUPT_DRIVEN
969 if (data->user_cb) {
970 data->user_cb(dev, data->user_data);
971 }
972#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
973
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200974#ifdef CONFIG_UART_ASYNC_API
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200975 if (LL_USART_IsEnabledIT_IDLE(UartInstance) &&
976 LL_USART_IsActiveFlag_IDLE(UartInstance)) {
977
978 LL_USART_ClearFlag_IDLE(UartInstance);
979
980 LOG_DBG("idle interrupt occurred");
981
982 /* Start the RX timer */
983 async_timer_start(&data->dma_rx.timeout_work,
984 data->dma_rx.timeout);
985
986 if (data->dma_rx.timeout == 0) {
987 uart_stm32_dma_rx_flush(dev);
988 }
Zisis Adamos7235b092021-03-30 12:20:46 +0200989 } else if (LL_USART_IsEnabledIT_TC(UartInstance) &&
Francois Ramu95e2c392021-10-26 11:39:57 +0200990 LL_USART_IsActiveFlag_TC(UartInstance)) {
Zisis Adamos7235b092021-03-30 12:20:46 +0200991
992 LL_USART_DisableIT_TC(UartInstance);
993 LL_USART_ClearFlag_TC(UartInstance);
994 /* Generate TX_DONE event when transmission is done */
995 async_evt_tx_done(data);
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +0200996
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200997#ifdef CONFIG_PM
998 uart_stm32_pm_constraint_release(dev);
999#endif
Francois Ramu95e2c392021-10-26 11:39:57 +02001000 } else if (LL_USART_IsEnabledIT_RXNE(UartInstance) &&
1001 LL_USART_IsActiveFlag_RXNE(UartInstance)) {
Francois Ramucf606392021-11-08 11:43:53 +01001002#ifdef USART_SR_RXNE
1003 /* clear the RXNE flag, because Rx data was not read */
1004 LL_USART_ClearFlag_RXNE(UartInstance);
1005#else
Francois Ramu95e2c392021-10-26 11:39:57 +02001006 /* clear the RXNE by flushing the fifo, because Rx data was not read */
1007 LL_USART_RequestRxDataFlush(UartInstance);
Francois Ramucf606392021-11-08 11:43:53 +01001008#endif /* USART_SR_RXNE */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001009 }
1010
1011 /* Clear errors */
1012 uart_stm32_err_check(dev);
1013#endif /* CONFIG_UART_ASYNC_API */
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001014}
Erwan Gouriou79ff6452021-09-21 09:34:09 +02001015#endif /* CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API || CONFIG_PM */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001016
1017#ifdef CONFIG_UART_ASYNC_API
1018
1019static int uart_stm32_async_callback_set(const struct device *dev,
1020 uart_callback_t callback,
1021 void *user_data)
1022{
1023 struct uart_stm32_data *data = DEV_DATA(dev);
1024
1025 data->async_cb = callback;
1026 data->async_user_data = user_data;
1027
1028 return 0;
1029}
1030
1031static inline void uart_stm32_dma_tx_enable(const struct device *dev)
1032{
1033 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1034
1035 LL_USART_EnableDMAReq_TX(UartInstance);
1036}
1037
1038static inline void uart_stm32_dma_tx_disable(const struct device *dev)
1039{
1040 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1041
1042 LL_USART_DisableDMAReq_TX(UartInstance);
1043}
1044
1045static inline void uart_stm32_dma_rx_enable(const struct device *dev)
1046{
1047 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1048 struct uart_stm32_data *data = DEV_DATA(dev);
1049
1050 LL_USART_EnableDMAReq_RX(UartInstance);
1051
1052 data->dma_rx.enabled = true;
1053}
1054
1055static inline void uart_stm32_dma_rx_disable(const struct device *dev)
1056{
1057 struct uart_stm32_data *data = DEV_DATA(dev);
1058
1059 data->dma_rx.enabled = false;
1060}
1061
1062static int uart_stm32_async_rx_disable(const struct device *dev)
1063{
1064 struct uart_stm32_data *data = DEV_DATA(dev);
1065 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1066 struct uart_event disabled_event = {
1067 .type = UART_RX_DISABLED
1068 };
1069
1070 if (!data->dma_rx.enabled) {
1071 async_user_callback(data, &disabled_event);
1072 return -EFAULT;
1073 }
1074
1075 LL_USART_DisableIT_IDLE(UartInstance);
1076
1077 uart_stm32_dma_rx_flush(dev);
1078
1079 async_evt_rx_buf_release(data);
1080
1081 uart_stm32_dma_rx_disable(dev);
1082
Francois Ramu962d6b12021-04-08 12:09:58 +02001083 (void)k_work_cancel_delayable(&data->dma_rx.timeout_work);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001084
Erwan Gouriou13c23512021-03-01 11:59:57 +01001085 dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001086
1087 data->rx_next_buffer = NULL;
1088 data->rx_next_buffer_len = 0;
1089
Francois Ramu95e2c392021-10-26 11:39:57 +02001090 /* When async rx is disabled, enable interruptable instance of uart to function normally*/
Manojkumar Subramaniamd79d26f2021-08-23 02:04:05 +08001091 LL_USART_EnableIT_RXNE(UartInstance);
1092
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001093 LOG_DBG("rx: disabled");
1094
1095 async_user_callback(data, &disabled_event);
1096
1097 return 0;
1098}
1099
1100void uart_stm32_dma_tx_cb(const struct device *dma_dev, void *user_data,
1101 uint32_t channel, int status)
1102{
1103 const struct device *uart_dev = user_data;
1104 struct uart_stm32_data *data = DEV_DATA(uart_dev);
1105 struct dma_status stat;
1106 unsigned int key = irq_lock();
1107
1108 /* Disable TX */
1109 uart_stm32_dma_tx_disable(uart_dev);
1110
Francois Ramu962d6b12021-04-08 12:09:58 +02001111 (void)k_work_cancel_delayable(&data->dma_tx.timeout_work);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001112
Erwan Gouriou13c23512021-03-01 11:59:57 +01001113 if (!dma_get_status(data->dma_tx.dma_dev,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001114 data->dma_tx.dma_channel, &stat)) {
1115 data->dma_tx.counter = data->dma_tx.buffer_length -
1116 stat.pending_length;
1117 }
1118
Prema Jonathan van Win76dee392021-05-03 11:24:38 +03001119 data->dma_tx.buffer_length = 0;
1120
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001121 irq_unlock(key);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001122}
1123
1124static void uart_stm32_dma_replace_buffer(const struct device *dev)
1125{
1126 struct uart_stm32_data *data = DEV_DATA(dev);
1127
1128 /* Replace the buffer and relod the DMA */
1129 LOG_DBG("Replacing RX buffer: %d", data->rx_next_buffer_len);
1130
1131 /* reload DMA */
1132 data->dma_rx.offset = 0;
1133 data->dma_rx.counter = 0;
1134 data->dma_rx.buffer = data->rx_next_buffer;
1135 data->dma_rx.buffer_length = data->rx_next_buffer_len;
1136 data->dma_rx.blk_cfg.block_size = data->dma_rx.buffer_length;
1137 data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer;
1138 data->rx_next_buffer = NULL;
1139 data->rx_next_buffer_len = 0;
1140
Erwan Gouriou13c23512021-03-01 11:59:57 +01001141 dma_reload(data->dma_rx.dma_dev, data->dma_rx.dma_channel,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001142 data->dma_rx.blk_cfg.source_address,
1143 data->dma_rx.blk_cfg.dest_address,
1144 data->dma_rx.blk_cfg.block_size);
1145
Erwan Gouriou13c23512021-03-01 11:59:57 +01001146 dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001147
1148 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1149
1150 LL_USART_ClearFlag_IDLE(UartInstance);
1151
1152 /* Request next buffer */
1153 async_evt_rx_buf_request(data);
1154}
1155
1156void uart_stm32_dma_rx_cb(const struct device *dma_dev, void *user_data,
1157 uint32_t channel, int status)
1158{
1159 const struct device *uart_dev = user_data;
1160 struct uart_stm32_data *data = DEV_DATA(uart_dev);
1161
1162 if (status != 0) {
1163 async_evt_rx_err(data, status);
1164 return;
1165 }
1166
Francois Ramu962d6b12021-04-08 12:09:58 +02001167 (void)k_work_cancel_delayable(&data->dma_rx.timeout_work);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001168
1169 /* true since this functions occurs when buffer if full */
1170 data->dma_rx.counter = data->dma_rx.buffer_length;
1171
1172 async_evt_rx_rdy(data);
1173
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001174 if (data->rx_next_buffer != NULL) {
1175 async_evt_rx_buf_release(data);
1176
1177 /* replace the buffer when the current
1178 * is full and not the same as the next
1179 * one.
1180 */
1181 uart_stm32_dma_replace_buffer(uart_dev);
1182 } else {
1183 /* Buffer full without valid next buffer,
1184 * an UART_RX_DISABLED event must be generated,
1185 * but uart_stm32_async_rx_disable() cannot be
1186 * called in ISR context. So force the RX timeout
1187 * to minimum value and let the RX timeout to do the job.
1188 */
Francois Ramu962d6b12021-04-08 12:09:58 +02001189 k_work_reschedule(&data->dma_rx.timeout_work, K_TICKS(1));
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001190 }
1191}
1192
1193static int uart_stm32_async_tx(const struct device *dev,
1194 const uint8_t *tx_data, size_t buf_size, int32_t timeout)
1195{
1196 struct uart_stm32_data *data = DEV_DATA(dev);
1197 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1198 int ret;
1199
Erwan Gouriou13c23512021-03-01 11:59:57 +01001200 if (data->dma_tx.dma_dev == NULL) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001201 return -ENODEV;
1202 }
1203
1204 if (data->dma_tx.buffer_length != 0) {
1205 return -EBUSY;
1206 }
1207
1208 data->dma_tx.buffer = (uint8_t *)tx_data;
1209 data->dma_tx.buffer_length = buf_size;
1210 data->dma_tx.timeout = timeout;
1211
1212 LOG_DBG("tx: l=%d", data->dma_tx.buffer_length);
1213
Zisis Adamos7235b092021-03-30 12:20:46 +02001214 /* Clear TC flag */
1215 LL_USART_ClearFlag_TC(UartInstance);
1216
1217 /* Enable TC interrupt so we can signal correct TX done */
1218 LL_USART_EnableIT_TC(UartInstance);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001219
1220 /* set source address */
1221 data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.buffer;
1222 data->dma_tx.blk_cfg.block_size = data->dma_tx.buffer_length;
1223
Erwan Gouriou13c23512021-03-01 11:59:57 +01001224 ret = dma_config(data->dma_tx.dma_dev, data->dma_tx.dma_channel,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001225 &data->dma_tx.dma_cfg);
1226
1227 if (ret != 0) {
1228 LOG_ERR("dma tx config error!");
1229 return -EINVAL;
1230 }
1231
Erwan Gouriou13c23512021-03-01 11:59:57 +01001232 if (dma_start(data->dma_tx.dma_dev, data->dma_tx.dma_channel)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001233 LOG_ERR("UART err: TX DMA start failed!");
1234 return -EFAULT;
1235 }
1236
1237 /* Start TX timer */
1238 async_timer_start(&data->dma_tx.timeout_work, data->dma_tx.timeout);
1239
Erwan Gourioua3de3df2021-09-14 09:27:56 +02001240#ifdef CONFIG_PM
Erwan Gouriou79ff6452021-09-21 09:34:09 +02001241
1242 /* Do not allow system to suspend until transmission has completed */
Erwan Gourioua3de3df2021-09-14 09:27:56 +02001243 uart_stm32_pm_constraint_set(dev);
1244#endif
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001245
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001246 /* Enable TX DMA requests */
1247 uart_stm32_dma_tx_enable(dev);
1248
1249 return 0;
1250}
1251
1252static int uart_stm32_async_rx_enable(const struct device *dev,
1253 uint8_t *rx_buf, size_t buf_size, int32_t timeout)
1254{
1255 struct uart_stm32_data *data = DEV_DATA(dev);
1256 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1257 int ret;
1258
Erwan Gouriou13c23512021-03-01 11:59:57 +01001259 if (data->dma_rx.dma_dev == NULL) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001260 return -ENODEV;
1261 }
1262
1263 if (data->dma_rx.enabled) {
1264 LOG_WRN("RX was already enabled");
1265 return -EBUSY;
1266 }
1267
1268 data->dma_rx.offset = 0;
1269 data->dma_rx.buffer = rx_buf;
1270 data->dma_rx.buffer_length = buf_size;
1271 data->dma_rx.counter = 0;
1272 data->dma_rx.timeout = timeout;
1273
1274 /* Disable RX interrupts to let DMA to handle it */
1275 LL_USART_DisableIT_RXNE(UartInstance);
1276
1277 data->dma_rx.blk_cfg.block_size = buf_size;
1278 data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer;
1279
Erwan Gouriou13c23512021-03-01 11:59:57 +01001280 ret = dma_config(data->dma_rx.dma_dev, data->dma_rx.dma_channel,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001281 &data->dma_rx.dma_cfg);
1282
1283 if (ret != 0) {
1284 LOG_ERR("UART ERR: RX DMA config failed!");
1285 return -EINVAL;
1286 }
1287
Erwan Gouriou13c23512021-03-01 11:59:57 +01001288 if (dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001289 LOG_ERR("UART ERR: RX DMA start failed!");
1290 return -EFAULT;
1291 }
1292
1293 /* Enable RX DMA requests */
1294 uart_stm32_dma_rx_enable(dev);
1295
1296 /* Enable IRQ IDLE to define the end of a
1297 * RX DMA transaction.
1298 */
1299 LL_USART_ClearFlag_IDLE(UartInstance);
1300 LL_USART_EnableIT_IDLE(UartInstance);
1301
1302 LL_USART_EnableIT_ERROR(UartInstance);
1303
1304 /* Request next buffer */
1305 async_evt_rx_buf_request(data);
1306
1307 LOG_DBG("async rx enabled");
1308
1309 return ret;
1310}
1311
1312static int uart_stm32_async_tx_abort(const struct device *dev)
1313{
1314 struct uart_stm32_data *data = DEV_DATA(dev);
1315 size_t tx_buffer_length = data->dma_tx.buffer_length;
1316 struct dma_status stat;
1317
1318 if (tx_buffer_length == 0) {
1319 return -EFAULT;
1320 }
1321
Francois Ramu962d6b12021-04-08 12:09:58 +02001322 (void)k_work_cancel_delayable(&data->dma_tx.timeout_work);
Erwan Gouriou13c23512021-03-01 11:59:57 +01001323 if (!dma_get_status(data->dma_tx.dma_dev,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001324 data->dma_tx.dma_channel, &stat)) {
1325 data->dma_tx.counter = tx_buffer_length - stat.pending_length;
1326 }
1327
Erwan Gouriou13c23512021-03-01 11:59:57 +01001328 dma_stop(data->dma_tx.dma_dev, data->dma_tx.dma_channel);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001329 async_evt_tx_abort(data);
1330
1331 return 0;
1332}
1333
1334static void uart_stm32_async_rx_timeout(struct k_work *work)
1335{
1336 struct uart_dma_stream *rx_stream = CONTAINER_OF(work,
1337 struct uart_dma_stream, timeout_work);
1338 struct uart_stm32_data *data = CONTAINER_OF(rx_stream,
1339 struct uart_stm32_data, dma_rx);
1340 const struct device *dev = data->uart_dev;
1341
1342 LOG_DBG("rx timeout");
1343
1344 if (data->dma_rx.counter == data->dma_rx.buffer_length) {
1345 uart_stm32_async_rx_disable(dev);
1346 } else {
1347 uart_stm32_dma_rx_flush(dev);
1348 }
1349}
1350
1351static void uart_stm32_async_tx_timeout(struct k_work *work)
1352{
1353 struct uart_dma_stream *tx_stream = CONTAINER_OF(work,
1354 struct uart_dma_stream, timeout_work);
1355 struct uart_stm32_data *data = CONTAINER_OF(tx_stream,
1356 struct uart_stm32_data, dma_tx);
1357 const struct device *dev = data->uart_dev;
1358
1359 uart_stm32_async_tx_abort(dev);
1360
1361 LOG_DBG("tx: async timeout");
1362}
1363
1364static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf,
1365 size_t len)
1366{
1367 struct uart_stm32_data *data = DEV_DATA(dev);
1368
1369 LOG_DBG("replace buffer (%d)", len);
1370 data->rx_next_buffer = buf;
1371 data->rx_next_buffer_len = len;
1372
1373 return 0;
1374}
1375
1376static int uart_stm32_async_init(const struct device *dev)
1377{
1378 struct uart_stm32_data *data = DEV_DATA(dev);
1379 USART_TypeDef *UartInstance = UART_STRUCT(dev);
1380
1381 data->uart_dev = dev;
1382
Erwan Gouriou13c23512021-03-01 11:59:57 +01001383 if (data->dma_rx.dma_dev != NULL) {
1384 if (!device_is_ready(data->dma_rx.dma_dev)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001385 return -ENODEV;
1386 }
1387 }
1388
Erwan Gouriou13c23512021-03-01 11:59:57 +01001389 if (data->dma_tx.dma_dev != NULL) {
1390 if (!device_is_ready(data->dma_rx.dma_dev)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001391 return -ENODEV;
1392 }
1393 }
1394
1395 /* Disable both TX and RX DMA requests */
1396 uart_stm32_dma_rx_disable(dev);
1397 uart_stm32_dma_tx_disable(dev);
1398
Francois Ramu962d6b12021-04-08 12:09:58 +02001399 k_work_init_delayable(&data->dma_rx.timeout_work,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001400 uart_stm32_async_rx_timeout);
Francois Ramu962d6b12021-04-08 12:09:58 +02001401 k_work_init_delayable(&data->dma_tx.timeout_work,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001402 uart_stm32_async_tx_timeout);
1403
1404 /* Configure dma rx config */
1405 memset(&data->dma_rx.blk_cfg, 0, sizeof(data->dma_rx.blk_cfg));
1406
1407#if defined(CONFIG_SOC_SERIES_STM32F1X) || \
1408 defined(CONFIG_SOC_SERIES_STM32F2X) || \
1409 defined(CONFIG_SOC_SERIES_STM32F4X) || \
1410 defined(CONFIG_SOC_SERIES_STM32L1X)
1411 data->dma_rx.blk_cfg.source_address =
1412 LL_USART_DMA_GetRegAddr(UartInstance);
1413#else
1414 data->dma_rx.blk_cfg.source_address =
1415 LL_USART_DMA_GetRegAddr(UartInstance,
1416 LL_USART_DMA_REG_DATA_RECEIVE);
1417#endif
1418
1419 data->dma_rx.blk_cfg.dest_address = 0; /* dest not ready */
1420
1421 if (data->dma_rx.src_addr_increment) {
1422 data->dma_rx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1423 } else {
1424 data->dma_rx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1425 }
1426
1427 if (data->dma_rx.dst_addr_increment) {
1428 data->dma_rx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1429 } else {
1430 data->dma_rx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1431 }
1432
1433 /* RX disable circular buffer */
1434 data->dma_rx.blk_cfg.source_reload_en = 0;
1435 data->dma_rx.blk_cfg.dest_reload_en = 0;
1436 data->dma_rx.blk_cfg.fifo_mode_control = data->dma_rx.fifo_threshold;
1437
1438 data->dma_rx.dma_cfg.head_block = &data->dma_rx.blk_cfg;
1439 data->dma_rx.dma_cfg.user_data = (void *)dev;
1440 data->rx_next_buffer = NULL;
1441 data->rx_next_buffer_len = 0;
1442
1443 /* Configure dma tx config */
1444 memset(&data->dma_tx.blk_cfg, 0, sizeof(data->dma_tx.blk_cfg));
1445
1446#if defined(CONFIG_SOC_SERIES_STM32F1X) || \
1447 defined(CONFIG_SOC_SERIES_STM32F2X) || \
1448 defined(CONFIG_SOC_SERIES_STM32F4X) || \
1449 defined(CONFIG_SOC_SERIES_STM32L1X)
1450 data->dma_tx.blk_cfg.dest_address =
1451 LL_USART_DMA_GetRegAddr(UartInstance);
1452#else
1453 data->dma_tx.blk_cfg.dest_address =
1454 LL_USART_DMA_GetRegAddr(UartInstance,
1455 LL_USART_DMA_REG_DATA_TRANSMIT);
1456#endif
1457
1458 data->dma_tx.blk_cfg.source_address = 0; /* not ready */
1459
1460 if (data->dma_tx.src_addr_increment) {
1461 data->dma_tx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1462 } else {
1463 data->dma_tx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1464 }
1465
1466 if (data->dma_tx.dst_addr_increment) {
1467 data->dma_tx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1468 } else {
1469 data->dma_tx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1470 }
1471
1472 data->dma_tx.blk_cfg.fifo_mode_control = data->dma_tx.fifo_threshold;
1473
1474 data->dma_tx.dma_cfg.head_block = &data->dma_tx.blk_cfg;
1475 data->dma_tx.dma_cfg.user_data = (void *)dev;
1476
1477 return 0;
1478}
1479
1480#endif /* CONFIG_UART_ASYNC_API */
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001481
Marcus Shawcroftd3ea5392016-10-24 08:38:49 +01001482static const struct uart_driver_api uart_stm32_driver_api = {
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001483 .poll_in = uart_stm32_poll_in,
1484 .poll_out = uart_stm32_poll_out,
Georgij Cernysiovc74c1312019-02-14 10:50:19 +01001485 .err_check = uart_stm32_err_check,
Daniel Leung4e1692f2021-05-26 12:33:37 -07001486#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
Pushpal Sidhuacd0e252019-01-07 13:52:24 -08001487 .configure = uart_stm32_configure,
1488 .config_get = uart_stm32_config_get,
Daniel Leung4e1692f2021-05-26 12:33:37 -07001489#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001490#ifdef CONFIG_UART_INTERRUPT_DRIVEN
1491 .fifo_fill = uart_stm32_fifo_fill,
1492 .fifo_read = uart_stm32_fifo_read,
1493 .irq_tx_enable = uart_stm32_irq_tx_enable,
1494 .irq_tx_disable = uart_stm32_irq_tx_disable,
1495 .irq_tx_ready = uart_stm32_irq_tx_ready,
Paul Sokolovsky0fdc9b52017-05-11 17:57:29 +03001496 .irq_tx_complete = uart_stm32_irq_tx_complete,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001497 .irq_rx_enable = uart_stm32_irq_rx_enable,
1498 .irq_rx_disable = uart_stm32_irq_rx_disable,
1499 .irq_rx_ready = uart_stm32_irq_rx_ready,
1500 .irq_err_enable = uart_stm32_irq_err_enable,
1501 .irq_err_disable = uart_stm32_irq_err_disable,
1502 .irq_is_pending = uart_stm32_irq_is_pending,
1503 .irq_update = uart_stm32_irq_update,
1504 .irq_callback_set = uart_stm32_irq_callback_set,
1505#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001506#ifdef CONFIG_UART_ASYNC_API
1507 .callback_set = uart_stm32_async_callback_set,
1508 .tx = uart_stm32_async_tx,
1509 .tx_abort = uart_stm32_async_tx_abort,
1510 .rx_enable = uart_stm32_async_rx_enable,
1511 .rx_disable = uart_stm32_async_rx_disable,
1512 .rx_buf_rsp = uart_stm32_async_rx_buf_rsp,
1513#endif /* CONFIG_UART_ASYNC_API */
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001514};
1515
1516/**
1517 * @brief Initialize UART channel
1518 *
1519 * This routine is called to reset the chip in a quiescent state.
1520 * It is assumed that this function is called only once per UART.
1521 *
1522 * @param dev UART device struct
1523 *
1524 * @return 0
1525 */
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +02001526static int uart_stm32_init(const struct device *dev)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001527{
Erwan Gouriou8c079e92016-11-14 11:53:52 +01001528 const struct uart_stm32_config *config = DEV_CFG(dev);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001529 struct uart_stm32_data *data = DEV_DATA(dev);
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001530 USART_TypeDef *UartInstance = UART_STRUCT(dev);
Kumar Galaa1b77fd2020-05-27 11:26:57 -05001531 uint32_t ll_parity;
1532 uint32_t ll_datawidth;
Erwan Gouriou0b9c5842020-10-16 17:20:00 +02001533 int err;
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001534
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001535 __uart_stm32_get_clock(dev);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001536 /* enable clock */
Erwan Gouriou9062e972018-12-07 11:09:28 +01001537 if (clock_control_on(data->clock,
1538 (clock_control_subsys_t *)&config->pclken) != 0) {
1539 return -EIO;
1540 }
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001541
Erwan Gouriou252a6232020-06-05 10:57:52 +02001542 /* Configure dt provided device signals when available */
Gerard Marull-Paretas21a27192021-09-07 16:39:45 +02001543 err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
Erwan Gouriou0b9c5842020-10-16 17:20:00 +02001544 if (err < 0) {
1545 return err;
Erwan Gouriou252a6232020-06-05 10:57:52 +02001546 }
1547
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001548 LL_USART_Disable(UartInstance);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001549
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001550 /* TX/RX direction */
1551 LL_USART_SetTransferDirection(UartInstance,
1552 LL_USART_DIRECTION_TX_RX);
1553
Pauli Salmenrinne30003ff2020-03-18 13:40:21 +02001554 /* Determine the datawidth and parity. If we use other parity than
1555 * 'none' we must use datawidth = 9 (to get 8 databit + 1 parity bit).
1556 */
1557 if (config->parity == 2) {
1558 /* 8 databit, 1 parity bit, parity even */
1559 ll_parity = LL_USART_PARITY_EVEN;
1560 ll_datawidth = LL_USART_DATAWIDTH_9B;
1561 } else if (config->parity == 1) {
1562 /* 8 databit, 1 parity bit, parity odd */
1563 ll_parity = LL_USART_PARITY_ODD;
1564 ll_datawidth = LL_USART_DATAWIDTH_9B;
1565 } else { /* Default to 8N0, but show warning if invalid value */
1566 if (config->parity != 0) {
1567 LOG_WRN("Invalid parity setting '%d'."
1568 "Defaulting to 'none'.", config->parity);
1569 }
1570 /* 8 databit, parity none */
1571 ll_parity = LL_USART_PARITY_NONE;
1572 ll_datawidth = LL_USART_DATAWIDTH_8B;
1573 }
1574
1575 /* Set datawidth and parity, 1 start bit, 1 stop bit */
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001576 LL_USART_ConfigCharacter(UartInstance,
Pauli Salmenrinne30003ff2020-03-18 13:40:21 +02001577 ll_datawidth,
1578 ll_parity,
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001579 LL_USART_STOPBITS_1);
1580
Georgij Cernysiov04da64d2019-02-08 18:39:35 +01001581 if (config->hw_flow_control) {
1582 uart_stm32_set_hwctrl(dev, LL_USART_HWCONTROL_RTS_CTS);
1583 }
1584
Pushpal Sidhuacd0e252019-01-07 13:52:24 -08001585 /* Set the default baudrate */
1586 uart_stm32_set_baudrate(dev, data->baud_rate);
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001587
Jonathan Hahn32f9dcf2022-01-01 23:41:19 +01001588 /* Enable the single wire / half-duplex mode */
1589 if (config->single_wire) {
1590 LL_USART_EnableHalfDuplex(UartInstance);
1591 }
1592
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001593 LL_USART_Enable(UartInstance);
1594
Erwan Gouriou80b8c502018-06-13 11:32:38 +02001595#ifdef USART_ISR_TEACK
1596 /* Wait until TEACK flag is set */
Anas Nashif4c322582019-06-04 10:52:23 -04001597 while (!(LL_USART_IsActiveFlag_TEACK(UartInstance))) {
1598 }
Erwan Gouriou80b8c502018-06-13 11:32:38 +02001599#endif /* !USART_ISR_TEACK */
1600
1601#ifdef USART_ISR_REACK
Erwan Gouriou13a96572018-06-18 18:01:06 +02001602 /* Wait until REACK flag is set */
Anas Nashif4c322582019-06-04 10:52:23 -04001603 while (!(LL_USART_IsActiveFlag_REACK(UartInstance))) {
1604 }
Erwan Gouriou80b8c502018-06-13 11:32:38 +02001605#endif /* !USART_ISR_REACK */
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001606
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001607#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API)
Erwan Gouriou8c079e92016-11-14 11:53:52 +01001608 config->uconf.irq_config_func(dev);
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001609#elif defined(CONFIG_PM)
1610 config->irq_config_func(dev);
1611#endif /* defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) */
1612
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001613#ifdef CONFIG_UART_ASYNC_API
1614 return uart_stm32_async_init(dev);
1615#else
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001616 return 0;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001617#endif
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001618}
1619
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001620#ifdef CONFIG_UART_ASYNC_API
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001621
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001622/* src_dev and dest_dev should be 'MEMORY' or 'PERIPHERAL'. */
1623#define UART_DMA_CHANNEL_INIT(index, dir, dir_cap, src_dev, dest_dev) \
Francois Ramu30fd0222021-06-18 15:52:30 +02001624 .dma_dev = DEVICE_DT_GET(STM32_DMA_CTLR(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001625 .dma_channel = DT_INST_DMAS_CELL_BY_NAME(index, dir, channel), \
1626 .dma_cfg = { \
Francois Ramu744e1dc2021-08-09 16:32:57 +02001627 .dma_slot = STM32_DMA_SLOT(index, dir, slot),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001628 .channel_direction = STM32_DMA_CONFIG_DIRECTION( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001629 STM32_DMA_CHANNEL_CONFIG(index, dir)),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001630 .channel_priority = STM32_DMA_CONFIG_PRIORITY( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001631 STM32_DMA_CHANNEL_CONFIG(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001632 .source_data_size = STM32_DMA_CONFIG_##src_dev##_DATA_SIZE(\
Francois Ramu30fd0222021-06-18 15:52:30 +02001633 STM32_DMA_CHANNEL_CONFIG(index, dir)),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001634 .dest_data_size = STM32_DMA_CONFIG_##dest_dev##_DATA_SIZE(\
Francois Ramu30fd0222021-06-18 15:52:30 +02001635 STM32_DMA_CHANNEL_CONFIG(index, dir)),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001636 .source_burst_length = 1, /* SINGLE transfer */ \
1637 .dest_burst_length = 1, \
1638 .block_count = 1, \
1639 .dma_callback = uart_stm32_dma_##dir##_cb, \
1640 }, \
1641 .src_addr_increment = STM32_DMA_CONFIG_##src_dev##_ADDR_INC( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001642 STM32_DMA_CHANNEL_CONFIG(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001643 .dst_addr_increment = STM32_DMA_CONFIG_##dest_dev##_ADDR_INC( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001644 STM32_DMA_CHANNEL_CONFIG(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001645 .fifo_threshold = STM32_DMA_FEATURES_FIFO_THRESHOLD( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001646 STM32_DMA_FEATURES(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001647
1648#endif
1649
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001650#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) || \
1651 defined(CONFIG_PM)
Erwan Gouriou62755132020-02-28 14:54:37 +01001652#define STM32_UART_IRQ_HANDLER_DECL(index) \
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001653 static void uart_stm32_irq_config_func_##index(const struct device *dev);
Erwan Gouriou62755132020-02-28 14:54:37 +01001654#define STM32_UART_IRQ_HANDLER(index) \
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +02001655static void uart_stm32_irq_config_func_##index(const struct device *dev) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001656{ \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001657 IRQ_CONNECT(DT_INST_IRQN(index), \
1658 DT_INST_IRQ(index, priority), \
Kumar Galac49b1622020-12-11 10:12:30 -06001659 uart_stm32_isr, DEVICE_DT_INST_GET(index), \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001660 0); \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001661 irq_enable(DT_INST_IRQN(index)); \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001662}
1663#else
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001664#define STM32_UART_IRQ_HANDLER_DECL(index) /* Not used */
1665#define STM32_UART_IRQ_HANDLER(index) /* Not used */
1666#endif
1667
1668#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API)
1669#define STM32_UART_IRQ_HANDLER_FUNC(index) \
1670 .irq_config_func = uart_stm32_irq_config_func_##index,
1671#define STM32_UART_POLL_IRQ_HANDLER_FUNC(index) /* Not used */
1672#elif defined(CONFIG_PM)
1673#define STM32_UART_IRQ_HANDLER_FUNC(index) /* Not used */
1674#define STM32_UART_POLL_IRQ_HANDLER_FUNC(index) \
1675 .irq_config_func = uart_stm32_irq_config_func_##index,
1676#else
1677#define STM32_UART_IRQ_HANDLER_FUNC(index) /* Not used */
1678#define STM32_UART_POLL_IRQ_HANDLER_FUNC(index) /* Not used */
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001679#endif
1680
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001681#ifdef CONFIG_UART_ASYNC_API
1682#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) \
1683.dma_##dir = { \
1684 COND_CODE_1(DT_INST_DMAS_HAS_NAME(index, dir), \
1685 (UART_DMA_CHANNEL_INIT(index, dir, DIR, src, dest)), \
1686 (NULL)) \
1687 },
1688
1689#else
1690#define UART_DMA_CHANNEL(index, dir, DIR, src, dest)
1691#endif
1692
Erwan Gouriou62755132020-02-28 14:54:37 +01001693#define STM32_UART_INIT(index) \
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001694STM32_UART_IRQ_HANDLER_DECL(index) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001695 \
Gerard Marull-Paretas5dc6ed32021-12-23 12:33:03 +01001696PINCTRL_DT_INST_DEFINE(index); \
Erwan Gouriou252a6232020-06-05 10:57:52 +02001697 \
Erwan Gouriou62755132020-02-28 14:54:37 +01001698static const struct uart_stm32_config uart_stm32_cfg_##index = { \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001699 .uconf = { \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001700 .base = (uint8_t *)DT_INST_REG_ADDR(index), \
Erwan Gouriou62755132020-02-28 14:54:37 +01001701 STM32_UART_IRQ_HANDLER_FUNC(index) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001702 }, \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001703 .pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
1704 .enr = DT_INST_CLOCKS_CELL(index, bits) \
Erwan Gourioud76a5592018-11-08 14:38:48 +01001705 }, \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001706 .hw_flow_control = DT_INST_PROP(index, hw_flow_control), \
Gerard Marull-Paretasc759a352021-11-17 14:01:42 +01001707 .parity = DT_INST_ENUM_IDX_OR(index, parity, UART_CFG_PARITY_NONE), \
Gerard Marull-Paretas21a27192021-09-07 16:39:45 +02001708 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
Jonathan Hahn32f9dcf2022-01-01 23:41:19 +01001709 .single_wire = DT_INST_PROP_OR(index, single_wire, false), \
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001710 STM32_UART_POLL_IRQ_HANDLER_FUNC(index) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001711}; \
1712 \
Erwan Gouriou62755132020-02-28 14:54:37 +01001713static struct uart_stm32_data uart_stm32_data_##index = { \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001714 .baud_rate = DT_INST_PROP(index, current_speed), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001715 UART_DMA_CHANNEL(index, rx, RX, PERIPHERAL, MEMORY) \
1716 UART_DMA_CHANNEL(index, tx, TX, MEMORY, PERIPHERAL) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001717}; \
1718 \
Kumar Galac49b1622020-12-11 10:12:30 -06001719DEVICE_DT_INST_DEFINE(index, \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001720 &uart_stm32_init, \
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001721 NULL, \
Erwan Gouriou62755132020-02-28 14:54:37 +01001722 &uart_stm32_data_##index, &uart_stm32_cfg_##index, \
Maureen Helmad145052021-10-14 09:38:10 -05001723 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001724 &uart_stm32_driver_api); \
1725 \
Erwan Gouriou62755132020-02-28 14:54:37 +01001726STM32_UART_IRQ_HANDLER(index)
Erwan Gouriou8c079e92016-11-14 11:53:52 +01001727
Martí Bolívar7e0eed92020-05-06 11:23:07 -07001728DT_INST_FOREACH_STATUS_OKAY(STM32_UART_INIT)