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, @@ -231,8 +231,10 @@ static int uart_npcx_fifo_fill(const struct device *dev, const uint8_t *tx_data,
}
#ifdef CONFIG_PM
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 */
inst->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN);
#endif /* CONFIG_UART_NPCX_FIFO_EX */
#endif /* CONFIG_PM */
k_spin_unlock(&data->lock, key);
@ -258,32 +260,49 @@ static void uart_npcx_irq_tx_enable(const struct device *dev) @@ -258,32 +260,49 @@ static void uart_npcx_irq_tx_enable(const struct device *dev)
{
const struct uart_npcx_config *const config = dev->config;
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)
inst->UICTRL |= BIT(NPCX_UICTRL_ETI);
#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);
k_spin_unlock(&data->lock, key);
#endif
k_spin_unlock(&data->lock, key);
}
static void uart_npcx_irq_tx_disable(const struct device *dev)
{
const struct uart_npcx_config *const config = dev->config;
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)
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
struct uart_npcx_data *data = dev->data;
k_spinlock_key_t key = k_spin_lock(&data->lock);
inst->UFTCTL &= ~(BIT(NPCX_UFTCTL_TEMPTY_EN));
key = k_spin_lock(&data->lock);
inst->UFTCTL &= ~BIT(NPCX_UFTCTL_TEMPTY_EN);
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)
@ -310,7 +329,7 @@ static int uart_npcx_irq_tx_complete(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 */
#if defined(CONFIG_UART_NPCX_FIFO_EX)
return inst->UTXFLV == 0;
return (inst->UTXFLV == 0) && !IS_BIT_SET(inst->USTAT, NPCX_USTAT_XMIP);
#else
return IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP);
#endif
@ -334,9 +353,9 @@ static void uart_npcx_irq_rx_disable(const struct device *dev) @@ -334,9 +353,9 @@ static void uart_npcx_irq_rx_disable(const struct device *dev)
struct uart_reg *const inst = config->inst;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ERI));
inst->UICTRL &= ~BIT(NPCX_UICTRL_ERI);
#else
inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN));
inst->UFRCTL &= ~BIT(NPCX_UFRCTL_RNEMPTY_EN);
#endif
}
@ -370,7 +389,7 @@ static void uart_npcx_irq_err_disable(const struct device *dev) @@ -370,7 +389,7 @@ static void uart_npcx_irq_err_disable(const struct device *dev)
const struct uart_npcx_config *const config = dev->config;
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)
@ -743,7 +762,7 @@ static int uart_npcx_async_rx_disable(const struct device *dev) @@ -743,7 +762,7 @@ static int uart_npcx_async_rx_disable(const struct device *dev)
LOG_DBG("Async RX Disable");
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);
@ -858,10 +877,6 @@ static void uart_npcx_async_dma_rx_complete(const struct device *dev) @@ -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)
{
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
@ -882,8 +897,11 @@ static void uart_npcx_isr(const struct device *dev) @@ -882,8 +897,11 @@ static void uart_npcx_isr(const struct device *dev)
}
#endif
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
#ifdef CONFIG_UART_ASYNC_API
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;
/*
@ -935,10 +953,12 @@ static void uart_npcx_isr(const struct device *dev) @@ -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)
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) &&
IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP)) {
k_spinlock_key_t key = k_spin_lock(&data->lock);
@ -957,10 +977,10 @@ static void uart_npcx_isr(const struct device *dev) @@ -957,10 +977,10 @@ static void uart_npcx_isr(const struct device *dev)
}
#endif
}
#endif
#endif
#endif /* CONFIG_PM || CONFIG_UART_ASYNC_API */
#endif /* !CONFIG_UART_NPCX_FIFO_EX */
}
#endif
#endif /* CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API */
/* UART api functions */
static int uart_npcx_err_check(const struct device *dev)

Loading…
Cancel
Save