Skip to content

Commit 9f19359

Browse files
alvsunkartben
authored andcommitted
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 <[email protected]> Signed-off-by: Tom Chang <[email protected]> Signed-off-by: Mulin Chao <[email protected]>
1 parent bf0fd15 commit 9f19359

File tree

1 file changed

+44
-24
lines changed

1 file changed

+44
-24
lines changed

drivers/serial/uart_npcx.c

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,10 @@ static int uart_npcx_fifo_fill(const struct device *dev, const uint8_t *tx_data,
231231
}
232232
#ifdef CONFIG_PM
233233
uart_npcx_pm_policy_state_lock_get(data, UART_PM_POLICY_STATE_TX_FLAG);
234+
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
234235
/* Enable NXMIP interrupt in case ec enters deep sleep early */
235236
inst->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN);
237+
#endif /* CONFIG_UART_NPCX_FIFO_EX */
236238
#endif /* CONFIG_PM */
237239
k_spin_unlock(&data->lock, key);
238240

@@ -258,32 +260,49 @@ static void uart_npcx_irq_tx_enable(const struct device *dev)
258260
{
259261
const struct uart_npcx_config *const config = dev->config;
260262
struct uart_reg *const inst = config->inst;
263+
struct uart_npcx_data *data = dev->data;
264+
k_spinlock_key_t key = k_spin_lock(&data->lock);
261265

262266
#if defined(CONFIG_UART_NPCX_FIFO_EX)
263267
inst->UICTRL |= BIT(NPCX_UICTRL_ETI);
264268
#else
265-
struct uart_npcx_data *data = dev->data;
266-
k_spinlock_key_t key = k_spin_lock(&data->lock);
267-
268269
inst->UFTCTL |= BIT(NPCX_UFTCTL_TEMPTY_EN);
269-
k_spin_unlock(&data->lock, key);
270270
#endif
271+
272+
k_spin_unlock(&data->lock, key);
271273
}
272274

273275
static void uart_npcx_irq_tx_disable(const struct device *dev)
274276
{
275277
const struct uart_npcx_config *const config = dev->config;
276278
struct uart_reg *const inst = config->inst;
279+
struct uart_npcx_data *data = dev->data;
280+
k_spinlock_key_t key;
277281

278282
#if defined(CONFIG_UART_NPCX_FIFO_EX)
279-
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ETI));
283+
#if defined(CONFIG_PM)
284+
/*
285+
* Since TBE is 1 does not mean that the Tx FIFO is empty, we need to check
286+
* the UTXFLV register to make sure that the Tx FIFO is empty.
287+
*/
288+
if (IS_BIT_SET(inst->UICTRL, NPCX_UICTRL_ETI) &&
289+
IS_BIT_SET(inst->UICTRL, NPCX_UICTRL_TBE) &&
290+
(inst->UTXFLV == 0)) {
291+
/* Wait for transmitting is completed */
292+
while (IS_BIT_SET(inst->USTAT, NPCX_USTAT_XMIP)) {
293+
;
294+
}
295+
uart_npcx_pm_policy_state_lock_put(data, UART_PM_POLICY_STATE_TX_FLAG);
296+
}
297+
#endif /* CONFIG_PM */
298+
key = k_spin_lock(&data->lock);
299+
inst->UICTRL &= ~BIT(NPCX_UICTRL_ETI);
300+
k_spin_unlock(&data->lock, key);
280301
#else
281-
struct uart_npcx_data *data = dev->data;
282-
k_spinlock_key_t key = k_spin_lock(&data->lock);
283-
284-
inst->UFTCTL &= ~(BIT(NPCX_UFTCTL_TEMPTY_EN));
302+
key = k_spin_lock(&data->lock);
303+
inst->UFTCTL &= ~BIT(NPCX_UFTCTL_TEMPTY_EN);
285304
k_spin_unlock(&data->lock, key);
286-
#endif
305+
#endif /* CONFIG_UART_NPCX_FIFO_EX */
287306
}
288307

