blob: 5de02fbee298184b5ede28bc61fa1142334b7e82 [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
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020017#include <zephyr/kernel.h>
18#include <zephyr/arch/cpu.h>
19#include <zephyr/sys/__assert.h>
Kumar Galaaa2bdbe2018-10-31 12:44:45 -050020#include <soc.h>
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020021#include <zephyr/init.h>
22#include <zephyr/drivers/uart.h>
23#include <zephyr/drivers/clock_control.h>
24#include <zephyr/pm/policy.h>
Erwan Gourioua439c042022-08-03 14:39:59 +020025#include <zephyr/pm/device.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010026
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +020027#ifdef CONFIG_UART_ASYNC_API
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020028#include <zephyr/drivers/dma/dma_stm32.h>
29#include <zephyr/drivers/dma.h>
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +020030#endif
31
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020032#include <zephyr/linker/sections.h>
33#include <zephyr/drivers/clock_control/stm32_clock_control.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010034#include "uart_stm32.h"
35
Gerard Marull-Paretase83fab32020-10-03 23:58:36 +020036#include <stm32_ll_usart.h>
37#include <stm32_ll_lpuart.h>
38
Gerard Marull-Paretasfb60aab2022-05-06 10:25:46 +020039#include <zephyr/logging/log.h>
Pete Dietl060e39e2022-03-04 12:56:05 -080040LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL);
Francois Ramud3ffa8d2019-11-12 16:13:03 +010041
Artur Lipowskibb857592022-05-10 12:18:28 +020042/* This symbol takes the value 1 if one of the device instances */
Erwan Gouriou1ef9e9e2022-08-04 11:08:15 +020043/* is configured in dts with a domain clock */
44#if STM32_DT_INST_DEV_DOMAIN_CLOCK_SUPPORT
45#define STM32_UART_DOMAIN_CLOCK_SUPPORT 1
Artur Lipowskibb857592022-05-10 12:18:28 +020046#else
Erwan Gouriou1ef9e9e2022-08-04 11:08:15 +020047#define STM32_UART_DOMAIN_CLOCK_SUPPORT 0
Artur Lipowskibb857592022-05-10 12:18:28 +020048#endif
49
Kumar Galac2135f82020-05-07 12:22:26 -050050#define HAS_LPUART_1 (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), \
51 st_stm32_lpuart, okay))
Erwan Gouriou76313f02020-04-17 12:33:29 +020052
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +080053#if HAS_LPUART_1
54#ifdef USART_PRESC_PRESCALER
55uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint16_t presc_idx,
56 const uint32_t baud_rate)
57{
58 uint64_t lpuartdiv;
59
60 lpuartdiv = clock_rate / LPUART_PRESCALER_TAB[presc_idx];
61 lpuartdiv *= LPUART_LPUARTDIV_FREQ_MUL;
62 lpuartdiv += baud_rate / 2;
63 lpuartdiv /= baud_rate;
64
65 return (uint32_t)lpuartdiv;
66}
67#else
68uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint32_t baud_rate)
69{
70 uint64_t lpuartdiv;
71
72 lpuartdiv = clock_rate * LPUART_LPUARTDIV_FREQ_MUL;
73 lpuartdiv += baud_rate / 2;
74 lpuartdiv /= baud_rate;
75
76 return (uint32_t)lpuartdiv;
77}
78#endif /* USART_PRESC_PRESCALER */
79#endif /* HAS_LPUART_1 */
80
Erwan Gourioua3de3df2021-09-14 09:27:56 +020081#ifdef CONFIG_PM
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +010082static void uart_stm32_pm_policy_state_lock_get(const struct device *dev)
Erwan Gourioua3de3df2021-09-14 09:27:56 +020083{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +010084 struct uart_stm32_data *data = dev->data;
Erwan Gourioua3de3df2021-09-14 09:27:56 +020085
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +010086 if (!data->pm_policy_state_on) {
87 data->pm_policy_state_on = true;
Carlo Caione69b28bf2022-04-07 13:06:12 +020088 pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
Erwan Gourioua3de3df2021-09-14 09:27:56 +020089 }
90}
91
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +010092static void uart_stm32_pm_policy_state_lock_put(const struct device *dev)
Erwan Gourioua3de3df2021-09-14 09:27:56 +020093{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +010094 struct uart_stm32_data *data = dev->data;
Erwan Gourioua3de3df2021-09-14 09:27:56 +020095
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +010096 if (data->pm_policy_state_on) {
97 data->pm_policy_state_on = false;
Carlo Caione69b28bf2022-04-07 13:06:12 +020098 pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
Erwan Gourioua3de3df2021-09-14 09:27:56 +020099 }
100}
101#endif /* CONFIG_PM */
102
Artur Lipowskibb857592022-05-10 12:18:28 +0200103static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t baud_rate)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800104{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100105 const struct uart_stm32_config *config = dev->config;
106 struct uart_stm32_data *data = dev->data;
Erwan Gouriou69a28962019-05-20 17:15:02 +0200107
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500108 uint32_t clock_rate;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800109
110 /* Get clock rate */
Erwan Gouriou1ef9e9e2022-08-04 11:08:15 +0200111 if (IS_ENABLED(STM32_UART_DOMAIN_CLOCK_SUPPORT) && (config->pclk_len > 1)) {
Artur Lipowskibb857592022-05-10 12:18:28 +0200112 if (clock_control_get_rate(data->clock,
113 (clock_control_subsys_t)&config->pclken[1],
114 &clock_rate) < 0) {
115 LOG_ERR("Failed call clock_control_get_rate(pclken[1])");
116 return;
117 }
118 } else {
119 if (clock_control_get_rate(data->clock,
120 (clock_control_subsys_t)&config->pclken[0],
121 &clock_rate) < 0) {
122 LOG_ERR("Failed call clock_control_get_rate(pclken[0])");
123 return;
124 }
Francois Ramud3ffa8d2019-11-12 16:13:03 +0100125 }
Erwan Gouriou69a28962019-05-20 17:15:02 +0200126
Erwan Gouriou76313f02020-04-17 12:33:29 +0200127#if HAS_LPUART_1
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100128 if (IS_LPUART_INSTANCE(config->usart)) {
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +0800129 uint32_t lpuartdiv;
130#ifdef USART_PRESC_PRESCALER
131 uint8_t presc_idx;
132 uint32_t presc_val;
133
134 for (presc_idx = 0; presc_idx < ARRAY_SIZE(LPUART_PRESCALER_TAB); presc_idx++) {
135 lpuartdiv = lpuartdiv_calc(clock_rate, presc_idx, baud_rate);
136 if (lpuartdiv >= LPUART_BRR_MIN_VALUE && lpuartdiv <= LPUART_BRR_MASK) {
137 break;
138 }
139 }
140
141 if (presc_idx == ARRAY_SIZE(LPUART_PRESCALER_TAB)) {
142 LOG_ERR("Unable to set %s to %d", dev->name, baud_rate);
143 return;
144 }
145
146 presc_val = presc_idx << USART_PRESC_PRESCALER_Pos;
147
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100148 LL_LPUART_SetPrescaler(config->usart, presc_val);
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +0800149#else
150 lpuartdiv = lpuartdiv_calc(clock_rate, baud_rate);
151 if (lpuartdiv < LPUART_BRR_MIN_VALUE || lpuartdiv > LPUART_BRR_MASK) {
152 LOG_ERR("Unable to set %s to %d", dev->name, baud_rate);
153 return;
154 }
155#endif /* USART_PRESC_PRESCALER */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100156 LL_LPUART_SetBaudRate(config->usart,
Erwan Gouriou69a28962019-05-20 17:15:02 +0200157 clock_rate,
158#ifdef USART_PRESC_PRESCALER
Yong Cong Sina6ebcdd2021-10-22 00:02:29 +0800159 presc_val,
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800160#endif
Erwan Gouriou69a28962019-05-20 17:15:02 +0200161 baud_rate);
162 } else {
Erwan Gouriou76313f02020-04-17 12:33:29 +0200163#endif /* HAS_LPUART_1 */
Erwan Gouriou37c7b892021-01-08 10:54:46 +0100164#ifdef USART_CR1_OVER8
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100165 LL_USART_SetOverSampling(config->usart,
Erwan Gouriou37c7b892021-01-08 10:54:46 +0100166 LL_USART_OVERSAMPLING_16);
167#endif
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100168 LL_USART_SetBaudRate(config->usart,
Erwan Gouriou69a28962019-05-20 17:15:02 +0200169 clock_rate,
170#ifdef USART_PRESC_PRESCALER
171 LL_USART_PRESCALER_DIV1,
172#endif
173#ifdef USART_CR1_OVER8
174 LL_USART_OVERSAMPLING_16,
175#endif
176 baud_rate);
177
Erwan Gouriou76313f02020-04-17 12:33:29 +0200178#if HAS_LPUART_1
Erwan Gouriou69a28962019-05-20 17:15:02 +0200179 }
Erwan Gouriou76313f02020-04-17 12:33:29 +0200180#endif /* HAS_LPUART_1 */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800181}
182
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200183static inline void uart_stm32_set_parity(const struct device *dev,
184 uint32_t parity)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800185{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100186 const struct uart_stm32_config *config = dev->config;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800187
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100188 LL_USART_SetParity(config->usart, parity);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800189}
190
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200191static inline uint32_t uart_stm32_get_parity(const struct device *dev)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800192{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100193 const struct uart_stm32_config *config = dev->config;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800194
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100195 return LL_USART_GetParity(config->usart);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800196}
197
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200198static inline void uart_stm32_set_stopbits(const struct device *dev,
199 uint32_t stopbits)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800200{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100201 const struct uart_stm32_config *config = dev->config;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800202
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100203 LL_USART_SetStopBitsLength(config->usart, stopbits);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800204}
205
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200206static inline uint32_t uart_stm32_get_stopbits(const struct device *dev)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800207{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100208 const struct uart_stm32_config *config = dev->config;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800209
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100210 return LL_USART_GetStopBitsLength(config->usart);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800211}
212
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200213static inline void uart_stm32_set_databits(const struct device *dev,
214 uint32_t databits)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800215{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100216 const struct uart_stm32_config *config = dev->config;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800217
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100218 LL_USART_SetDataWidth(config->usart, databits);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800219}
220
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200221static inline uint32_t uart_stm32_get_databits(const struct device *dev)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800222{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100223 const struct uart_stm32_config *config = dev->config;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800224
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100225 return LL_USART_GetDataWidth(config->usart);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800226}
227
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200228static inline void uart_stm32_set_hwctrl(const struct device *dev,
229 uint32_t hwctrl)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100230{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100231 const struct uart_stm32_config *config = dev->config;
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100232
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100233 LL_USART_SetHWFlowCtrl(config->usart, hwctrl);
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100234}
235
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200236static inline uint32_t uart_stm32_get_hwctrl(const struct device *dev)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100237{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100238 const struct uart_stm32_config *config = dev->config;
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100239
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100240 return LL_USART_GetHWFlowCtrl(config->usart);
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100241}
242
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500243static inline uint32_t uart_stm32_cfg2ll_parity(enum uart_config_parity parity)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800244{
245 switch (parity) {
246 case UART_CFG_PARITY_ODD:
247 return LL_USART_PARITY_ODD;
248 case UART_CFG_PARITY_EVEN:
249 return LL_USART_PARITY_EVEN;
250 case UART_CFG_PARITY_NONE:
251 default:
252 return LL_USART_PARITY_NONE;
253 }
254}
255
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500256static inline enum uart_config_parity uart_stm32_ll2cfg_parity(uint32_t parity)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800257{
258 switch (parity) {
259 case LL_USART_PARITY_ODD:
260 return UART_CFG_PARITY_ODD;
261 case LL_USART_PARITY_EVEN:
262 return UART_CFG_PARITY_EVEN;
263 case LL_USART_PARITY_NONE:
264 default:
265 return UART_CFG_PARITY_NONE;
266 }
267}
268
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500269static inline uint32_t uart_stm32_cfg2ll_stopbits(enum uart_config_stop_bits sb)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800270{
271 switch (sb) {
272/* Some MCU's don't support 0.5 stop bits */
273#ifdef LL_USART_STOPBITS_0_5
274 case UART_CFG_STOP_BITS_0_5:
275 return LL_USART_STOPBITS_0_5;
276#endif /* LL_USART_STOPBITS_0_5 */
277 case UART_CFG_STOP_BITS_1:
278 return LL_USART_STOPBITS_1;
279/* Some MCU's don't support 1.5 stop bits */
280#ifdef LL_USART_STOPBITS_1_5
281 case UART_CFG_STOP_BITS_1_5:
282 return LL_USART_STOPBITS_1_5;
283#endif /* LL_USART_STOPBITS_1_5 */
284 case UART_CFG_STOP_BITS_2:
285 default:
286 return LL_USART_STOPBITS_2;
287 }
288}
289
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500290static inline enum uart_config_stop_bits uart_stm32_ll2cfg_stopbits(uint32_t sb)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800291{
292 switch (sb) {
293/* Some MCU's don't support 0.5 stop bits */
294#ifdef LL_USART_STOPBITS_0_5
295 case LL_USART_STOPBITS_0_5:
296 return UART_CFG_STOP_BITS_0_5;
297#endif /* LL_USART_STOPBITS_0_5 */
298 case LL_USART_STOPBITS_1:
299 return UART_CFG_STOP_BITS_1;
300/* Some MCU's don't support 1.5 stop bits */
301#ifdef LL_USART_STOPBITS_1_5
302 case LL_USART_STOPBITS_1_5:
303 return UART_CFG_STOP_BITS_1_5;
304#endif /* LL_USART_STOPBITS_1_5 */
305 case LL_USART_STOPBITS_2:
306 default:
307 return UART_CFG_STOP_BITS_2;
308 }
309}
310
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100311static inline uint32_t uart_stm32_cfg2ll_databits(enum uart_config_data_bits db,
312 enum uart_config_parity p)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800313{
314 switch (db) {
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100315/* Some MCU's don't support 7B or 9B datawidth */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800316#ifdef LL_USART_DATAWIDTH_7B
317 case UART_CFG_DATA_BITS_7:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100318 if (p == UART_CFG_PARITY_NONE) {
319 return LL_USART_DATAWIDTH_7B;
320 } else {
321 return LL_USART_DATAWIDTH_8B;
322 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800323#endif /* LL_USART_DATAWIDTH_7B */
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100324#ifdef LL_USART_DATAWIDTH_9B
325 case UART_CFG_DATA_BITS_9:
326 return LL_USART_DATAWIDTH_9B;
327#endif /* LL_USART_DATAWIDTH_9B */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800328 case UART_CFG_DATA_BITS_8:
329 default:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100330 if (p == UART_CFG_PARITY_NONE) {
331 return LL_USART_DATAWIDTH_8B;
332#ifdef LL_USART_DATAWIDTH_9B
333 } else {
334 return LL_USART_DATAWIDTH_9B;
335#endif
336 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800337 return LL_USART_DATAWIDTH_8B;
338 }
339}
340
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100341static inline enum uart_config_data_bits uart_stm32_ll2cfg_databits(uint32_t db,
342 uint32_t p)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800343{
344 switch (db) {
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100345/* Some MCU's don't support 7B or 9B datawidth */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800346#ifdef LL_USART_DATAWIDTH_7B
347 case LL_USART_DATAWIDTH_7B:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100348 if (p == LL_USART_PARITY_NONE) {
349 return UART_CFG_DATA_BITS_7;
350 } else {
351 return UART_CFG_DATA_BITS_6;
352 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800353#endif /* LL_USART_DATAWIDTH_7B */
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100354#ifdef LL_USART_DATAWIDTH_9B
355 case LL_USART_DATAWIDTH_9B:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100356 if (p == LL_USART_PARITY_NONE) {
357 return UART_CFG_DATA_BITS_9;
358 } else {
359 return UART_CFG_DATA_BITS_8;
360 }
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100361#endif /* LL_USART_DATAWIDTH_9B */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800362 case LL_USART_DATAWIDTH_8B:
363 default:
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100364 if (p == LL_USART_PARITY_NONE) {
365 return UART_CFG_DATA_BITS_8;
366 } else {
367 return UART_CFG_DATA_BITS_7;
368 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800369 }
370}
371
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100372/**
373 * @brief Get LL hardware flow control define from
374 * Zephyr hardware flow control option.
375 * @note Supports only UART_CFG_FLOW_CTRL_RTS_CTS.
376 * @param fc: Zephyr hardware flow control option.
377 * @retval LL_USART_HWCONTROL_RTS_CTS, or LL_USART_HWCONTROL_NONE.
378 */
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500379static inline uint32_t uart_stm32_cfg2ll_hwctrl(enum uart_config_flow_control fc)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100380{
381 if (fc == UART_CFG_FLOW_CTRL_RTS_CTS) {
382 return LL_USART_HWCONTROL_RTS_CTS;
383 }
384
385 return LL_USART_HWCONTROL_NONE;
386}
387
388/**
Yannis Damigosa4b448e2020-02-06 20:36:03 +0200389 * @brief Get Zephyr hardware flow control option from
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100390 * LL hardware flow control define.
391 * @note Supports only LL_USART_HWCONTROL_RTS_CTS.
Yannis Damigosa4b448e2020-02-06 20:36:03 +0200392 * @param fc: LL hardware flow control definition.
Kumar Gala61153462020-02-06 11:30:05 -0600393 * @retval UART_CFG_FLOW_CTRL_RTS_CTS, or UART_CFG_FLOW_CTRL_NONE.
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100394 */
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500395static inline enum uart_config_flow_control uart_stm32_ll2cfg_hwctrl(uint32_t fc)
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100396{
397 if (fc == LL_USART_HWCONTROL_RTS_CTS) {
398 return UART_CFG_FLOW_CTRL_RTS_CTS;
399 }
400
Kumar Gala61153462020-02-06 11:30:05 -0600401 return UART_CFG_FLOW_CTRL_NONE;
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100402}
403
Daniel Leung4e1692f2021-05-26 12:33:37 -0700404#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200405static int uart_stm32_configure(const struct device *dev,
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800406 const struct uart_config *cfg)
407{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100408 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100409 struct uart_stm32_data *data = dev->data;
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500410 const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity);
411 const uint32_t stopbits = uart_stm32_cfg2ll_stopbits(cfg->stop_bits);
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100412 const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits,
413 cfg->parity);
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500414 const uint32_t flowctrl = uart_stm32_cfg2ll_hwctrl(cfg->flow_ctrl);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800415
416 /* Hardware doesn't support mark or space parity */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100417 if ((cfg->parity == UART_CFG_PARITY_MARK) ||
418 (cfg->parity == UART_CFG_PARITY_SPACE)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800419 return -ENOTSUP;
420 }
421
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100422 /* Driver does not supports parity + 9 databits */
423 if ((cfg->parity != UART_CFG_PARITY_NONE) &&
424 (cfg->data_bits == UART_CFG_DATA_BITS_9)) {
425 return -ENOTSUP;
426 }
427
Erwan Gouriou76313f02020-04-17 12:33:29 +0200428#if defined(LL_USART_STOPBITS_0_5) && HAS_LPUART_1
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100429 if (IS_LPUART_INSTANCE(config->usart) &&
Erwan Gouriou5e561702021-02-11 09:55:38 +0100430 (cfg->stop_bits == UART_CFG_STOP_BITS_0_5)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800431 return -ENOTSUP;
432 }
433#else
Erwan Gouriou5e561702021-02-11 09:55:38 +0100434 if (cfg->stop_bits == UART_CFG_STOP_BITS_0_5) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800435 return -ENOTSUP;
436 }
437#endif
438
Erwan Gouriou76313f02020-04-17 12:33:29 +0200439#if defined(LL_USART_STOPBITS_1_5) && HAS_LPUART_1
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100440 if (IS_LPUART_INSTANCE(config->usart) &&
Erwan Gouriou5e561702021-02-11 09:55:38 +0100441 (cfg->stop_bits == UART_CFG_STOP_BITS_1_5)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800442 return -ENOTSUP;
443 }
444#else
Erwan Gouriou5e561702021-02-11 09:55:38 +0100445 if (cfg->stop_bits == UART_CFG_STOP_BITS_1_5) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800446 return -ENOTSUP;
447 }
448#endif
449
Benoit Leforestier9fee67d2019-03-22 14:19:57 +0100450 /* Driver doesn't support 5 or 6 databits and potentially 7 or 9 */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100451 if ((cfg->data_bits == UART_CFG_DATA_BITS_5) ||
452 (cfg->data_bits == UART_CFG_DATA_BITS_6)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800453#ifndef LL_USART_DATAWIDTH_7B
Erwan Gouriou5e561702021-02-11 09:55:38 +0100454 || (cfg->data_bits == UART_CFG_DATA_BITS_7)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800455#endif /* LL_USART_DATAWIDTH_7B */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100456 || (cfg->data_bits == UART_CFG_DATA_BITS_9)) {
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800457 return -ENOTSUP;
458 }
459
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100460 /* Driver supports only RTS CTS flow control */
Erwan Gouriou5e561702021-02-11 09:55:38 +0100461 if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100462 if (!IS_UART_HWFLOW_INSTANCE(config->usart) ||
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100463 UART_CFG_FLOW_CTRL_RTS_CTS != cfg->flow_ctrl) {
464 return -ENOTSUP;
465 }
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800466 }
467
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100468 LL_USART_Disable(config->usart);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800469
470 if (parity != uart_stm32_get_parity(dev)) {
471 uart_stm32_set_parity(dev, parity);
472 }
473
474 if (stopbits != uart_stm32_get_stopbits(dev)) {
475 uart_stm32_set_stopbits(dev, stopbits);
476 }
477
478 if (databits != uart_stm32_get_databits(dev)) {
479 uart_stm32_set_databits(dev, databits);
480 }
481
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100482 if (flowctrl != uart_stm32_get_hwctrl(dev)) {
483 uart_stm32_set_hwctrl(dev, flowctrl);
484 }
485
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800486 if (cfg->baudrate != data->baud_rate) {
487 uart_stm32_set_baudrate(dev, cfg->baudrate);
488 data->baud_rate = cfg->baudrate;
489 }
490
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100491 LL_USART_Enable(config->usart);
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800492 return 0;
493};
494
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200495static int uart_stm32_config_get(const struct device *dev,
496 struct uart_config *cfg)
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800497{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100498 struct uart_stm32_data *data = dev->data;
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800499
500 cfg->baudrate = data->baud_rate;
501 cfg->parity = uart_stm32_ll2cfg_parity(uart_stm32_get_parity(dev));
502 cfg->stop_bits = uart_stm32_ll2cfg_stopbits(
503 uart_stm32_get_stopbits(dev));
504 cfg->data_bits = uart_stm32_ll2cfg_databits(
Nicolas VINCENT573eec12021-03-10 13:23:00 +0100505 uart_stm32_get_databits(dev), uart_stm32_get_parity(dev));
Georgij Cernysiov78eed342019-03-15 19:51:09 +0100506 cfg->flow_ctrl = uart_stm32_ll2cfg_hwctrl(
507 uart_stm32_get_hwctrl(dev));
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800508 return 0;
509}
Daniel Leung4e1692f2021-05-26 12:33:37 -0700510#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
Pushpal Sidhuacd0e252019-01-07 13:52:24 -0800511
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200512static int uart_stm32_poll_in(const struct device *dev, unsigned char *c)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100513{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100514 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100515
Kiril Zyapkov7a602fc2018-11-02 15:34:56 +0200516 /* Clear overrun error flag */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100517 if (LL_USART_IsActiveFlag_ORE(config->usart)) {
518 LL_USART_ClearFlag_ORE(config->usart);
Kiril Zyapkov7a602fc2018-11-02 15:34:56 +0200519 }
520
Francois Ramu860bd872022-01-28 16:52:28 +0100521 /*
522 * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by
523 * the uart_err_check function call (on errors flags clearing)
524 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100525 if (!LL_USART_IsActiveFlag_RXNE(config->usart)) {
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100526 return -1;
527 }
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200528
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100529 *c = (unsigned char)LL_USART_ReceiveData8(config->usart);
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200530
531 return 0;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100532}
533
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200534static void uart_stm32_poll_out(const struct device *dev,
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100535 unsigned char c)
536{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100537 const struct uart_stm32_config *config = dev->config;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100538#ifdef CONFIG_PM
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100539 struct uart_stm32_data *data = dev->data;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100540#endif
Johann Fischer5e5ea9a2022-07-13 16:50:25 +0200541 unsigned int key;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100542
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100543 /* Wait for TXE flag to be raised
544 * When TXE flag is raised, we lock interrupts to prevent interrupts (notably that of usart)
545 * or thread switch. Then, we can safely send our character. The character sent will be
546 * interlaced with the characters potentially send with interrupt transmission API
547 */
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100548 while (1) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100549 if (LL_USART_IsActiveFlag_TXE(config->usart)) {
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100550 key = irq_lock();
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100551 if (LL_USART_IsActiveFlag_TXE(config->usart)) {
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100552 break;
553 }
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100554 irq_unlock(key);
555 }
Anas Nashif4c322582019-06-04 10:52:23 -0400556 }
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200557
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200558#ifdef CONFIG_PM
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200559
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100560 /* If an interrupt transmission is in progress, the pm constraint is already managed by the
561 * call of uart_stm32_irq_tx_[en|dis]able
562 */
563 if (!data->tx_poll_stream_on && !data->tx_int_stream_on) {
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200564 data->tx_poll_stream_on = true;
565
566 /* Don't allow system to suspend until stream
567 * transmission has completed
568 */
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +0100569 uart_stm32_pm_policy_state_lock_get(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200570
571 /* Enable TC interrupt so we can release suspend
572 * constraint when done
573 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100574 LL_USART_EnableIT_TC(config->usart);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200575 }
576#endif /* CONFIG_PM */
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +0200577
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100578 LL_USART_TransmitData8(config->usart, (uint8_t)c);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100579 irq_unlock(key);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100580}
581
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200582static int uart_stm32_err_check(const struct device *dev)
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100583{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100584 const struct uart_stm32_config *config = dev->config;
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500585 uint32_t err = 0U;
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100586
Francois Ramu860bd872022-01-28 16:52:28 +0100587 /* Check for errors, then clear them.
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100588 * Some SoC clear all error flags when at least
Francois Ramu860bd872022-01-28 16:52:28 +0100589 * one is cleared. (e.g. F4X, F1X, and F2X).
590 * The stm32 F4X, F1X, and F2X also reads the usart DR when clearing Errors
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100591 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100592 if (LL_USART_IsActiveFlag_ORE(config->usart)) {
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100593 err |= UART_ERROR_OVERRUN;
594 }
595
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100596 if (LL_USART_IsActiveFlag_PE(config->usart)) {
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100597 err |= UART_ERROR_PARITY;
598 }
599
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100600 if (LL_USART_IsActiveFlag_FE(config->usart)) {
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100601 err |= UART_ERROR_FRAMING;
602 }
603
Andrea Campanellab2190fd2021-12-21 16:09:15 +0000604#if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT)
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100605 if (LL_USART_IsActiveFlag_LBD(config->usart)) {
Andrea Campanellab2190fd2021-12-21 16:09:15 +0000606 err |= UART_BREAK;
607 }
608
609 if (err & UART_BREAK) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100610 LL_USART_ClearFlag_LBD(config->usart);
Andrea Campanellab2190fd2021-12-21 16:09:15 +0000611 }
612#endif
Francois Ramu860bd872022-01-28 16:52:28 +0100613 /* Clearing error :
614 * the stm32 F4X, F1X, and F2X sw sequence is reading the usart SR
615 * then the usart DR to clear the Error flags ORE, PE, FE, NE
616 * --> so is the RXNE flag also cleared !
617 */
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100618 if (err & UART_ERROR_OVERRUN) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100619 LL_USART_ClearFlag_ORE(config->usart);
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100620 }
621
622 if (err & UART_ERROR_PARITY) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100623 LL_USART_ClearFlag_PE(config->usart);
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100624 }
625
626 if (err & UART_ERROR_FRAMING) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100627 LL_USART_ClearFlag_FE(config->usart);
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100628 }
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100629 /* Clear noise error as well,
630 * it is not represented by the errors enum
631 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100632 LL_USART_ClearFlag_NE(config->usart);
Georgij Cernysiovc74c1312019-02-14 10:50:19 +0100633
634 return err;
635}
636
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200637static inline void __uart_stm32_get_clock(const struct device *dev)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100638{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100639 struct uart_stm32_data *data = dev->data;
Kumar Galab275fec2021-02-11 11:49:24 -0600640 const struct device *clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100641
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100642 data->clock = clk;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100643}
644
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100645#ifdef CONFIG_UART_INTERRUPT_DRIVEN
646
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200647static int uart_stm32_fifo_fill(const struct device *dev,
648 const uint8_t *tx_data,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100649 int size)
650{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100651 const struct uart_stm32_config *config = dev->config;
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500652 uint8_t num_tx = 0U;
Johann Fischer5e5ea9a2022-07-13 16:50:25 +0200653 unsigned int key;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100654
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100655 if (!LL_USART_IsActiveFlag_TXE(config->usart)) {
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100656 return num_tx;
657 }
658
659 /* Lock interrupts to prevent nested interrupts or thread switch */
660 key = irq_lock();
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100661
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200662 while ((size - num_tx > 0) &&
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100663 LL_USART_IsActiveFlag_TXE(config->usart)) {
Georgij Cernysiov3de55da2019-02-06 23:31:24 +0100664 /* TXE flag will be cleared with byte write to DR|RDR register */
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100665
666 /* Send a character (8bit , parity none) */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100667 LL_USART_TransmitData8(config->usart, tx_data[num_tx++]);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100668 }
669
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100670 irq_unlock(key);
671
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100672 return num_tx;
673}
674
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200675static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100676 const int size)
677{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100678 const struct uart_stm32_config *config = dev->config;
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500679 uint8_t num_rx = 0U;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100680
Erwan Gouriouda210ba2017-09-21 15:20:53 +0200681 while ((size - num_rx > 0) &&
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100682 LL_USART_IsActiveFlag_RXNE(config->usart)) {
Georgij Cernysiov3de55da2019-02-06 23:31:24 +0100683 /* RXNE flag will be cleared upon read from DR|RDR register */
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100684
685 /* Receive a character (8bit , parity none) */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100686 rx_data[num_rx++] = LL_USART_ReceiveData8(config->usart);
Kiril Zyapkov7a602fc2018-11-02 15:34:56 +0200687
688 /* Clear overrun error flag */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100689 if (LL_USART_IsActiveFlag_ORE(config->usart)) {
690 LL_USART_ClearFlag_ORE(config->usart);
Francois Ramu860bd872022-01-28 16:52:28 +0100691 /*
692 * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by
693 * the uart_err_check function call (on errors flags clearing)
694 */
Kiril Zyapkov7a602fc2018-11-02 15:34:56 +0200695 }
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100696 }
Georgij Cernysiov3de55da2019-02-06 23:31:24 +0100697
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100698 return num_rx;
699}
700
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200701static void uart_stm32_irq_tx_enable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100702{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100703 const struct uart_stm32_config *config = dev->config;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100704#ifdef CONFIG_PM
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100705 struct uart_stm32_data *data = dev->data;
Johann Fischer5e5ea9a2022-07-13 16:50:25 +0200706 unsigned int key;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100707#endif
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100708
709#ifdef CONFIG_PM
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100710 key = irq_lock();
Julien D'ascenzio7b210502021-10-26 18:03:31 +0200711 data->tx_poll_stream_on = false;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100712 data->tx_int_stream_on = true;
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +0100713 uart_stm32_pm_policy_state_lock_get(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200714#endif
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100715 LL_USART_EnableIT_TC(config->usart);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100716
717#ifdef CONFIG_PM
718 irq_unlock(key);
719#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100720}
721
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200722static void uart_stm32_irq_tx_disable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100723{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100724 const struct uart_stm32_config *config = dev->config;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100725#ifdef CONFIG_PM
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100726 struct uart_stm32_data *data = dev->data;
Johann Fischer5e5ea9a2022-07-13 16:50:25 +0200727 unsigned int key;
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100728
729 key = irq_lock();
730#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100731
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100732 LL_USART_DisableIT_TC(config->usart);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200733
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100734#ifdef CONFIG_PM
735 data->tx_int_stream_on = false;
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +0100736 uart_stm32_pm_policy_state_lock_put(dev);
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100737#endif
Julien D'ascenziod42cef12021-11-08 12:47:25 +0100738
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200739#ifdef CONFIG_PM
Julien D'ascenzioe4234ae2021-12-01 10:19:44 +0100740 irq_unlock(key);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200741#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100742}
743
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200744static int uart_stm32_irq_tx_ready(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100745{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100746 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100747
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100748 return LL_USART_IsActiveFlag_TXE(config->usart) &&
749 LL_USART_IsEnabledIT_TC(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100750}
751
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200752static int uart_stm32_irq_tx_complete(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100753{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100754 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100755
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100756 return LL_USART_IsActiveFlag_TC(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100757}
758
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200759static void uart_stm32_irq_rx_enable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100760{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100761 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100762
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100763 LL_USART_EnableIT_RXNE(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100764}
765
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200766static void uart_stm32_irq_rx_disable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100767{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100768 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100769
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100770 LL_USART_DisableIT_RXNE(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100771}
772
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200773static int uart_stm32_irq_rx_ready(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100774{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100775 const struct uart_stm32_config *config = dev->config;
Francois Ramu860bd872022-01-28 16:52:28 +0100776 /*
777 * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by
778 * the uart_err_check function call (on errors flags clearing)
779 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100780 return LL_USART_IsActiveFlag_RXNE(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100781}
782
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200783static void uart_stm32_irq_err_enable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100784{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100785 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100786
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100787 /* Enable FE, ORE interruptions */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100788 LL_USART_EnableIT_ERROR(config->usart);
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300789#if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT)
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100790 /* Enable Line break detection */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100791 if (IS_UART_LIN_INSTANCE(config->usart)) {
792 LL_USART_EnableIT_LBD(config->usart);
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300793 }
Maciej Debskieaff37e2017-08-09 11:23:04 +0200794#endif
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100795 /* Enable parity error interruption */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100796 LL_USART_EnableIT_PE(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100797}
798
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200799static void uart_stm32_irq_err_disable(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100800{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100801 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100802
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300803 /* Disable FE, ORE interruptions */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100804 LL_USART_DisableIT_ERROR(config->usart);
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300805#if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT)
806 /* Disable Line break detection */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100807 if (IS_UART_LIN_INSTANCE(config->usart)) {
808 LL_USART_DisableIT_LBD(config->usart);
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300809 }
Maciej Debskieaff37e2017-08-09 11:23:04 +0200810#endif
Ilya Tagunov967c31b2018-03-29 19:40:00 +0300811 /* Disable parity error interruption */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100812 LL_USART_DisableIT_PE(config->usart);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100813}
814
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200815static int uart_stm32_irq_is_pending(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100816{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100817 const struct uart_stm32_config *config = dev->config;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100818
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100819 return ((LL_USART_IsActiveFlag_RXNE(config->usart) &&
820 LL_USART_IsEnabledIT_RXNE(config->usart)) ||
821 (LL_USART_IsActiveFlag_TC(config->usart) &&
822 LL_USART_IsEnabledIT_TC(config->usart)));
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100823}
824
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200825static int uart_stm32_irq_update(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100826{
827 return 1;
828}
829
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +0200830static void uart_stm32_irq_callback_set(const struct device *dev,
Paul Sokolovsky57286af2018-07-16 21:12:26 +0300831 uart_irq_callback_user_data_t cb,
832 void *cb_data)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100833{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100834 struct uart_stm32_data *data = dev->data;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100835
836 data->user_cb = cb;
Paul Sokolovsky57286af2018-07-16 21:12:26 +0300837 data->user_data = cb_data;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100838}
839
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200840#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
841
842#ifdef CONFIG_UART_ASYNC_API
843
844static inline void async_user_callback(struct uart_stm32_data *data,
845 struct uart_event *event)
846{
847 if (data->async_cb) {
848 data->async_cb(data->uart_dev, event, data->async_user_data);
849 }
850}
851
852static inline void async_evt_rx_rdy(struct uart_stm32_data *data)
853{
854 LOG_DBG("rx_rdy: (%d %d)", data->dma_rx.offset, data->dma_rx.counter);
855
856 struct uart_event event = {
857 .type = UART_RX_RDY,
858 .data.rx.buf = data->dma_rx.buffer,
859 .data.rx.len = data->dma_rx.counter - data->dma_rx.offset,
860 .data.rx.offset = data->dma_rx.offset
861 };
862
Alexander Shuklin6831b8b2021-02-04 12:00:49 +0300863 /* update the current pos for new data */
864 data->dma_rx.offset = data->dma_rx.counter;
865
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200866 /* send event only for new data */
867 if (event.data.rx.len > 0) {
868 async_user_callback(data, &event);
869 }
870}
871
872static inline void async_evt_rx_err(struct uart_stm32_data *data, int err_code)
873{
874 LOG_DBG("rx error: %d", err_code);
875
876 struct uart_event event = {
877 .type = UART_RX_STOPPED,
878 .data.rx_stop.reason = err_code,
879 .data.rx_stop.data.len = data->dma_rx.counter,
880 .data.rx_stop.data.offset = 0,
881 .data.rx_stop.data.buf = data->dma_rx.buffer
882 };
883
884 async_user_callback(data, &event);
885}
886
887static inline void async_evt_tx_done(struct uart_stm32_data *data)
888{
889 LOG_DBG("tx done: %d", data->dma_tx.counter);
890
891 struct uart_event event = {
892 .type = UART_TX_DONE,
893 .data.tx.buf = data->dma_tx.buffer,
894 .data.tx.len = data->dma_tx.counter
895 };
896
897 /* Reset tx buffer */
898 data->dma_tx.buffer_length = 0;
899 data->dma_tx.counter = 0;
900
901 async_user_callback(data, &event);
902}
903
904static inline void async_evt_tx_abort(struct uart_stm32_data *data)
905{
906 LOG_DBG("tx abort: %d", data->dma_tx.counter);
907
908 struct uart_event event = {
909 .type = UART_TX_ABORTED,
910 .data.tx.buf = data->dma_tx.buffer,
911 .data.tx.len = data->dma_tx.counter
912 };
913
914 /* Reset tx buffer */
915 data->dma_tx.buffer_length = 0;
916 data->dma_tx.counter = 0;
917
918 async_user_callback(data, &event);
919}
920
921static inline void async_evt_rx_buf_request(struct uart_stm32_data *data)
922{
923 struct uart_event evt = {
924 .type = UART_RX_BUF_REQUEST,
925 };
926
927 async_user_callback(data, &evt);
928}
929
930static inline void async_evt_rx_buf_release(struct uart_stm32_data *data)
931{
932 struct uart_event evt = {
933 .type = UART_RX_BUF_RELEASED,
934 .data.rx_buf.buf = data->dma_rx.buffer,
935 };
936
937 async_user_callback(data, &evt);
938}
939
Francois Ramu962d6b12021-04-08 12:09:58 +0200940static inline void async_timer_start(struct k_work_delayable *work,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200941 int32_t timeout)
942{
Krzysztof Chruscinskic590b352021-10-01 15:47:40 +0200943 if ((timeout != SYS_FOREVER_US) && (timeout != 0)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200944 /* start timer */
Krzysztof Chruscinskic590b352021-10-01 15:47:40 +0200945 LOG_DBG("async timer started for %d us", timeout);
946 k_work_reschedule(work, K_USEC(timeout));
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200947 }
948}
949
950static void uart_stm32_dma_rx_flush(const struct device *dev)
951{
952 struct dma_status stat;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100953 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200954
Erwan Gouriou13c23512021-03-01 11:59:57 +0100955 if (dma_get_status(data->dma_rx.dma_dev,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200956 data->dma_rx.dma_channel, &stat) == 0) {
957 size_t rx_rcv_len = data->dma_rx.buffer_length -
958 stat.pending_length;
959 if (rx_rcv_len > data->dma_rx.offset) {
960 data->dma_rx.counter = rx_rcv_len;
961
962 async_evt_rx_rdy(data);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200963 }
964 }
965}
966
967#endif /* CONFIG_UART_ASYNC_API */
968
Erwan Gouriou79ff6452021-09-21 09:34:09 +0200969#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || \
970 defined(CONFIG_UART_ASYNC_API) || \
971 defined(CONFIG_PM)
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +0200972
Tomasz Bursztyka4dcfb552020-06-17 14:58:56 +0200973static void uart_stm32_isr(const struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100974{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +0100975 struct uart_stm32_data *data = dev->data;
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200976#if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API)
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100977 const struct uart_stm32_config *config = dev->config;
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200978#endif
979
980#ifdef CONFIG_PM
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100981 if (LL_USART_IsEnabledIT_TC(config->usart) &&
982 LL_USART_IsActiveFlag_TC(config->usart)) {
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200983
984 if (data->tx_poll_stream_on) {
Yegor Yefremov1155d462022-03-07 22:53:16 +0100985 /* A poll stream transmission just completed,
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200986 * allow system to suspend
987 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +0100988 LL_USART_DisableIT_TC(config->usart);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200989 data->tx_poll_stream_on = false;
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +0100990 uart_stm32_pm_policy_state_lock_put(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200991 }
Yegor Yefremov1155d462022-03-07 22:53:16 +0100992 /* Stream transmission was either async or IRQ based,
Erwan Gourioua3de3df2021-09-14 09:27:56 +0200993 * constraint will be released at the same time TC IT
994 * is disabled
995 */
996 }
997#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100998
Shlomi Vaknin1b4f7e52021-05-17 23:06:51 +0300999#ifdef CONFIG_UART_INTERRUPT_DRIVEN
1000 if (data->user_cb) {
1001 data->user_cb(dev, data->user_data);
1002 }
1003#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
1004
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001005#ifdef CONFIG_UART_ASYNC_API
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001006 if (LL_USART_IsEnabledIT_IDLE(config->usart) &&
1007 LL_USART_IsActiveFlag_IDLE(config->usart)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001008
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001009 LL_USART_ClearFlag_IDLE(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001010
1011 LOG_DBG("idle interrupt occurred");
1012
1013 /* Start the RX timer */
1014 async_timer_start(&data->dma_rx.timeout_work,
1015 data->dma_rx.timeout);
1016
1017 if (data->dma_rx.timeout == 0) {
1018 uart_stm32_dma_rx_flush(dev);
1019 }
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001020 } else if (LL_USART_IsEnabledIT_TC(config->usart) &&
1021 LL_USART_IsActiveFlag_TC(config->usart)) {
Zisis Adamos7235b092021-03-30 12:20:46 +02001022
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001023 LL_USART_DisableIT_TC(config->usart);
1024 LL_USART_ClearFlag_TC(config->usart);
Zisis Adamos7235b092021-03-30 12:20:46 +02001025 /* Generate TX_DONE event when transmission is done */
1026 async_evt_tx_done(data);
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001027
Erwan Gourioua3de3df2021-09-14 09:27:56 +02001028#ifdef CONFIG_PM
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +01001029 uart_stm32_pm_policy_state_lock_put(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +02001030#endif
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001031 } else if (LL_USART_IsEnabledIT_RXNE(config->usart) &&
1032 LL_USART_IsActiveFlag_RXNE(config->usart)) {
Francois Ramucf606392021-11-08 11:43:53 +01001033#ifdef USART_SR_RXNE
1034 /* clear the RXNE flag, because Rx data was not read */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001035 LL_USART_ClearFlag_RXNE(config->usart);
Francois Ramucf606392021-11-08 11:43:53 +01001036#else
Francois Ramu95e2c392021-10-26 11:39:57 +02001037 /* clear the RXNE by flushing the fifo, because Rx data was not read */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001038 LL_USART_RequestRxDataFlush(config->usart);
Francois Ramucf606392021-11-08 11:43:53 +01001039#endif /* USART_SR_RXNE */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001040 }
1041
1042 /* Clear errors */
1043 uart_stm32_err_check(dev);
1044#endif /* CONFIG_UART_ASYNC_API */
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001045}
Erwan Gouriou79ff6452021-09-21 09:34:09 +02001046#endif /* CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API || CONFIG_PM */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001047
1048#ifdef CONFIG_UART_ASYNC_API
1049
1050static int uart_stm32_async_callback_set(const struct device *dev,
1051 uart_callback_t callback,
1052 void *user_data)
1053{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001054 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001055
1056 data->async_cb = callback;
1057 data->async_user_data = user_data;
1058
1059 return 0;
1060}
1061
1062static inline void uart_stm32_dma_tx_enable(const struct device *dev)
1063{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001064 const struct uart_stm32_config *config = dev->config;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001065
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001066 LL_USART_EnableDMAReq_TX(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001067}
1068
1069static inline void uart_stm32_dma_tx_disable(const struct device *dev)
1070{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001071 const struct uart_stm32_config *config = dev->config;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001072
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001073 LL_USART_DisableDMAReq_TX(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001074}
1075
1076static inline void uart_stm32_dma_rx_enable(const struct device *dev)
1077{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001078 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001079 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001080
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001081 LL_USART_EnableDMAReq_RX(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001082
1083 data->dma_rx.enabled = true;
1084}
1085
1086static inline void uart_stm32_dma_rx_disable(const struct device *dev)
1087{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001088 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001089
1090 data->dma_rx.enabled = false;
1091}
1092
1093static int uart_stm32_async_rx_disable(const struct device *dev)
1094{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001095 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001096 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001097 struct uart_event disabled_event = {
1098 .type = UART_RX_DISABLED
1099 };
1100
1101 if (!data->dma_rx.enabled) {
1102 async_user_callback(data, &disabled_event);
1103 return -EFAULT;
1104 }
1105
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001106 LL_USART_DisableIT_IDLE(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001107
1108 uart_stm32_dma_rx_flush(dev);
1109
1110 async_evt_rx_buf_release(data);
1111
1112 uart_stm32_dma_rx_disable(dev);
1113
Francois Ramu962d6b12021-04-08 12:09:58 +02001114 (void)k_work_cancel_delayable(&data->dma_rx.timeout_work);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001115
Erwan Gouriou13c23512021-03-01 11:59:57 +01001116 dma_stop(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001117
1118 data->rx_next_buffer = NULL;
1119 data->rx_next_buffer_len = 0;
1120
Yegor Yefremov1155d462022-03-07 22:53:16 +01001121 /* When async rx is disabled, enable interruptible instance of uart to function normally */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001122 LL_USART_EnableIT_RXNE(config->usart);
Manojkumar Subramaniamd79d26f2021-08-23 02:04:05 +08001123
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001124 LOG_DBG("rx: disabled");
1125
1126 async_user_callback(data, &disabled_event);
1127
1128 return 0;
1129}
1130
1131void uart_stm32_dma_tx_cb(const struct device *dma_dev, void *user_data,
1132 uint32_t channel, int status)
1133{
1134 const struct device *uart_dev = user_data;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001135 struct uart_stm32_data *data = uart_dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001136 struct dma_status stat;
1137 unsigned int key = irq_lock();
1138
1139 /* Disable TX */
1140 uart_stm32_dma_tx_disable(uart_dev);
1141
Francois Ramu962d6b12021-04-08 12:09:58 +02001142 (void)k_work_cancel_delayable(&data->dma_tx.timeout_work);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001143
Erwan Gouriou13c23512021-03-01 11:59:57 +01001144 if (!dma_get_status(data->dma_tx.dma_dev,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001145 data->dma_tx.dma_channel, &stat)) {
1146 data->dma_tx.counter = data->dma_tx.buffer_length -
1147 stat.pending_length;
1148 }
1149
Prema Jonathan van Win76dee392021-05-03 11:24:38 +03001150 data->dma_tx.buffer_length = 0;
1151
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001152 irq_unlock(key);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001153}
1154
1155static void uart_stm32_dma_replace_buffer(const struct device *dev)
1156{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001157 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001158 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001159
Yegor Yefremov1155d462022-03-07 22:53:16 +01001160 /* Replace the buffer and reload the DMA */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001161 LOG_DBG("Replacing RX buffer: %d", data->rx_next_buffer_len);
1162
1163 /* reload DMA */
1164 data->dma_rx.offset = 0;
1165 data->dma_rx.counter = 0;
1166 data->dma_rx.buffer = data->rx_next_buffer;
1167 data->dma_rx.buffer_length = data->rx_next_buffer_len;
1168 data->dma_rx.blk_cfg.block_size = data->dma_rx.buffer_length;
1169 data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer;
1170 data->rx_next_buffer = NULL;
1171 data->rx_next_buffer_len = 0;
1172
Erwan Gouriou13c23512021-03-01 11:59:57 +01001173 dma_reload(data->dma_rx.dma_dev, data->dma_rx.dma_channel,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001174 data->dma_rx.blk_cfg.source_address,
1175 data->dma_rx.blk_cfg.dest_address,
1176 data->dma_rx.blk_cfg.block_size);
1177
Erwan Gouriou13c23512021-03-01 11:59:57 +01001178 dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001179
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001180 LL_USART_ClearFlag_IDLE(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001181
1182 /* Request next buffer */
1183 async_evt_rx_buf_request(data);
1184}
1185
1186void uart_stm32_dma_rx_cb(const struct device *dma_dev, void *user_data,
1187 uint32_t channel, int status)
1188{
1189 const struct device *uart_dev = user_data;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001190 struct uart_stm32_data *data = uart_dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001191
1192 if (status != 0) {
1193 async_evt_rx_err(data, status);
1194 return;
1195 }
1196
Francois Ramu962d6b12021-04-08 12:09:58 +02001197 (void)k_work_cancel_delayable(&data->dma_rx.timeout_work);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001198
1199 /* true since this functions occurs when buffer if full */
1200 data->dma_rx.counter = data->dma_rx.buffer_length;
1201
1202 async_evt_rx_rdy(data);
1203
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001204 if (data->rx_next_buffer != NULL) {
1205 async_evt_rx_buf_release(data);
1206
1207 /* replace the buffer when the current
1208 * is full and not the same as the next
1209 * one.
1210 */
1211 uart_stm32_dma_replace_buffer(uart_dev);
1212 } else {
1213 /* Buffer full without valid next buffer,
1214 * an UART_RX_DISABLED event must be generated,
1215 * but uart_stm32_async_rx_disable() cannot be
1216 * called in ISR context. So force the RX timeout
1217 * to minimum value and let the RX timeout to do the job.
1218 */
Francois Ramu962d6b12021-04-08 12:09:58 +02001219 k_work_reschedule(&data->dma_rx.timeout_work, K_TICKS(1));
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001220 }
1221}
1222
1223static int uart_stm32_async_tx(const struct device *dev,
1224 const uint8_t *tx_data, size_t buf_size, int32_t timeout)
1225{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001226 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001227 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001228 int ret;
1229
Erwan Gouriou13c23512021-03-01 11:59:57 +01001230 if (data->dma_tx.dma_dev == NULL) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001231 return -ENODEV;
1232 }
1233
1234 if (data->dma_tx.buffer_length != 0) {
1235 return -EBUSY;
1236 }
1237
1238 data->dma_tx.buffer = (uint8_t *)tx_data;
1239 data->dma_tx.buffer_length = buf_size;
1240 data->dma_tx.timeout = timeout;
1241
1242 LOG_DBG("tx: l=%d", data->dma_tx.buffer_length);
1243
Zisis Adamos7235b092021-03-30 12:20:46 +02001244 /* Clear TC flag */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001245 LL_USART_ClearFlag_TC(config->usart);
Zisis Adamos7235b092021-03-30 12:20:46 +02001246
1247 /* Enable TC interrupt so we can signal correct TX done */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001248 LL_USART_EnableIT_TC(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001249
1250 /* set source address */
1251 data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.buffer;
1252 data->dma_tx.blk_cfg.block_size = data->dma_tx.buffer_length;
1253
Erwan Gouriou13c23512021-03-01 11:59:57 +01001254 ret = dma_config(data->dma_tx.dma_dev, data->dma_tx.dma_channel,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001255 &data->dma_tx.dma_cfg);
1256
1257 if (ret != 0) {
1258 LOG_ERR("dma tx config error!");
1259 return -EINVAL;
1260 }
1261
Erwan Gouriou13c23512021-03-01 11:59:57 +01001262 if (dma_start(data->dma_tx.dma_dev, data->dma_tx.dma_channel)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001263 LOG_ERR("UART err: TX DMA start failed!");
1264 return -EFAULT;
1265 }
1266
1267 /* Start TX timer */
1268 async_timer_start(&data->dma_tx.timeout_work, data->dma_tx.timeout);
1269
Erwan Gourioua3de3df2021-09-14 09:27:56 +02001270#ifdef CONFIG_PM
Erwan Gouriou79ff6452021-09-21 09:34:09 +02001271
1272 /* Do not allow system to suspend until transmission has completed */
Gerard Marull-Paretas5a71eeb2022-01-20 16:06:28 +01001273 uart_stm32_pm_policy_state_lock_get(dev);
Erwan Gourioua3de3df2021-09-14 09:27:56 +02001274#endif
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001275
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001276 /* Enable TX DMA requests */
1277 uart_stm32_dma_tx_enable(dev);
1278
1279 return 0;
1280}
1281
1282static int uart_stm32_async_rx_enable(const struct device *dev,
1283 uint8_t *rx_buf, size_t buf_size, int32_t timeout)
1284{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001285 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001286 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001287 int ret;
1288
Erwan Gouriou13c23512021-03-01 11:59:57 +01001289 if (data->dma_rx.dma_dev == NULL) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001290 return -ENODEV;
1291 }
1292
1293 if (data->dma_rx.enabled) {
1294 LOG_WRN("RX was already enabled");
1295 return -EBUSY;
1296 }
1297
1298 data->dma_rx.offset = 0;
1299 data->dma_rx.buffer = rx_buf;
1300 data->dma_rx.buffer_length = buf_size;
1301 data->dma_rx.counter = 0;
1302 data->dma_rx.timeout = timeout;
1303
1304 /* Disable RX interrupts to let DMA to handle it */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001305 LL_USART_DisableIT_RXNE(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001306
1307 data->dma_rx.blk_cfg.block_size = buf_size;
1308 data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer;
1309
Erwan Gouriou13c23512021-03-01 11:59:57 +01001310 ret = dma_config(data->dma_rx.dma_dev, data->dma_rx.dma_channel,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001311 &data->dma_rx.dma_cfg);
1312
1313 if (ret != 0) {
1314 LOG_ERR("UART ERR: RX DMA config failed!");
1315 return -EINVAL;
1316 }
1317
Erwan Gouriou13c23512021-03-01 11:59:57 +01001318 if (dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001319 LOG_ERR("UART ERR: RX DMA start failed!");
1320 return -EFAULT;
1321 }
1322
1323 /* Enable RX DMA requests */
1324 uart_stm32_dma_rx_enable(dev);
1325
1326 /* Enable IRQ IDLE to define the end of a
1327 * RX DMA transaction.
1328 */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001329 LL_USART_ClearFlag_IDLE(config->usart);
1330 LL_USART_EnableIT_IDLE(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001331
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001332 LL_USART_EnableIT_ERROR(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001333
1334 /* Request next buffer */
1335 async_evt_rx_buf_request(data);
1336
1337 LOG_DBG("async rx enabled");
1338
1339 return ret;
1340}
1341
1342static int uart_stm32_async_tx_abort(const struct device *dev)
1343{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001344 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001345 size_t tx_buffer_length = data->dma_tx.buffer_length;
1346 struct dma_status stat;
1347
1348 if (tx_buffer_length == 0) {
1349 return -EFAULT;
1350 }
1351
Francois Ramu962d6b12021-04-08 12:09:58 +02001352 (void)k_work_cancel_delayable(&data->dma_tx.timeout_work);
Erwan Gouriou13c23512021-03-01 11:59:57 +01001353 if (!dma_get_status(data->dma_tx.dma_dev,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001354 data->dma_tx.dma_channel, &stat)) {
1355 data->dma_tx.counter = tx_buffer_length - stat.pending_length;
1356 }
1357
Erwan Gouriou13c23512021-03-01 11:59:57 +01001358 dma_stop(data->dma_tx.dma_dev, data->dma_tx.dma_channel);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001359 async_evt_tx_abort(data);
1360
1361 return 0;
1362}
1363
1364static void uart_stm32_async_rx_timeout(struct k_work *work)
1365{
Yong Cong Sin731241f2022-01-19 12:07:51 +08001366 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1367 struct uart_dma_stream *rx_stream = CONTAINER_OF(dwork,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001368 struct uart_dma_stream, timeout_work);
1369 struct uart_stm32_data *data = CONTAINER_OF(rx_stream,
1370 struct uart_stm32_data, dma_rx);
1371 const struct device *dev = data->uart_dev;
1372
1373 LOG_DBG("rx timeout");
1374
1375 if (data->dma_rx.counter == data->dma_rx.buffer_length) {
1376 uart_stm32_async_rx_disable(dev);
1377 } else {
1378 uart_stm32_dma_rx_flush(dev);
1379 }
1380}
1381
1382static void uart_stm32_async_tx_timeout(struct k_work *work)
1383{
Yong Cong Sin731241f2022-01-19 12:07:51 +08001384 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1385 struct uart_dma_stream *tx_stream = CONTAINER_OF(dwork,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001386 struct uart_dma_stream, timeout_work);
1387 struct uart_stm32_data *data = CONTAINER_OF(tx_stream,
1388 struct uart_stm32_data, dma_tx);
1389 const struct device *dev = data->uart_dev;
1390
1391 uart_stm32_async_tx_abort(dev);
1392
1393 LOG_DBG("tx: async timeout");
1394}
1395
1396static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf,
1397 size_t len)
1398{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001399 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001400
1401 LOG_DBG("replace buffer (%d)", len);
1402 data->rx_next_buffer = buf;
1403 data->rx_next_buffer_len = len;
1404
1405 return 0;
1406}
1407
1408static int uart_stm32_async_init(const struct device *dev)
1409{
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001410 const struct uart_stm32_config *config = dev->config;
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001411 struct uart_stm32_data *data = dev->data;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001412
1413 data->uart_dev = dev;
1414
Erwan Gouriou13c23512021-03-01 11:59:57 +01001415 if (data->dma_rx.dma_dev != NULL) {
1416 if (!device_is_ready(data->dma_rx.dma_dev)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001417 return -ENODEV;
1418 }
1419 }
1420
Erwan Gouriou13c23512021-03-01 11:59:57 +01001421 if (data->dma_tx.dma_dev != NULL) {
Georgij Cernysiov64c804a2022-05-06 08:47:03 +02001422 if (!device_is_ready(data->dma_tx.dma_dev)) {
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001423 return -ENODEV;
1424 }
1425 }
1426
1427 /* Disable both TX and RX DMA requests */
1428 uart_stm32_dma_rx_disable(dev);
1429 uart_stm32_dma_tx_disable(dev);
1430
Francois Ramu962d6b12021-04-08 12:09:58 +02001431 k_work_init_delayable(&data->dma_rx.timeout_work,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001432 uart_stm32_async_rx_timeout);
Francois Ramu962d6b12021-04-08 12:09:58 +02001433 k_work_init_delayable(&data->dma_tx.timeout_work,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001434 uart_stm32_async_tx_timeout);
1435
1436 /* Configure dma rx config */
1437 memset(&data->dma_rx.blk_cfg, 0, sizeof(data->dma_rx.blk_cfg));
1438
1439#if defined(CONFIG_SOC_SERIES_STM32F1X) || \
1440 defined(CONFIG_SOC_SERIES_STM32F2X) || \
1441 defined(CONFIG_SOC_SERIES_STM32F4X) || \
1442 defined(CONFIG_SOC_SERIES_STM32L1X)
1443 data->dma_rx.blk_cfg.source_address =
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001444 LL_USART_DMA_GetRegAddr(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001445#else
1446 data->dma_rx.blk_cfg.source_address =
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001447 LL_USART_DMA_GetRegAddr(config->usart,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001448 LL_USART_DMA_REG_DATA_RECEIVE);
1449#endif
1450
1451 data->dma_rx.blk_cfg.dest_address = 0; /* dest not ready */
1452
1453 if (data->dma_rx.src_addr_increment) {
1454 data->dma_rx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1455 } else {
1456 data->dma_rx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1457 }
1458
1459 if (data->dma_rx.dst_addr_increment) {
1460 data->dma_rx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1461 } else {
1462 data->dma_rx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1463 }
1464
1465 /* RX disable circular buffer */
1466 data->dma_rx.blk_cfg.source_reload_en = 0;
1467 data->dma_rx.blk_cfg.dest_reload_en = 0;
1468 data->dma_rx.blk_cfg.fifo_mode_control = data->dma_rx.fifo_threshold;
1469
1470 data->dma_rx.dma_cfg.head_block = &data->dma_rx.blk_cfg;
1471 data->dma_rx.dma_cfg.user_data = (void *)dev;
1472 data->rx_next_buffer = NULL;
1473 data->rx_next_buffer_len = 0;
1474
1475 /* Configure dma tx config */
1476 memset(&data->dma_tx.blk_cfg, 0, sizeof(data->dma_tx.blk_cfg));
1477
1478#if defined(CONFIG_SOC_SERIES_STM32F1X) || \
1479 defined(CONFIG_SOC_SERIES_STM32F2X) || \
1480 defined(CONFIG_SOC_SERIES_STM32F4X) || \
1481 defined(CONFIG_SOC_SERIES_STM32L1X)
1482 data->dma_tx.blk_cfg.dest_address =
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001483 LL_USART_DMA_GetRegAddr(config->usart);
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001484#else
1485 data->dma_tx.blk_cfg.dest_address =
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001486 LL_USART_DMA_GetRegAddr(config->usart,
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001487 LL_USART_DMA_REG_DATA_TRANSMIT);
1488#endif
1489
1490 data->dma_tx.blk_cfg.source_address = 0; /* not ready */
1491
1492 if (data->dma_tx.src_addr_increment) {
1493 data->dma_tx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1494 } else {
1495 data->dma_tx.blk_cfg.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1496 }
1497
1498 if (data->dma_tx.dst_addr_increment) {
1499 data->dma_tx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT;
1500 } else {
1501 data->dma_tx.blk_cfg.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE;
1502 }
1503
1504 data->dma_tx.blk_cfg.fifo_mode_control = data->dma_tx.fifo_threshold;
1505
1506 data->dma_tx.dma_cfg.head_block = &data->dma_tx.blk_cfg;
1507 data->dma_tx.dma_cfg.user_data = (void *)dev;
1508
1509 return 0;
1510}
1511
1512#endif /* CONFIG_UART_ASYNC_API */
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001513
Marcus Shawcroftd3ea5392016-10-24 08:38:49 +01001514static const struct uart_driver_api uart_stm32_driver_api = {
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001515 .poll_in = uart_stm32_poll_in,
1516 .poll_out = uart_stm32_poll_out,
Georgij Cernysiovc74c1312019-02-14 10:50:19 +01001517 .err_check = uart_stm32_err_check,
Daniel Leung4e1692f2021-05-26 12:33:37 -07001518#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
Pushpal Sidhuacd0e252019-01-07 13:52:24 -08001519 .configure = uart_stm32_configure,
1520 .config_get = uart_stm32_config_get,
Daniel Leung4e1692f2021-05-26 12:33:37 -07001521#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001522#ifdef CONFIG_UART_INTERRUPT_DRIVEN
1523 .fifo_fill = uart_stm32_fifo_fill,
1524 .fifo_read = uart_stm32_fifo_read,
1525 .irq_tx_enable = uart_stm32_irq_tx_enable,
1526 .irq_tx_disable = uart_stm32_irq_tx_disable,
1527 .irq_tx_ready = uart_stm32_irq_tx_ready,
Paul Sokolovsky0fdc9b52017-05-11 17:57:29 +03001528 .irq_tx_complete = uart_stm32_irq_tx_complete,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +01001529 .irq_rx_enable = uart_stm32_irq_rx_enable,
1530 .irq_rx_disable = uart_stm32_irq_rx_disable,
1531 .irq_rx_ready = uart_stm32_irq_rx_ready,
1532 .irq_err_enable = uart_stm32_irq_err_enable,
1533 .irq_err_disable = uart_stm32_irq_err_disable,
1534 .irq_is_pending = uart_stm32_irq_is_pending,
1535 .irq_update = uart_stm32_irq_update,
1536 .irq_callback_set = uart_stm32_irq_callback_set,
1537#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001538#ifdef CONFIG_UART_ASYNC_API
1539 .callback_set = uart_stm32_async_callback_set,
1540 .tx = uart_stm32_async_tx,
1541 .tx_abort = uart_stm32_async_tx_abort,
1542 .rx_enable = uart_stm32_async_rx_enable,
1543 .rx_disable = uart_stm32_async_rx_disable,
1544 .rx_buf_rsp = uart_stm32_async_rx_buf_rsp,
1545#endif /* CONFIG_UART_ASYNC_API */
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001546};
1547
1548/**
1549 * @brief Initialize UART channel
1550 *
1551 * This routine is called to reset the chip in a quiescent state.
1552 * It is assumed that this function is called only once per UART.
1553 *
1554 * @param dev UART device struct
1555 *
1556 * @return 0
1557 */
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +02001558static int uart_stm32_init(const struct device *dev)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001559{
Gerard Marull-Paretas1674fec2022-01-18 16:58:32 +01001560 const struct uart_stm32_config *config = dev->config;
1561 struct uart_stm32_data *data = dev->data;
Kumar Galaa1b77fd2020-05-27 11:26:57 -05001562 uint32_t ll_parity;
1563 uint32_t ll_datawidth;
Erwan Gouriou0b9c5842020-10-16 17:20:00 +02001564 int err;
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001565
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001566 __uart_stm32_get_clock(dev);
Henrik Brix Andersen9456eca2022-08-08 16:05:16 +02001567
1568 if (!device_is_ready(data->clock)) {
1569 LOG_ERR("clock control device not ready");
1570 return -ENODEV;
1571 }
1572
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001573 /* enable clock */
Artur Lipowskibb857592022-05-10 12:18:28 +02001574 err = clock_control_on(data->clock, (clock_control_subsys_t)&config->pclken[0]);
1575 if (err != 0) {
1576 LOG_ERR("Could not enable (LP)UART clock");
1577 return err;
1578 }
1579
Erwan Gouriou1ef9e9e2022-08-04 11:08:15 +02001580 if (IS_ENABLED(STM32_UART_DOMAIN_CLOCK_SUPPORT) && (config->pclk_len > 1)) {
Artur Lipowskibb857592022-05-10 12:18:28 +02001581 err = clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
1582 (clock_control_subsys_t) &config->pclken[1],
1583 NULL);
1584 if (err != 0) {
Erwan Gouriou1ef9e9e2022-08-04 11:08:15 +02001585 LOG_ERR("Could not select UART domain clock");
Artur Lipowskibb857592022-05-10 12:18:28 +02001586 return err;
1587 }
Erwan Gouriou9062e972018-12-07 11:09:28 +01001588 }
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001589
Erwan Gouriou252a6232020-06-05 10:57:52 +02001590 /* Configure dt provided device signals when available */
Gerard Marull-Paretas21a27192021-09-07 16:39:45 +02001591 err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
Erwan Gouriou0b9c5842020-10-16 17:20:00 +02001592 if (err < 0) {
1593 return err;
Erwan Gouriou252a6232020-06-05 10:57:52 +02001594 }
1595
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001596 LL_USART_Disable(config->usart);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001597
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001598 /* TX/RX direction */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001599 LL_USART_SetTransferDirection(config->usart,
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001600 LL_USART_DIRECTION_TX_RX);
1601
Pauli Salmenrinne30003ff2020-03-18 13:40:21 +02001602 /* Determine the datawidth and parity. If we use other parity than
1603 * 'none' we must use datawidth = 9 (to get 8 databit + 1 parity bit).
1604 */
1605 if (config->parity == 2) {
1606 /* 8 databit, 1 parity bit, parity even */
1607 ll_parity = LL_USART_PARITY_EVEN;
1608 ll_datawidth = LL_USART_DATAWIDTH_9B;
1609 } else if (config->parity == 1) {
1610 /* 8 databit, 1 parity bit, parity odd */
1611 ll_parity = LL_USART_PARITY_ODD;
1612 ll_datawidth = LL_USART_DATAWIDTH_9B;
1613 } else { /* Default to 8N0, but show warning if invalid value */
1614 if (config->parity != 0) {
1615 LOG_WRN("Invalid parity setting '%d'."
1616 "Defaulting to 'none'.", config->parity);
1617 }
1618 /* 8 databit, parity none */
1619 ll_parity = LL_USART_PARITY_NONE;
1620 ll_datawidth = LL_USART_DATAWIDTH_8B;
1621 }
1622
1623 /* Set datawidth and parity, 1 start bit, 1 stop bit */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001624 LL_USART_ConfigCharacter(config->usart,
Pauli Salmenrinne30003ff2020-03-18 13:40:21 +02001625 ll_datawidth,
1626 ll_parity,
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001627 LL_USART_STOPBITS_1);
1628
Georgij Cernysiov04da64d2019-02-08 18:39:35 +01001629 if (config->hw_flow_control) {
1630 uart_stm32_set_hwctrl(dev, LL_USART_HWCONTROL_RTS_CTS);
1631 }
1632
Pushpal Sidhuacd0e252019-01-07 13:52:24 -08001633 /* Set the default baudrate */
1634 uart_stm32_set_baudrate(dev, data->baud_rate);
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001635
Jonathan Hahn32f9dcf2022-01-01 23:41:19 +01001636 /* Enable the single wire / half-duplex mode */
1637 if (config->single_wire) {
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001638 LL_USART_EnableHalfDuplex(config->usart);
Jonathan Hahn32f9dcf2022-01-01 23:41:19 +01001639 }
1640
Peter Maxwell Warasila3c09c212022-05-09 16:28:51 -04001641#ifdef LL_USART_TXRX_SWAPPED
1642 if (config->tx_rx_swap) {
1643 LL_USART_SetTXRXSwap(config->usart, LL_USART_TXRX_SWAPPED);
1644 }
1645#endif
1646
Jonathan Hahn05cc2e12022-04-25 20:12:25 +02001647#ifdef LL_USART_RXPIN_LEVEL_INVERTED
1648 if (config->rx_invert) {
1649 LL_USART_SetRXPinLevel(config->usart, LL_USART_RXPIN_LEVEL_INVERTED);
1650 }
1651#endif
1652
1653#ifdef LL_USART_TXPIN_LEVEL_INVERTED
1654 if (config->tx_invert) {
1655 LL_USART_SetTXPinLevel(config->usart, LL_USART_TXPIN_LEVEL_INVERTED);
1656 }
1657#endif
1658
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001659 LL_USART_Enable(config->usart);
Erwan Gouriouda210ba2017-09-21 15:20:53 +02001660
Erwan Gouriou80b8c502018-06-13 11:32:38 +02001661#ifdef USART_ISR_TEACK
1662 /* Wait until TEACK flag is set */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001663 while (!(LL_USART_IsActiveFlag_TEACK(config->usart))) {
Anas Nashif4c322582019-06-04 10:52:23 -04001664 }
Erwan Gouriou80b8c502018-06-13 11:32:38 +02001665#endif /* !USART_ISR_TEACK */
1666
1667#ifdef USART_ISR_REACK
Erwan Gouriou13a96572018-06-18 18:01:06 +02001668 /* Wait until REACK flag is set */
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001669 while (!(LL_USART_IsActiveFlag_REACK(config->usart))) {
Anas Nashif4c322582019-06-04 10:52:23 -04001670 }
Erwan Gouriou80b8c502018-06-13 11:32:38 +02001671#endif /* !USART_ISR_REACK */
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001672
Gerard Marull-Paretase101cc72022-01-25 16:21:36 +01001673#if defined(CONFIG_PM) || \
1674 defined(CONFIG_UART_INTERRUPT_DRIVEN) || \
1675 defined(CONFIG_UART_ASYNC_API)
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001676 config->irq_config_func(dev);
Gerard Marull-Paretase101cc72022-01-25 16:21:36 +01001677#endif /* CONFIG_PM || CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API */
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001678
Erwan Gouriou4422de52022-08-03 14:39:48 +02001679#if defined(CONFIG_PM)
1680 if (config->wakeup_source) {
1681 /* Enable ability to wakeup device in Stop mode
1682 * Effect depends on CONFIG_PM_DEVICE status:
1683 * CONFIG_PM_DEVICE=n : Always active
1684 * CONFIG_PM_DEVICE=y : Controlled by pm_device_wakeup_enable()
1685 */
1686 LL_USART_EnableInStopMode(config->usart);
1687 }
1688#endif /* CONFIG_PM */
1689
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001690#ifdef CONFIG_UART_ASYNC_API
1691 return uart_stm32_async_init(dev);
1692#else
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001693 return 0;
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001694#endif
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001695}
1696
Erwan Gourioua439c042022-08-03 14:39:59 +02001697#ifdef CONFIG_PM_DEVICE
1698static void uart_stm32_suspend_setup(const struct device *dev)
1699{
1700 const struct uart_stm32_config *config = dev->config;
1701
1702#ifdef USART_ISR_BUSY
1703 /* Make sure that no USART transfer is on-going */
1704 while (LL_USART_IsActiveFlag_BUSY(config->usart) == 1) {
1705 }
1706#endif
1707 while (LL_USART_IsActiveFlag_TC(config->usart) == 0) {
1708 }
1709#ifdef USART_ISR_REACK
1710 /* Make sure that USART is ready for reception */
1711 while (LL_USART_IsActiveFlag_REACK(config->usart) == 0) {
1712 }
1713#endif
1714 /* Clear OVERRUN flag */
1715 LL_USART_ClearFlag_ORE(config->usart);
1716}
1717
1718static int uart_stm32_pm_action(const struct device *dev,
1719 enum pm_device_action action)
1720{
1721 const struct uart_stm32_config *config = dev->config;
1722 struct uart_stm32_data *data = dev->data;
1723 int err;
1724
1725
1726 switch (action) {
1727 case PM_DEVICE_ACTION_RESUME:
1728 /* Set pins to active state */
1729 err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
1730 if (err < 0) {
1731 return err;
1732 }
1733
1734 /* enable clock */
1735 err = clock_control_on(data->clock, (clock_control_subsys_t)&config->pclken[0]);
1736 if (err != 0) {
1737 LOG_ERR("Could not enable (LP)UART clock");
1738 return err;
1739 }
1740 break;
1741 case PM_DEVICE_ACTION_SUSPEND:
1742 uart_stm32_suspend_setup(dev);
Erwan Gourioue89e4b52022-08-03 10:47:34 +02001743 /* Stop device clock. Note: fixed clocks are not handled yet. */
Erwan Gourioua439c042022-08-03 14:39:59 +02001744 err = clock_control_off(data->clock, (clock_control_subsys_t)&config->pclken[0]);
1745 if (err != 0) {
1746 LOG_ERR("Could not enable (LP)UART clock");
1747 return err;
1748 }
1749
1750 /* Move pins to sleep state */
1751 err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
Erwan Gourioue89e4b52022-08-03 10:47:34 +02001752 if (err == -ENOENT) {
1753 /* Warn but don't block PM suspend */
1754 LOG_WRN("(LP)UART pinctrl sleep state not available ");
1755 } else if (err < 0) {
Erwan Gourioua439c042022-08-03 14:39:59 +02001756 return err;
1757 }
1758 break;
1759 default:
1760 return -ENOTSUP;
1761 }
1762
1763 return 0;
1764}
1765#endif /* CONFIG_PM_DEVICE */
1766
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001767#ifdef CONFIG_UART_ASYNC_API
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001768
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001769/* src_dev and dest_dev should be 'MEMORY' or 'PERIPHERAL'. */
1770#define UART_DMA_CHANNEL_INIT(index, dir, dir_cap, src_dev, dest_dev) \
Francois Ramu30fd0222021-06-18 15:52:30 +02001771 .dma_dev = DEVICE_DT_GET(STM32_DMA_CTLR(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001772 .dma_channel = DT_INST_DMAS_CELL_BY_NAME(index, dir, channel), \
1773 .dma_cfg = { \
Francois Ramu744e1dc2021-08-09 16:32:57 +02001774 .dma_slot = STM32_DMA_SLOT(index, dir, slot),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001775 .channel_direction = STM32_DMA_CONFIG_DIRECTION( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001776 STM32_DMA_CHANNEL_CONFIG(index, dir)),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001777 .channel_priority = STM32_DMA_CONFIG_PRIORITY( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001778 STM32_DMA_CHANNEL_CONFIG(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001779 .source_data_size = STM32_DMA_CONFIG_##src_dev##_DATA_SIZE(\
Francois Ramu30fd0222021-06-18 15:52:30 +02001780 STM32_DMA_CHANNEL_CONFIG(index, dir)),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001781 .dest_data_size = STM32_DMA_CONFIG_##dest_dev##_DATA_SIZE(\
Francois Ramu30fd0222021-06-18 15:52:30 +02001782 STM32_DMA_CHANNEL_CONFIG(index, dir)),\
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001783 .source_burst_length = 1, /* SINGLE transfer */ \
1784 .dest_burst_length = 1, \
1785 .block_count = 1, \
1786 .dma_callback = uart_stm32_dma_##dir##_cb, \
1787 }, \
1788 .src_addr_increment = STM32_DMA_CONFIG_##src_dev##_ADDR_INC( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001789 STM32_DMA_CHANNEL_CONFIG(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001790 .dst_addr_increment = STM32_DMA_CONFIG_##dest_dev##_ADDR_INC( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001791 STM32_DMA_CHANNEL_CONFIG(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001792 .fifo_threshold = STM32_DMA_FEATURES_FIFO_THRESHOLD( \
Francois Ramu30fd0222021-06-18 15:52:30 +02001793 STM32_DMA_FEATURES(index, dir)), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001794
1795#endif
1796
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001797#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) || \
1798 defined(CONFIG_PM)
Erwan Gouriou62755132020-02-28 14:54:37 +01001799#define STM32_UART_IRQ_HANDLER_DECL(index) \
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001800 static void uart_stm32_irq_config_func_##index(const struct device *dev);
Erwan Gouriou62755132020-02-28 14:54:37 +01001801#define STM32_UART_IRQ_HANDLER(index) \
Tomasz Bursztykae18fcbb2020-04-30 20:33:38 +02001802static void uart_stm32_irq_config_func_##index(const struct device *dev) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001803{ \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001804 IRQ_CONNECT(DT_INST_IRQN(index), \
1805 DT_INST_IRQ(index, priority), \
Kumar Galac49b1622020-12-11 10:12:30 -06001806 uart_stm32_isr, DEVICE_DT_INST_GET(index), \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001807 0); \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001808 irq_enable(DT_INST_IRQN(index)); \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001809}
1810#else
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001811#define STM32_UART_IRQ_HANDLER_DECL(index) /* Not used */
1812#define STM32_UART_IRQ_HANDLER(index) /* Not used */
1813#endif
1814
Gerard Marull-Paretase101cc72022-01-25 16:21:36 +01001815#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) || \
1816 defined(CONFIG_PM)
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001817#define STM32_UART_IRQ_HANDLER_FUNC(index) \
1818 .irq_config_func = uart_stm32_irq_config_func_##index,
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001819#else
1820#define STM32_UART_IRQ_HANDLER_FUNC(index) /* Not used */
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001821#endif
1822
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001823#ifdef CONFIG_UART_ASYNC_API
1824#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) \
Artur Lipowskibb857592022-05-10 12:18:28 +02001825.dma_##dir = { \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001826 COND_CODE_1(DT_INST_DMAS_HAS_NAME(index, dir), \
1827 (UART_DMA_CHANNEL_INIT(index, dir, DIR, src, dest)), \
Artur Lipowskibb857592022-05-10 12:18:28 +02001828 (NULL)) \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001829 },
1830
1831#else
1832#define UART_DMA_CHANNEL(index, dir, DIR, src, dest)
1833#endif
1834
Erwan Gouriou4422de52022-08-03 14:39:48 +02001835#ifdef CONFIG_PM
1836#define STM32_UART_PM_WAKEUP(index) \
1837 .wakeup_source = DT_INST_PROP(index, wakeup_source),
1838#else
1839#define STM32_UART_PM_WAKEUP(index) /* Not used */
1840#endif
1841
Erwan Gouriou62755132020-02-28 14:54:37 +01001842#define STM32_UART_INIT(index) \
Gerard Marull-Paretase3f49072021-09-09 22:41:35 +02001843STM32_UART_IRQ_HANDLER_DECL(index) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001844 \
Gerard Marull-Paretas5dc6ed32021-12-23 12:33:03 +01001845PINCTRL_DT_INST_DEFINE(index); \
Erwan Gouriou252a6232020-06-05 10:57:52 +02001846 \
Artur Lipowskibb857592022-05-10 12:18:28 +02001847static const struct stm32_pclken pclken_##index[] = \
1848 STM32_DT_INST_CLOCKS(index);\
1849 \
Erwan Gouriou62755132020-02-28 14:54:37 +01001850static const struct uart_stm32_config uart_stm32_cfg_##index = { \
Gerard Marull-Paretas32a3a022022-01-25 16:14:12 +01001851 .usart = (USART_TypeDef *)DT_INST_REG_ADDR(index), \
Artur Lipowskibb857592022-05-10 12:18:28 +02001852 .pclken = pclken_##index, \
1853 .pclk_len = DT_INST_NUM_CLOCKS(index), \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001854 .hw_flow_control = DT_INST_PROP(index, hw_flow_control), \
Gerard Marull-Paretasc759a352021-11-17 14:01:42 +01001855 .parity = DT_INST_ENUM_IDX_OR(index, parity, UART_CFG_PARITY_NONE), \
Gerard Marull-Paretas21a27192021-09-07 16:39:45 +02001856 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
Artur Lipowskibb857592022-05-10 12:18:28 +02001857 .single_wire = DT_INST_PROP_OR(index, single_wire, false), \
Alexander Mihajlovic4ff49912022-04-02 15:21:01 +02001858 .tx_rx_swap = DT_INST_PROP_OR(index, tx_rx_swap, false), \
Erwan Gouriou4422de52022-08-03 14:39:48 +02001859 .rx_invert = DT_INST_PROP(index, rx_invert), \
1860 .tx_invert = DT_INST_PROP(index, tx_invert), \
Gerard Marull-Paretase101cc72022-01-25 16:21:36 +01001861 STM32_UART_IRQ_HANDLER_FUNC(index) \
Erwan Gouriou4422de52022-08-03 14:39:48 +02001862 STM32_UART_PM_WAKEUP(index) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001863}; \
1864 \
Erwan Gouriou62755132020-02-28 14:54:37 +01001865static struct uart_stm32_data uart_stm32_data_##index = { \
Erwan Gouriouccd6b722020-06-05 09:48:29 +02001866 .baud_rate = DT_INST_PROP(index, current_speed), \
Shlomi Vakninb4afd1a2021-01-16 18:44:24 +02001867 UART_DMA_CHANNEL(index, rx, RX, PERIPHERAL, MEMORY) \
1868 UART_DMA_CHANNEL(index, tx, TX, MEMORY, PERIPHERAL) \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001869}; \
1870 \
Erwan Gourioua439c042022-08-03 14:39:59 +02001871PM_DEVICE_DT_INST_DEFINE(index, uart_stm32_pm_action); \
1872 \
Kumar Galac49b1622020-12-11 10:12:30 -06001873DEVICE_DT_INST_DEFINE(index, \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001874 &uart_stm32_init, \
Erwan Gourioua439c042022-08-03 14:39:59 +02001875 PM_DEVICE_DT_INST_GET(index), \
Erwan Gouriou62755132020-02-28 14:54:37 +01001876 &uart_stm32_data_##index, &uart_stm32_cfg_##index, \
Maureen Helmad145052021-10-14 09:38:10 -05001877 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
Florian Vaussardf27a5a32017-05-01 15:21:52 +02001878 &uart_stm32_driver_api); \
1879 \
Erwan Gouriou62755132020-02-28 14:54:37 +01001880STM32_UART_IRQ_HANDLER(index)
Erwan Gouriou8c079e92016-11-14 11:53:52 +01001881
Martí Bolívar7e0eed92020-05-06 11:23:07 -07001882DT_INST_FOREACH_STATUS_OKAY(STM32_UART_INIT)