Skip to content

Commit 3931c01

Browse files
committed
drivers: serial: stm32: Add reinitialization feature
The added reinitialization function helps PM logic restore peripheral functionality when clock context and register contents are lost in certain low-power modes. Signed-off-by: Kenneth J. Miller <[email protected]>
1 parent 2985006 commit 3931c01

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

drivers/serial/uart_stm32.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,29 @@ static int uart_stm32_registers_configure(const struct device *dev)
19551955
return 0;
19561956
}
19571957

1958+
#ifdef CONFIG_PM
1959+
/**
1960+
* @brief Reinitialization of UART context
1961+
*
1962+
* This function reenables clocks, and reconfigures the peripheral registers,
1963+
* which is required upon exiting certain low-power modes on select SoCs.
1964+
*
1965+
* @param direction PM state transition direction
1966+
* @param ctx UART device struct
1967+
*/
1968+
static void uart_stm32_reinit(uint8_t direction, void *ctx)
1969+
{
1970+
ARG_UNUSED(direction);
1971+
const struct device *dev = ctx;
1972+
1973+
if (uart_stm32_clocks_enable(dev)) {
1974+
return;
1975+
}
1976+
1977+
uart_stm32_registers_configure(dev);
1978+
}
1979+
#endif /* CONFIG_PM */
1980+
19581981
/**
19591982
* @brief Initialize UART channel
19601983
*
@@ -2007,6 +2030,15 @@ static int uart_stm32_init(const struct device *dev)
20072030
}
20082031
#endif /* CONFIG_PM */
20092032

2033+
#ifdef CONFIG_PM
2034+
if (config->reinit_states_size > 0) {
2035+
for (uint8_t i = 0; i < config->reinit_states_size; i++) {
2036+
pm_notifier_register(config->notifier, config->reinit_states[i].state,
2037+
config->reinit_states[i].substate_id);
2038+
}
2039+
}
2040+
#endif /* CONFIG_PM */
2041+
20102042
#ifdef CONFIG_UART_ASYNC_API
20112043
return uart_stm32_async_init(dev);
20122044
#else
@@ -2162,9 +2194,20 @@ static void uart_stm32_irq_config_func_##index(const struct device *dev) \
21622194
.wakeup_line = COND_CODE_1(DT_INST_NODE_HAS_PROP(index, wakeup_line), \
21632195
(DT_INST_PROP(index, wakeup_line)), \
21642196
(STM32_EXTI_LINE_NONE)),
2197+
2198+
#define STM32_UART_REINIT_STATES_INIT(index) \
2199+
static const struct pm_state_info reinit_states_##index[] \
2200+
= PM_STATE_INFO_LIST_FROM_DT_REINIT(DT_DRV_INST(index))
2201+
2202+
#define STM32_UART_REINIT_CFG_INIT(index) \
2203+
.notifier = &PM_NOTIFIER(DT_INST_DEP_ORD(index)), \
2204+
.reinit_states = reinit_states_##index, \
2205+
.reinit_states_size = ARRAY_SIZE(reinit_states_##index),
21652206
#else
21662207
#define STM32_UART_PM_WAKEUP(index) /* Not used */
2167-
#endif
2208+
#define STM32_UART_REINIT_STATES_INIT(index)
2209+
#define STM32_UART_REINIT_CFG_INIT(index)
2210+
#endif /* CONFIG_PM */
21682211

21692212
/* Ensure DTS doesn't present an incompatible parity configuration.
21702213
* Mark/space parity isn't supported on the STM32 family.
@@ -2273,10 +2316,16 @@ BUILD_ASSERT( \
22732316
#endif
22742317

22752318
#define STM32_UART_INIT(index) \
2319+
\
22762320
STM32_UART_IRQ_HANDLER_DECL(index) \
22772321
\
22782322
PINCTRL_DT_INST_DEFINE(index); \
22792323
\
2324+
STM32_UART_REINIT_STATES_INIT(index); \
2325+
\
2326+
PM_NOTIFIER_DEFINE(DT_INST_DEP_ORD(index), PM_STATE_EXIT, \
2327+
uart_stm32_reinit, DEVICE_DT_INST_GET(index)); \
2328+
\
22802329
static const struct stm32_pclken pclken_##index[] = \
22812330
STM32_DT_INST_CLOCKS(index);\
22822331
\
@@ -2309,6 +2358,7 @@ static const struct uart_stm32_config uart_stm32_cfg_##index = { \
23092358
.de_deassert_time = DT_INST_PROP(index, de_deassert_time), \
23102359
.de_invert = DT_INST_PROP(index, de_invert), \
23112360
STM32_UART_IRQ_HANDLER_FUNC(index) \
2361+
STM32_UART_REINIT_CFG_INIT(index) \
23122362
STM32_UART_PM_WAKEUP(index) \
23132363
}; \
23142364
\

drivers/serial/uart_stm32.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <zephyr/drivers/pinctrl.h>
1616
#include <zephyr/drivers/reset.h>
1717
#include <zephyr/drivers/uart.h>
18+
#include <zephyr/pm/pm.h>
1819

1920
#include <stm32_ll_usart.h>
2021

@@ -59,6 +60,9 @@ struct uart_stm32_config {
5960
/* Device defined as wake-up source */
6061
bool wakeup_source;
6162
uint32_t wakeup_line;
63+
struct pm_notifier *notifier;
64+
const struct pm_state_info *reinit_states;
65+
size_t reinit_states_size;
6266
#endif /* CONFIG_PM */
6367
};
6468

0 commit comments

Comments
 (0)