289308
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)
310329

311330
/* Tx FIFO is empty or last byte is sending */
312331
#if defined(CONFIG_UART_NPCX_FIFO_EX)
313-
return inst->UTXFLV == 0;
332+
return (inst->UTXFLV == 0) && !IS_BIT_SET(inst->USTAT, NPCX_USTAT_XMIP);
314333
#else
315334
return IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP);
316335
#endif
@@ -334,9 +353,9 @@ static void uart_npcx_irq_rx_disable(const struct device *dev)
334353
struct uart_reg *const inst = config->inst;
335354

336355
#if defined(CONFIG_UART_NPCX_FIFO_EX)
337-
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ERI));
356+
inst->UICTRL &= ~BIT(NPCX_UICTRL_ERI);
338357
#else
339-
inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN));
358+
inst->UFRCTL &= ~BIT(NPCX_UFRCTL_RNEMPTY_EN);
340359
#endif
341360
}
342361

@@ -370,7 +389,7 @@ static void uart_npcx_irq_err_disable(const struct device *dev)
370389
const struct uart_npcx_config *const config = dev->config;
371390
struct uart_reg *const inst = config->inst;
372391

373-
inst->UICTRL &= ~(BIT(NPCX_UICTRL_EEI));
392+
inst->UICTRL &= ~BIT(NPCX_UICTRL_EEI);
374393
}
375394

376395
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)
743762
LOG_DBG("Async RX Disable");
744763

745764
key = irq_lock();
746-
inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN));
765+
inst->UFRCTL &= ~BIT(NPCX_UFRCTL_RNEMPTY_EN);
747766

748767
k_work_cancel_delayable(&rx_dma_params->timeout_work);
749768

@@ -858,10 +877,6 @@ static void uart_npcx_async_dma_rx_complete(const struct device *dev)
858877
static void uart_npcx_isr(const struct device *dev)
859878
{
860879
struct uart_npcx_data *data = dev->data;
861-
#if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API)
862-
const struct uart_npcx_config *const config = dev->config;
863-
struct uart_reg *const inst = config->inst;
864-
#endif
865880

866881
/*
867882
* Set pm constraint to prevent the system enter suspend state within
@@ -882,8 +897,11 @@ static void uart_npcx_isr(const struct device *dev)
882897
}
883898
#endif
884899

900+
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
885901
#ifdef CONFIG_UART_ASYNC_API
886902
if (data->async.user_callback) {
903+
const struct uart_npcx_config *const config = dev->config;
904+
struct uart_reg *const inst = config->inst;
887905
struct mdma_reg *const mdma_reg_base = config->mdma_reg_base;
888906

889907
/*
@@ -935,10 +953,12 @@ static void uart_npcx_isr(const struct device *dev)
935953
}
936954
}
937955
}
938-
#endif
956+
#endif /* CONFIG_UART_ASYNC_API */
939957

940-
#if !defined(CONFIG_UART_NPCX_FIFO_EX)
941958
#if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API)
959+
const struct uart_npcx_config *const config = dev->config;
960+
struct uart_reg *const inst = config->inst;
961+
942962
if (IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_NXMIP_EN) &&
943963
IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP)) {
944964
k_spinlock_key_t key = k_spin_lock(&data->lock);
@@ -957,10 +977,10 @@ static void uart_npcx_isr(const struct device *dev)
957977
}
958978
#endif
959979
}
960-
#endif
961-
#endif
980+
#endif /* CONFIG_PM || CONFIG_UART_ASYNC_API */
981+
#endif /* !CONFIG_UART_NPCX_FIFO_EX */
962982
}
963-
#endif
983+
#endif /* CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API */
964984

965985
/* UART api functions */
966986
static int uart_npcx_err_check(const struct device *dev)

0 commit comments

Comments
 (0)