Skip to content

Commit 00378b5

Browse files
asmellbyaescolar
authored andcommitted
drivers: serial: gecko: Add device power management
Add basic device power management to USART driver. The initial implementation only ensures that the TX FIFO is flushed before allowing the system to go to sleep by polling the TXIDLE status register. This fixes an issue where the last 1-2 characters would be lost if transmitted immediately before going to deep sleep. Signed-off-by: Aksel Skauge Mellbye <[email protected]>
1 parent e0b748e commit 00378b5

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

drivers/serial/Kconfig.gecko

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ config UART_GECKO
1212
select SOC_GECKO_USART
1313
select PINCTRL if SOC_FAMILY_SILABS_S1
1414
select CLOCK_CONTROL if SOC_FAMILY_SILABS_S2
15+
select PM_DEVICE if PM && SOC_FAMILY_SILABS_S2
1516
help
1617
Enable the Gecko uart driver.

drivers/serial/uart_gecko.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <errno.h>
99
#include <zephyr/drivers/uart.h>
1010
#include <zephyr/irq.h>
11+
#include <zephyr/pm/device.h>
1112
#include <em_usart.h>
1213
#include <em_cmu.h>
1314
#include <soc.h>
@@ -488,6 +489,29 @@ static int uart_gecko_init(const struct device *dev)
488489
return 0;
489490
}
490491

492+
#ifdef CONFIG_PM_DEVICE
493+
static int uart_gecko_pm_action(const struct device *dev, enum pm_device_action action)
494+
{
495+
const struct uart_gecko_config *config = dev->config;
496+
497+
switch (action) {
498+
case PM_DEVICE_ACTION_SUSPEND:
499+
/* Wait for TX FIFO to flush before suspending */
500+
while (!(USART_StatusGet(config->base) & USART_STATUS_TXIDLE)) {
501+
}
502+
break;
503+
504+
case PM_DEVICE_ACTION_RESUME:
505+
break;
506+
507+
default:
508+
return -ENOTSUP;
509+
}
510+
511+
return 0;
512+
}
513+
#endif
514+
491515
static const struct uart_driver_api uart_gecko_driver_api = {
492516
.poll_in = uart_gecko_poll_in,
493517
.poll_out = uart_gecko_poll_out,
@@ -686,6 +710,7 @@ DT_INST_FOREACH_STATUS_OKAY(GECKO_UART_INIT)
686710
#define GECKO_USART_INIT(idx) \
687711
PINCTRL_DT_INST_DEFINE(idx); \
688712
GECKO_USART_IRQ_HANDLER_DECL(idx); \
713+
PM_DEVICE_DT_INST_DEFINE(idx, uart_gecko_pm_action); \
689714
\
690715
static const struct uart_gecko_config usart_gecko_cfg_##idx = { \
691716
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \
@@ -697,7 +722,7 @@ DT_INST_FOREACH_STATUS_OKAY(GECKO_UART_INIT)
697722
\
698723
static struct uart_gecko_data usart_gecko_data_##idx; \
699724
\
700-
DEVICE_DT_INST_DEFINE(idx, uart_gecko_init, NULL, \
725+
DEVICE_DT_INST_DEFINE(idx, uart_gecko_init, PM_DEVICE_DT_INST_GET(idx),\
701726
&usart_gecko_data_##idx, \
702727
&usart_gecko_cfg_##idx, PRE_KERNEL_1, \
703728
CONFIG_SERIAL_INIT_PRIORITY, \
@@ -710,6 +735,7 @@ DT_INST_FOREACH_STATUS_OKAY(GECKO_UART_INIT)
710735
VALIDATE_GECKO_UART_RTS_CTS_PIN_LOCATIONS(idx); \
711736
\
712737
GECKO_USART_IRQ_HANDLER_DECL(idx); \
738+
PM_DEVICE_DT_INST_DEFINE(idx, uart_gecko_pm_action); \
713739
\
714740
static const struct uart_gecko_config usart_gecko_cfg_##idx = { \
715741
.base = (USART_TypeDef *)DT_INST_REG_ADDR(idx), \
@@ -725,7 +751,7 @@ DT_INST_FOREACH_STATUS_OKAY(GECKO_UART_INIT)
725751
\
726752
static struct uart_gecko_data usart_gecko_data_##idx; \
727753
\
728-
DEVICE_DT_INST_DEFINE(idx, uart_gecko_init, NULL, \
754+
DEVICE_DT_INST_DEFINE(idx, uart_gecko_init, PM_DEVICE_DT_INST_GET(idx),\
729755
&usart_gecko_data_##idx, \
730756
&usart_gecko_cfg_##idx, PRE_KERNEL_1, \
731757
CONFIG_SERIAL_INIT_PRIORITY, \

0 commit comments

Comments
 (0)