@@ -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+ \
22762320STM32_UART_IRQ_HANDLER_DECL(index) \
22772321 \
22782322PINCTRL_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+ \
22802329static 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 \
0 commit comments