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>
This commit is contained in:
parent
bf0fd155ae
commit
9f1935923b
1 changed files with 45 additions and 25 deletions
|
@ -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)
|
|||
{
|
||||
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));
|
||||
#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));
|
||||
#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);
|
||||
#endif
|
||||
#else
|
||||
key = k_spin_lock(&data->lock);
|
||||
inst->UFTCTL &= ~BIT(NPCX_UFTCTL_TEMPTY_EN);
|
||||
k_spin_unlock(&data->lock, key);
|
||||
#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)
|
|||
|
||||
/* 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)
|
|||
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)
|
|||
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)
|
|||
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)
|
|||
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)
|
|||
}
|
||||
#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)
|
|||
}
|
||||
}
|
||||
}
|
||||
#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)
|
|||
}
|
||||
#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…
Add table
Add a link
Reference in a new issue