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 <Artur.Lipowski@hidglobal.com>
This commit is contained in:
parent
3c09c21fda
commit
bb8575962d
2 changed files with 48 additions and 17 deletions
|
@ -38,6 +38,14 @@
|
|||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL);
|
||||
|
||||
/* This symbol takes the value 1 if one of the device instances */
|
||||
/* is configured in dts with an optional clock */
|
||||
#if STM32_DT_INST_DEV_OPT_CLOCK_SUPPORT
|
||||
#define STM32_UART_OPT_CLOCK_SUPPORT 1
|
||||
#else
|
||||
#define STM32_UART_OPT_CLOCK_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#define HAS_LPUART_1 (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), \
|
||||
st_stm32_lpuart, okay))
|
||||
|
||||
|
@ -93,8 +101,7 @@ static void uart_stm32_pm_policy_state_lock_put(const struct device *dev)
|
|||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static inline void uart_stm32_set_baudrate(const struct device *dev,
|
||||
uint32_t baud_rate)
|
||||
static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t baud_rate)
|
||||
{
|
||||
const struct uart_stm32_config *config = dev->config;
|
||||
struct uart_stm32_data *data = dev->data;
|
||||
|
@ -102,11 +109,20 @@ static inline void uart_stm32_set_baudrate(const struct device *dev,
|
|||
uint32_t clock_rate;
|
||||
|
||||
/* Get clock rate */
|
||||
if (clock_control_get_rate(data->clock,
|
||||
(clock_control_subsys_t *)&config->pclken,
|
||||
&clock_rate) < 0) {
|
||||
LOG_ERR("Failed call clock_control_get_rate");
|
||||
return;
|
||||
if (IS_ENABLED(STM32_UART_OPT_CLOCK_SUPPORT) && (config->pclk_len > 1)) {
|
||||
if (clock_control_get_rate(data->clock,
|
||||
(clock_control_subsys_t)&config->pclken[1],
|
||||
&clock_rate) < 0) {
|
||||
LOG_ERR("Failed call clock_control_get_rate(pclken[1])");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (clock_control_get_rate(data->clock,
|
||||
(clock_control_subsys_t)&config->pclken[0],
|
||||
&clock_rate) < 0) {
|
||||
LOG_ERR("Failed call clock_control_get_rate(pclken[0])");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_LPUART_1
|
||||
|
@ -1550,9 +1566,20 @@ static int uart_stm32_init(const struct device *dev)
|
|||
|
||||
__uart_stm32_get_clock(dev);
|
||||
/* enable clock */
|
||||
if (clock_control_on(data->clock,
|
||||
(clock_control_subsys_t *)&config->pclken) != 0) {
|
||||
return -EIO;
|
||||
err = clock_control_on(data->clock, (clock_control_subsys_t)&config->pclken[0]);
|
||||
if (err != 0) {
|
||||
LOG_ERR("Could not enable (LP)UART clock");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(STM32_UART_OPT_CLOCK_SUPPORT) && (config->pclk_len > 1)) {
|
||||
err = clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE),
|
||||
(clock_control_subsys_t) &config->pclken[1],
|
||||
NULL);
|
||||
if (err != 0) {
|
||||
LOG_ERR("Could not select UART source clock");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure dt provided device signals when available */
|
||||
|
@ -1697,10 +1724,10 @@ static void uart_stm32_irq_config_func_##index(const struct device *dev) \
|
|||
|
||||
#ifdef CONFIG_UART_ASYNC_API
|
||||
#define UART_DMA_CHANNEL(index, dir, DIR, src, dest) \
|
||||
.dma_##dir = { \
|
||||
.dma_##dir = { \
|
||||
COND_CODE_1(DT_INST_DMAS_HAS_NAME(index, dir), \
|
||||
(UART_DMA_CHANNEL_INIT(index, dir, DIR, src, dest)), \
|
||||
(NULL)) \
|
||||
(NULL)) \
|
||||
},
|
||||
|
||||
#else
|
||||
|
@ -1712,15 +1739,17 @@ STM32_UART_IRQ_HANDLER_DECL(index) \
|
|||
\
|
||||
PINCTRL_DT_INST_DEFINE(index); \
|
||||
\
|
||||
static const struct stm32_pclken pclken_##index[] = \
|
||||
STM32_DT_INST_CLOCKS(index);\
|
||||
\
|
||||
static const struct uart_stm32_config uart_stm32_cfg_##index = { \
|
||||
.usart = (USART_TypeDef *)DT_INST_REG_ADDR(index), \
|
||||
.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
|
||||
.enr = DT_INST_CLOCKS_CELL(index, bits) \
|
||||
}, \
|
||||
.pclken = pclken_##index, \
|
||||
.pclk_len = DT_INST_NUM_CLOCKS(index), \
|
||||
.hw_flow_control = DT_INST_PROP(index, hw_flow_control), \
|
||||
.parity = DT_INST_ENUM_IDX_OR(index, parity, UART_CFG_PARITY_NONE), \
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \
|
||||
.single_wire = DT_INST_PROP_OR(index, single_wire, false), \
|
||||
.single_wire = DT_INST_PROP_OR(index, single_wire, false), \
|
||||
.tx_rx_swap = DT_INST_PROP_OR(index, tx_rx_swap, false), \
|
||||
STM32_UART_IRQ_HANDLER_FUNC(index) \
|
||||
}; \
|
||||
|
|
|
@ -21,7 +21,9 @@ struct uart_stm32_config {
|
|||
/* USART instance */
|
||||
USART_TypeDef *usart;
|
||||
/* clock subsystem driving this peripheral */
|
||||
struct stm32_pclken pclken;
|
||||
const struct stm32_pclken *pclken;
|
||||
/* number of clock subsystems */
|
||||
size_t pclk_len;
|
||||
/* initial hardware flow control, 1 for RTS/CTS */
|
||||
bool hw_flow_control;
|
||||
/* initial parity, 0 for none, 1 for odd, 2 for even */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue