diff --git a/drivers/serial/uart_npcx.c b/drivers/serial/uart_npcx.c index 4d32f9b160c..fc0303bcfd8 100644 --- a/drivers/serial/uart_npcx.c +++ b/drivers/serial/uart_npcx.c @@ -34,6 +34,7 @@ struct uart_npcx_config { struct uart_npcx_data { /* Baud rate */ uint32_t baud_rate; + struct miwu_dev_callback uart_rx_cb; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t user_cb; void *user_data; @@ -209,6 +210,12 @@ static void uart_npcx_isr(const struct device *dev) { struct uart_npcx_data *data = DRV_DATA(dev); + /* Refresh console expired time if got UART Rx event */ + if (IS_ENABLED(CONFIG_UART_CONSOLE_INPUT_EXPIRED) && + uart_npcx_irq_rx_ready(dev)) { + npcx_power_console_is_in_use_refresh(); + } + if (data->user_cb) { data->user_cb(dev, data->user_data); } @@ -285,6 +292,15 @@ static int uart_npcx_err_check(const struct device *dev) return err; } +static __unused void uart_npcx_rx_wk_isr(const struct device *dev, + struct npcx_wui *wui) +{ + /* Refresh console expired time if got UART Rx wake-up event */ + if (IS_ENABLED(CONFIG_UART_CONSOLE_INPUT_EXPIRED)) { + npcx_power_console_is_in_use_refresh(); + } +} + /* UART driver registration */ static const struct uart_driver_api uart_npcx_driver_api = { .poll_in = uart_npcx_poll_in, @@ -311,7 +327,7 @@ static const struct uart_driver_api uart_npcx_driver_api = { static int uart_npcx_init(const struct device *dev) { const struct uart_npcx_config *const config = DRV_CONFIG(dev); - const struct uart_npcx_data *const data = DRV_DATA(dev); + struct uart_npcx_data *const data = DRV_DATA(dev); struct uart_reg *const inst = HAL_INSTANCE(dev); const struct device *const clk_dev = device_get_binding(NPCX_CLK_CTRL_NAME); @@ -366,17 +382,22 @@ static int uart_npcx_init(const struct device *dev) config->uconf.irq_config_func(dev); #endif -#if defined(CONFIG_PM) - /* - * Configure the UART wake-up event triggered from a falling edge - * on CR_SIN pin. No need for callback function. - */ - npcx_miwu_interrupt_configure(&config->uart_rx_wui, - NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_LOW); + if (IS_ENABLED(CONFIG_PM)) { + /* Initialize a miwu device input and its callback function */ + npcx_miwu_init_dev_callback(&data->uart_rx_cb, + &config->uart_rx_wui, + uart_npcx_rx_wk_isr, dev); + npcx_miwu_manage_dev_callback(&data->uart_rx_cb, true); + /* + * Configure the UART wake-up event triggered from a falling + * edge on CR_SIN pin. No need for callback function. + */ + npcx_miwu_interrupt_configure(&config->uart_rx_wui, + NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_LOW); - /* Enable irq of interrupt-input module */ - npcx_miwu_irq_enable(&config->uart_rx_wui); -#endif + /* Enable irq of interrupt-input module */ + npcx_miwu_irq_enable(&config->uart_rx_wui); + } /* Configure pin-mux for uart device */ npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1); diff --git a/soc/arm/nuvoton_npcx/common/soc_power.h b/soc/arm/nuvoton_npcx/common/soc_power.h new file mode 100644 index 00000000000..d11cb15c45d --- /dev/null +++ b/soc/arm/nuvoton_npcx/common/soc_power.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NUVOTON_NPCX_SOC_POWER_H_ +#define _NUVOTON_NPCX_SOC_POWER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Receive whether the module for the console is in use. + * + * @return 1 if console is in use. Otherwise + * @return + * - True if the console is in use. + * - False otherwise, the module for console is reday to enter low power mode. + */ +bool npcx_power_console_is_in_use(void); + +/** + * @brief Notify the power module that the module for the console is in use. + * + * Notify the power module that the module for the console is in use. It also + * extends expired time by CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT. + */ +void npcx_power_console_is_in_use_refresh(void); + +/** + * @brief Set expired time-out directly for the console is in use. + * + * @param timeout Expired time-out for the console is in use. + */ +void npcx_power_set_console_in_use_timeout(int64_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* _NUVOTON_NPCX_SOC_POWER_H_ */ diff --git a/soc/arm/nuvoton_npcx/npcx7/power.c b/soc/arm/nuvoton_npcx/npcx7/power.c index 19637edc6fa..ce15fcd2f65 100644 --- a/soc/arm/nuvoton_npcx/npcx7/power.c +++ b/soc/arm/nuvoton_npcx/npcx7/power.c @@ -82,6 +82,27 @@ enum { NPCX_STANDARD_WAKE_UP, }; +#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED +static int64_t expired_timeout = CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT; +static int64_t console_expired_time = CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT; + +/* Platform specific power control functions */ +bool npcx_power_console_is_in_use(void) +{ + return (k_uptime_get() < console_expired_time); +} + +void npcx_power_console_is_in_use_refresh(void) +{ + console_expired_time = k_uptime_get() + expired_timeout; +} + +void npcx_power_set_console_in_use_timeout(int64_t timeout) +{ + expired_timeout = timeout; +} +#endif + static void npcx_power_enter_system_sleep(int slp_mode, int wk_mode) { /* Disable interrupts */ diff --git a/soc/arm/nuvoton_npcx/npcx7/soc.h b/soc/arm/nuvoton_npcx/npcx7/soc.h index 4ef4de98119..a9b6b9ed1e8 100644 --- a/soc/arm/nuvoton_npcx/npcx7/soc.h +++ b/soc/arm/nuvoton_npcx/npcx7/soc.h @@ -19,5 +19,6 @@ #include #include #include +#include #endif /* _NUVOTON_NPCX_SOC_H_ */