drivers: serial: stm32 restore uart after lowpower

This adds a function to control the uart device during lowpower modes

Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
Francois Ramu 2021-01-27 10:27:33 +01:00 committed by Anas Nashif
parent 930df38e23
commit 3c18bcbf77
2 changed files with 68 additions and 1 deletions

View file

@ -1373,6 +1373,9 @@ static int uart_stm32_init(const struct device *dev)
#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API)
config->uconf.irq_config_func(dev);
#endif
#ifdef CONFIG_PM_DEVICE
data->pm_state = DEVICE_PM_ACTIVE_STATE;
#endif /* CONFIG_PM_DEVICE */
#ifdef CONFIG_UART_ASYNC_API
return uart_stm32_async_init(dev);
@ -1381,6 +1384,67 @@ static int uart_stm32_init(const struct device *dev)
#endif
}
#ifdef CONFIG_PM_DEVICE
static int uart_stm32_set_power_state(const struct device *dev,
uint32_t new_state)
{
USART_TypeDef *UartInstance = UART_STRUCT(dev);
struct uart_stm32_data *data = DEV_DATA(dev);
/* setting a low power mode */
if (new_state != DEVICE_PM_ACTIVE_STATE) {
/* Make sure that no USART transfer is on-going */
while (LL_USART_IsActiveFlag_BUSY(UartInstance) == 1) {
}
while (LL_USART_IsActiveFlag_TC(UartInstance) == 0) {
}
/* Make sure that USART is ready for reception */
while (LL_USART_IsActiveFlag_REACK(UartInstance) == 0) {
}
/* Clear OVERRUN flag */
LL_USART_ClearFlag_ORE(UartInstance);
/* Leave UartInstance unchanged */
}
data->pm_state = new_state;
/* UartInstance returning to active mode has nothing special to do */
return 0;
}
/**
* @brief disable the UART channel
*
* This routine is called to put the device in low power mode.
*
* @param dev UART device struct
*
* @return 0
*/
static int uart_stm32_pm_control(const struct device *dev,
uint32_t ctrl_command,
void *context, device_pm_cb cb,
void *arg)
{
struct uart_stm32_data *data = DEV_DATA(dev);
if (ctrl_command == DEVICE_PM_SET_POWER_STATE) {
uint32_t new_state = *((const uint32_t *)context);
if (new_state != data->pm_state) {
uart_stm32_set_power_state(dev, new_state);
}
} else {
__ASSERT_NO_MSG(ctrl_command == DEVICE_PM_GET_POWER_STATE);
*((uint32_t *)context) = data->pm_state;
}
if (cb) {
cb(dev, 0, context, arg);
}
return 0;
}
#endif /* CONFIG_PM_DEVICE */
#ifdef CONFIG_UART_ASYNC_API
#define DMA_CHANNEL_CONFIG(id, dir) \
DT_INST_DMAS_CELL_BY_NAME(id, dir, channel_config)
@ -1475,7 +1539,7 @@ static struct uart_stm32_data uart_stm32_data_##index = { \
\
DEVICE_DT_INST_DEFINE(index, \
&uart_stm32_init, \
device_pm_control_nop, \
&uart_stm32_pm_control, \
&uart_stm32_data_##index, &uart_stm32_cfg_##index, \
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&uart_stm32_driver_api); \

View file

@ -69,6 +69,9 @@ struct uart_stm32_data {
uint8_t *rx_next_buffer;
size_t rx_next_buffer_len;
#endif
#ifdef CONFIG_PM_DEVICE
uint32_t pm_state;
#endif
};
#endif /* ZEPHYR_DRIVERS_SERIAL_UART_STM32_H_ */