Browse Source

driver: serial: npcx: add PM support for npck3 series.

This commit adds power management support to the UART driver for npck3
series chip.

Signed-off-by: Alvis Sun <yfsun@nuvoton.com>
Signed-off-by: Tom Chang <CHChang19@nuvoton.com>
Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
pull/85392/head
Alvis Sun 9 months ago committed by Benjamin Cabé
parent
commit
9f1935923b
  1. 68
      drivers/serial/uart_npcx.c

68
drivers/serial/uart_npcx.c

@ -231,8 +231,10 @@ static int uart_npcx_fifo_fill(const struct device *dev, const uint8_t *tx_data,
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
uart_npcx_pm_policy_state_lock_get(data, UART_PM_POLICY_STATE_TX_FLAG); uart_npcx_pm_policy_state_lock_get(data, UART_PM_POLICY_STATE_TX_FLAG);
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
/* Enable NXMIP interrupt in case ec enters deep sleep early */ /* Enable NXMIP interrupt in case ec enters deep sleep early */
inst->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN); inst->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN);
#endif /* CONFIG_UART_NPCX_FIFO_EX */
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
k_spin_unlock(&data->lock, key); k_spin_unlock(&data->lock, key);
@ -258,32 +260,49 @@ static void uart_npcx_irq_tx_enable(const struct device *dev)
{ {
const struct uart_npcx_config *const config = dev->config; const struct uart_npcx_config *const config = dev->config;
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
struct uart_npcx_data *data = dev->data;
k_spinlock_key_t key = k_spin_lock(&data->lock);
#if defined(CONFIG_UART_NPCX_FIFO_EX) #if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL |= BIT(NPCX_UICTRL_ETI); inst->UICTRL |= BIT(NPCX_UICTRL_ETI);
#else #else
struct uart_npcx_data *data = dev->data;
k_spinlock_key_t key = k_spin_lock(&data->lock);
inst->UFTCTL |= BIT(NPCX_UFTCTL_TEMPTY_EN); inst->UFTCTL |= BIT(NPCX_UFTCTL_TEMPTY_EN);
k_spin_unlock(&data->lock, key);
#endif #endif
k_spin_unlock(&data->lock, key);
} }
static void uart_npcx_irq_tx_disable(const struct device *dev) static void uart_npcx_irq_tx_disable(const struct device *dev)
{ {
const struct uart_npcx_config *const config = dev->config; const struct uart_npcx_config *const config = dev->config;
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
struct uart_npcx_data *data = dev->data;
k_spinlock_key_t key;
#if defined(CONFIG_UART_NPCX_FIFO_EX) #if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ETI)); #if defined(CONFIG_PM)
/*
* Since TBE is 1 does not mean that the Tx FIFO is empty, we need to check
* the UTXFLV register to make sure that the Tx FIFO is empty.
*/
if (IS_BIT_SET(inst->UICTRL, NPCX_UICTRL_ETI) &&
IS_BIT_SET(inst->UICTRL, NPCX_UICTRL_TBE) &&
(inst->UTXFLV == 0)) {
/* Wait for transmitting is completed */
while (IS_BIT_SET(inst->USTAT, NPCX_USTAT_XMIP)) {
;
}
uart_npcx_pm_policy_state_lock_put(data, UART_PM_POLICY_STATE_TX_FLAG);
}
#endif /* CONFIG_PM */
key = k_spin_lock(&data->lock);
inst->UICTRL &= ~BIT(NPCX_UICTRL_ETI);
k_spin_unlock(&data->lock, key);
#else #else
struct uart_npcx_data *data = dev->data; key = k_spin_lock(&data->lock);
k_spinlock_key_t key = k_spin_lock(&data->lock); inst->UFTCTL &= ~BIT(NPCX_UFTCTL_TEMPTY_EN);
inst->UFTCTL &= ~(BIT(NPCX_UFTCTL_TEMPTY_EN));
k_spin_unlock(&data->lock, key); k_spin_unlock(&data->lock, key);
#endif #endif /* CONFIG_UART_NPCX_FIFO_EX */
} }
static bool uart_npcx_irq_tx_is_enabled(const struct device *dev) static bool uart_npcx_irq_tx_is_enabled(const struct device *dev)
@ -310,7 +329,7 @@ static int uart_npcx_irq_tx_complete(const struct device *dev)
/* Tx FIFO is empty or last byte is sending */ /* Tx FIFO is empty or last byte is sending */
#if defined(CONFIG_UART_NPCX_FIFO_EX) #if defined(CONFIG_UART_NPCX_FIFO_EX)
return inst->UTXFLV == 0; return (inst->UTXFLV == 0) && !IS_BIT_SET(inst->USTAT, NPCX_USTAT_XMIP);
#else #else
return IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP); return IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP);
#endif #endif
@ -334,9 +353,9 @@ static void uart_npcx_irq_rx_disable(const struct device *dev)
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
#if defined(CONFIG_UART_NPCX_FIFO_EX) #if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ERI)); inst->UICTRL &= ~BIT(NPCX_UICTRL_ERI);
#else #else
inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN)); inst->UFRCTL &= ~BIT(NPCX_UFRCTL_RNEMPTY_EN);
#endif #endif
} }
@ -370,7 +389,7 @@ static void uart_npcx_irq_err_disable(const struct device *dev)
const struct uart_npcx_config *const config = dev->config; const struct uart_npcx_config *const config = dev->config;
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
inst->UICTRL &= ~(BIT(NPCX_UICTRL_EEI)); inst->UICTRL &= ~BIT(NPCX_UICTRL_EEI);
} }
static int uart_npcx_irq_is_pending(const struct device *dev) static int uart_npcx_irq_is_pending(const struct device *dev)
@ -743,7 +762,7 @@ static int uart_npcx_async_rx_disable(const struct device *dev)
LOG_DBG("Async RX Disable"); LOG_DBG("Async RX Disable");
key = irq_lock(); key = irq_lock();
inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN)); inst->UFRCTL &= ~BIT(NPCX_UFRCTL_RNEMPTY_EN);
k_work_cancel_delayable(&rx_dma_params->timeout_work); k_work_cancel_delayable(&rx_dma_params->timeout_work);
@ -858,10 +877,6 @@ static void uart_npcx_async_dma_rx_complete(const struct device *dev)
static void uart_npcx_isr(const struct device *dev) static void uart_npcx_isr(const struct device *dev)
{ {
struct uart_npcx_data *data = dev->data; struct uart_npcx_data *data = dev->data;
#if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API)
const struct uart_npcx_config *const config = dev->config;
struct uart_reg *const inst = config->inst;
#endif
/* /*
* Set pm constraint to prevent the system enter suspend state within * Set pm constraint to prevent the system enter suspend state within
@ -882,8 +897,11 @@ static void uart_npcx_isr(const struct device *dev)
} }
#endif #endif
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
#ifdef CONFIG_UART_ASYNC_API #ifdef CONFIG_UART_ASYNC_API
if (data->async.user_callback) { if (data->async.user_callback) {
const struct uart_npcx_config *const config = dev->config;
struct uart_reg *const inst = config->inst;
struct mdma_reg *const mdma_reg_base = config->mdma_reg_base; struct mdma_reg *const mdma_reg_base = config->mdma_reg_base;
/* /*
@ -935,10 +953,12 @@ static void uart_npcx_isr(const struct device *dev)
} }
} }
} }
#endif #endif /* CONFIG_UART_ASYNC_API */
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
#if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API) #if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API)
const struct uart_npcx_config *const config = dev->config;
struct uart_reg *const inst = config->inst;
if (IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_NXMIP_EN) && if (IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_NXMIP_EN) &&
IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP)) { IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP)) {
k_spinlock_key_t key = k_spin_lock(&data->lock); k_spinlock_key_t key = k_spin_lock(&data->lock);
@ -957,10 +977,10 @@ static void uart_npcx_isr(const struct device *dev)
} }
#endif #endif
} }
#endif #endif /* CONFIG_PM || CONFIG_UART_ASYNC_API */
#endif #endif /* !CONFIG_UART_NPCX_FIFO_EX */
} }
#endif #endif /* CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API */
/* UART api functions */ /* UART api functions */
static int uart_npcx_err_check(const struct device *dev) static int uart_npcx_err_check(const struct device *dev)

Loading…
Cancel
Save