drivers: serial: npcx: add serial driver support for npck3

This commit adds serial driver support for npck3.

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:
Alvis Sun 2025-05-09 10:56:35 +08:00 committed by Benjamin Cabé
commit bf0fd155ae
4 changed files with 65 additions and 1 deletions

View file

@ -25,3 +25,10 @@ config UART_NPCX_USE_MDMA
select SERIAL_SUPPORT_ASYNC select SERIAL_SUPPORT_ASYNC
help help
Enable support for npcx UART DMA mode. Enable support for npcx UART DMA mode.
config UART_NPCX_FIFO_EX
bool "Extended NPCX UART FIFO driver support"
default y if DT_HAS_NUVOTON_NPCX_UART_NPCKN_ENABLED
help
This option enables the extended UART FIFO driver for NPCKN variant
of processors.

View file

@ -167,7 +167,11 @@ static int uart_npcx_rx_fifo_available(const struct device *dev)
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
/* True if at least one byte is in the Rx FIFO */ /* True if at least one byte is in the Rx FIFO */
#if defined(CONFIG_UART_NPCX_FIFO_EX)
return inst->URXFLV != 0;
#else
return IS_BIT_SET(inst->UFRSTS, NPCX_UFRSTS_RFIFO_NEMPTY_STS); return IS_BIT_SET(inst->UFRSTS, NPCX_UFRSTS_RFIFO_NEMPTY_STS);
#endif
} }
static void uart_npcx_dis_all_tx_interrupts(const struct device *dev) static void uart_npcx_dis_all_tx_interrupts(const struct device *dev)
@ -176,8 +180,12 @@ static void uart_npcx_dis_all_tx_interrupts(const struct device *dev)
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
/* Disable all Tx interrupts */ /* Disable all Tx interrupts */
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL &= ~BIT(NPCX_UICTRL_ETI);
#else
inst->UFTCTL &= ~(BIT(NPCX_UFTCTL_TEMPTY_LVL_EN) | BIT(NPCX_UFTCTL_TEMPTY_EN) | inst->UFTCTL &= ~(BIT(NPCX_UFTCTL_TEMPTY_LVL_EN) | BIT(NPCX_UFTCTL_TEMPTY_EN) |
BIT(NPCX_UFTCTL_NXMIP_EN)); BIT(NPCX_UFTCTL_NXMIP_EN));
#endif
} }
static void uart_npcx_clear_rx_fifo(const struct device *dev) static void uart_npcx_clear_rx_fifo(const struct device *dev)
@ -201,7 +209,11 @@ static int uart_npcx_tx_fifo_ready(const struct device *dev)
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
/* True if the Tx FIFO is not completely full */ /* True if the Tx FIFO is not completely full */
#if defined(CONFIG_UART_NPCX_FIFO_EX)
return inst->UTXFLV != NPCK_SZ_UART_FIFO;
#else
return !(GET_FIELD(inst->UFTSTS, NPCX_UFTSTS_TEMPTY_LVL) == 0); return !(GET_FIELD(inst->UFTSTS, NPCX_UFTSTS_TEMPTY_LVL) == 0);
#endif
} }
static int uart_npcx_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) static int uart_npcx_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size)
@ -246,22 +258,32 @@ 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;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL |= BIT(NPCX_UICTRL_ETI);
#else
struct uart_npcx_data *data = dev->data; struct uart_npcx_data *data = dev->data;
k_spinlock_key_t 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
} }
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;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ETI));
#else
struct uart_npcx_data *data = dev->data; struct uart_npcx_data *data = dev->data;
k_spinlock_key_t 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
} }
static bool uart_npcx_irq_tx_is_enabled(const struct device *dev) static bool uart_npcx_irq_tx_is_enabled(const struct device *dev)
@ -269,7 +291,11 @@ static bool uart_npcx_irq_tx_is_enabled(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;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
return IS_BIT_SET(inst->UICTRL, NPCX_UICTRL_ETI);
#else
return IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_TEMPTY_EN); return IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_TEMPTY_EN);
#endif
} }
static int uart_npcx_irq_tx_ready(const struct device *dev) static int uart_npcx_irq_tx_ready(const struct device *dev)
@ -283,7 +309,11 @@ static int uart_npcx_irq_tx_complete(const struct device *dev)
struct uart_reg *const inst = config->inst; struct uart_reg *const inst = config->inst;
/* 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)
return inst->UTXFLV == 0;
#else
return IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP); return IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP);
#endif
} }
static void uart_npcx_irq_rx_enable(const struct device *dev) static void uart_npcx_irq_rx_enable(const struct device *dev)
@ -291,7 +321,11 @@ static void uart_npcx_irq_rx_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;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL |= BIT(NPCX_UICTRL_ERI);
#else
inst->UFRCTL |= BIT(NPCX_UFRCTL_RNEMPTY_EN); inst->UFRCTL |= BIT(NPCX_UFRCTL_RNEMPTY_EN);
#endif
} }
static void uart_npcx_irq_rx_disable(const struct device *dev) static void uart_npcx_irq_rx_disable(const struct device *dev)
@ -299,7 +333,11 @@ static void uart_npcx_irq_rx_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;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UICTRL &= ~(BIT(NPCX_UICTRL_ERI));
#else
inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN)); inst->UFRCTL &= ~(BIT(NPCX_UFRCTL_RNEMPTY_EN));
#endif
} }
static bool uart_npcx_irq_rx_is_enabled(const struct device *dev) static bool uart_npcx_irq_rx_is_enabled(const struct device *dev)
@ -307,7 +345,11 @@ static bool uart_npcx_irq_rx_is_enabled(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;
#if defined(CONFIG_UART_NPCX_FIFO_EX)
return IS_BIT_SET(inst->UICTRL, NPCX_UICTRL_ERI);
#else
return IS_BIT_SET(inst->UFRCTL, NPCX_UFRCTL_RNEMPTY_EN); return IS_BIT_SET(inst->UFRCTL, NPCX_UFRCTL_RNEMPTY_EN);
#endif
} }
static int uart_npcx_irq_rx_ready(const struct device *dev) static int uart_npcx_irq_rx_ready(const struct device *dev)
@ -895,6 +937,7 @@ static void uart_npcx_isr(const struct device *dev)
} }
#endif #endif
#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)
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)) {
@ -915,6 +958,7 @@ static void uart_npcx_isr(const struct device *dev)
#endif #endif
} }
#endif #endif
#endif
} }
#endif #endif
@ -1060,8 +1104,12 @@ static int uart_npcx_init(const struct device *dev)
/* Initialize UART FIFO if mode is interrupt driven */ /* Initialize UART FIFO if mode is interrupt driven */
#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) #if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API)
#if defined(CONFIG_UART_NPCX_FIFO_EX)
inst->UFCTRL |= BIT(NPCK_FIFO_EN);
#else
/* Enable the UART FIFO mode */ /* Enable the UART FIFO mode */
inst->UMDSL |= BIT(NPCX_UMDSL_FIFO_MD); inst->UMDSL |= BIT(NPCX_UMDSL_FIFO_MD);
#endif
/* Disable all UART tx FIFO interrupts */ /* Disable all UART tx FIFO interrupts */
uart_npcx_dis_all_tx_interrupts(dev); uart_npcx_dis_all_tx_interrupts(dev);

View file

@ -53,7 +53,7 @@
}; };
uart1: serial@400c4000 { uart1: serial@400c4000 {
compatible = "nuvoton,npcx-uart"; compatible = "nuvoton,npcx-uart", "nuvoton,npcx-uart-npckn";
reg = <0x400C4000 0x2000>; reg = <0x400C4000 0x2000>;
interrupts = <23 3>; interrupts = <23 3>;
clocks = <&pcc NPCX_CLOCK_BUS_APB2 NPCX_PWDWN_CTL1 4>; clocks = <&pcc NPCX_CLOCK_BUS_APB2 NPCX_PWDWN_CTL1 4>;

View file

@ -0,0 +1,9 @@
# Copyright (c) 2025 Nuvoton Technology Corporation.
# SPDX-License-Identifier: Apache-2.0
description: |
Nuvoton npcx serial uart for npckn variant
compatible: "nuvoton,npcx-uart-npckn"
include: nuvoton,npcx-uart.yaml