Skip to content

Commit bb85759

Browse files
r2r0MaureenHelm
authored andcommitted
stm32: Allow UARTs to use alternate clocks.
Add support for an alternate clock. If available, alternate clock is enabled and used to get the device clock rate. Based on: #45053. Signed-off-by: Artur Lipowski <[email protected]>
1 parent 3c09c21 commit bb85759

File tree

2 files changed

+48
-17
lines changed

2 files changed

+48
-17
lines changed

drivers/serial/uart_stm32.c

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@
3838
#include <zephyr/logging/log.h>
3939
LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL);
4040

41+
/* This symbol takes the value 1 if one of the device instances */
42+
/* is configured in dts with an optional clock */
43+
#if STM32_DT_INST_DEV_OPT_CLOCK_SUPPORT
44+
#define STM32_UART_OPT_CLOCK_SUPPORT 1
45+
#else
46+
#define STM32_UART_OPT_CLOCK_SUPPORT 0
47+
#endif
48+
4149
#define HAS_LPUART_1 (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), \
4250
st_stm32_lpuart, okay))
4351

@@ -93,20 +101,28 @@ static void uart_stm32_pm_policy_state_lock_put(const struct device *dev)
93101
}
94102
#endif /* CONFIG_PM */
95103

96-
static inline void uart_stm32_set_baudrate(const struct device *dev,
97-
uint32_t baud_rate)
104+
static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t baud_rate)
98105
{
99106
const struct uart_stm32_config *config = dev->config;
100107
struct uart_stm32_data *data = dev->data;
101108

102109
uint32_t clock_rate;
103110

104111
/* Get clock rate */
105-
if (clock_control_get_rate(data->clock,
106-
(clock_control_subsys_t *)&config->pclken,
107-
&clock_rate) < 0) {
108-
LOG_ERR("Failed call clock_control_get_rate");
109-
return;
112+
if (IS_ENABLED(STM32_UART_OPT_CLOCK_SUPPORT) && (config->pclk_len > 1)) {
113+
if (clock_control_get_rate(data->clock,
114+
(clock_control_subsys_t)&config->pclken[1],
115+
&clock_rate) < 0) {
116+
LOG_ERR("Failed call clock_control_get_rate(pclken[1])");
117+
return;
118+
}
119+
} else {
120+
if (clock_control_get_rate(data->clock,
121+
(clock_control_subsys_t)&config->pclken[0],
122+
&clock_rate) < 0) {
123+
LOG_ERR("Failed call clock_control_get_rate(pclken[0])");
124+
return;
125+
}
110126
}
111127

112128
#if HAS_LPUART_1
@@ -1550,9 +1566,20 @@ static int uart_stm32_init(const struct device *dev)
15501566

15511567
__uart_stm32_get_clock(dev);
15521568
/* enable clock */
1553-
if (clock_control_on(data->clock,
1554-
(clock_control_subsys_t *)&config->pclken) != 0) {
1555-
return -EIO;
1569+
err = clock_control_on(data->clock, (clock_control_subsys_t)&config->pclken[0]);
1570+
if (err != 0) {
1571+
LOG_ERR("Could not enable (LP)UART clock");
1572+
return err;
1573+
}
1574+
1575+
if (IS_ENABLED(STM32_UART_OPT_CLOCK_SUPPORT) && (config->pclk_len > 1)) {
1576+
err = clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
1577+
(clock_control_subsys_t) &config->pclken[1],
1578+
NULL);
1579+
if (err != 0) {
1580+
LOG_ERR("Could not select UART source clock");
1581+
return err;
1582+
}
15561583
}
15571584

15581585
/* Configure dt provided device signals when available */
@@ -1697,10 +1724,10 @@ static void uart_stm32_irq_config_func_##index(const struct device *dev) \
16971724

16981725
#ifdef CONFIG_UART_ASYNC_API
16991726
#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) \
1700-
.dma_##dir = { \
1727+
.dma_##dir = { \
17011728
COND_CODE_1(DT_INST_DMAS_HAS_NAME(index, dir), \
17021729
(UART_DMA_CHANNEL_INIT(index, dir, DIR, src, dest)), \
1703-
(NULL)) \
1730+
(NULL)) \
17041731
},
17051732

17061733
#else
@@ -1712,15 +1739,17 @@ STM32_UART_IRQ_HANDLER_DECL(index) \
17121739
\
17131740
PINCTRL_DT_INST_DEFINE(index); \
17141741
\
1742+
static const struct stm32_pclken pclken_##index[] = \
1743+
STM32_DT_INST_CLOCKS(index);\
1744+
\
17151745
static const struct uart_stm32_config uart_stm32_cfg_##index = { \
17161746
.usart = (USART_TypeDef *)DT_INST_REG_ADDR(index), \
1717-
.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
1718-
.enr = DT_INST_CLOCKS_CELL(index, bits) \
1719-
}, \
1747+
.pclken = pclken_##index, \
1748+
.pclk_len = DT_INST_NUM_CLOCKS(index), \
17201749
.hw_flow_control = DT_INST_PROP(index, hw_flow_control), \
17211750
.parity = DT_INST_ENUM_IDX_OR(index, parity, UART_CFG_PARITY_NONE), \
17221751
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
1723-
.single_wire = DT_INST_PROP_OR(index, single_wire, false), \
1752+
.single_wire = DT_INST_PROP_OR(index, single_wire, false), \
17241753
.tx_rx_swap = DT_INST_PROP_OR(index, tx_rx_swap, false), \
17251754
STM32_UART_IRQ_HANDLER_FUNC(index) \
17261755
}; \

drivers/serial/uart_stm32.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ struct uart_stm32_config {
2121
/* USART instance */
2222
USART_TypeDef *usart;
2323
/* clock subsystem driving this peripheral */
24-
struct stm32_pclken pclken;
24+
const struct stm32_pclken *pclken;
25+
/* number of clock subsystems */
26+
size_t pclk_len;
2527
/* initial hardware flow control, 1 for RTS/CTS */
2628
bool hw_flow_control;
2729
/* initial parity, 0 for none, 1 for odd, 2 for even */

0 commit comments

Comments
 (0)