summaryrefslogtreecommitdiff
path: root/chip/npcx
diff options
context:
space:
mode:
authorCHLin <CHLIN56@nuvoton.com>2018-04-13 16:08:23 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-04-18 02:08:10 -0700
commit6f8c010eb587dd1f017ff369a6e645913205a3a7 (patch)
treeab2874f29e4d0b642a292d42362be1df2d657524 /chip/npcx
parentdcaf8edc47c1703a760eff4d9ea12f68f8af492c (diff)
downloadchrome-ec-6f8c010eb587dd1f017ff369a6e645913205a3a7.tar.gz
npcx7: uart: Add FIFO mode support
NPCX79nxB chips add UART FIFO support with 16-bytes of TX/RX buffers. This CL enables the UART FIFO mode when NPCX79nxB chips are used. The UART interrupt priority is decreased from 1 to 4 because now it has the capability to buffter data in the FIFO when ec is serving the interrupts with higher priority. BRANCH=none BUG=none TEST=No build errors for make buildall. TEST=stress test the uart port by shell command "while true; do echo 'taskinfo'>/dev/pts/19; sleep 0.1; done". Change-Id: Ib09c1b5550d0db249201fc4fdd8d3b28c24b8a8e Signed-off-by: CHLin <CHLIN56@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/1012002 Commit-Ready: CH Lin <chlin56@nuvoton.com> Tested-by: CH Lin <chlin56@nuvoton.com> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip/npcx')
-rw-r--r--chip/npcx/config_chip-npcx7.h4
-rw-r--r--chip/npcx/registers.h32
-rw-r--r--chip/npcx/uart.c105
3 files changed, 124 insertions, 17 deletions
diff --git a/chip/npcx/config_chip-npcx7.h b/chip/npcx/config_chip-npcx7.h
index d2cf002ee2..74a4c30c36 100644
--- a/chip/npcx/config_chip-npcx7.h
+++ b/chip/npcx/config_chip-npcx7.h
@@ -25,6 +25,10 @@
#define NPCX_EXT32K_OSC_SUPPORT /* External 32KHz crytal osc. input support */
#endif
+#if defined(CHIP_VARIANT_NPCX7M7W) || defined(CHIP_VARIANT_NPCX7M6XB)
+#define NPCX_UART_FIFO_SUPPORT
+#endif
+
#ifdef CHIP_VARIANT_NPCX7M7W
#define NPCX_WOV_SUPPORT /* Audio front-end for Wake-on-Voice support */
#endif
diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h
index e04a8a8797..dee7629540 100644
--- a/chip/npcx/registers.h
+++ b/chip/npcx/registers.h
@@ -292,7 +292,7 @@
#define NPCX_LFCGCTL2_XT_OSC_SL_EN 6
/******************************************************************************/
-/*CR UART Register */
+/* CR UART Register */
#define NPCX_UTBUF REG8(NPCX_CR_UART_BASE_ADDR + 0x000)
#define NPCX_URBUF REG8(NPCX_CR_UART_BASE_ADDR + 0x002)
#define NPCX_UICTRL REG8(NPCX_CR_UART_BASE_ADDR + 0x004)
@@ -301,6 +301,36 @@
#define NPCX_UMDSL REG8(NPCX_CR_UART_BASE_ADDR + 0x00A)
#define NPCX_UBAUD REG8(NPCX_CR_UART_BASE_ADDR + 0x00C)
#define NPCX_UPSR REG8(NPCX_CR_UART_BASE_ADDR + 0x00E)
+#ifdef NPCX_UART_FIFO_SUPPORT
+ /* UART registers only used for FIFO mode */
+#define NPCX_UFTSTS REG8(NPCX_CR_UART_BASE_ADDR + 0x020)
+#define NPCX_UFRSTS REG8(NPCX_CR_UART_BASE_ADDR + 0x022)
+#define NPCX_UFTCTL REG8(NPCX_CR_UART_BASE_ADDR + 0x024)
+#define NPCX_UFRCTL REG8(NPCX_CR_UART_BASE_ADDR + 0x026)
+
+/* UART FIFO register fields */
+#define NPCX_UMDSL_FIFO_MD 0
+
+#define NPCX_UFTSTS_TEMPTY_LVL FIELD(0, 5)
+#define NPCX_UFTSTS_TEMPTY_LVL_STS 5
+#define NPCX_UFTSTS_TFIFO_EMPTY_STS 6
+#define NPCX_UFTSTS_NXMIP 7
+
+#define NPCX_UFRSTS_RFULL_LVL_STS 5
+#define NPCX_UFRSTS_RFIFO_NEMPTY_STS 6
+#define NPCX_UFRSTS_ERR 7
+
+#define NPCX_UFTCTL_TEMPTY_LVL_SEL FIELD(0, 5)
+#define NPCX_UFTCTL_TEMPTY_LVL_EN 5
+#define NPCX_UFTCTL_TEMPTY_EN 6
+#define NPCX_UFTCTL_NXIMPEN 7
+
+#define NPCX_UFRCTL_RFULL_LVL_SEL FIELD(0, 5)
+#define NPCX_UFRCTL_RFULL_LVL_EN 5
+#define NPCX_UFRCTL_RNEMPTY_EN 6
+#define NPCX_UFRCTL_ERR_EN 7
+
+#endif
/******************************************************************************/
/* KBSCAN registers */
diff --git a/chip/npcx/uart.c b/chip/npcx/uart.c
index aa719ad640..384f71d8be 100644
--- a/chip/npcx/uart.c
+++ b/chip/npcx/uart.c
@@ -20,6 +20,57 @@
#include "uart.h"
#include "util.h"
+#ifdef NPCX_UART_FIFO_SUPPORT
+/* Enable UART Tx FIFO empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_EN() \
+ (SET_BIT(NPCX_UFTCTL, NPCX_UFTCTL_TEMPTY_EN))
+/* True if UART Tx FIFO empty interrupt is enabled */
+#define NPCX_UART_TX_EMPTY_INT_IS_EN() \
+ (IS_BIT_SET(NPCX_UFTCTL, NPCX_UFTCTL_TEMPTY_EN))
+/* Disable UART Tx FIFO empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_DIS() \
+ (CLEAR_BIT(NPCX_UFTCTL, NPCX_UFTCTL_TEMPTY_EN))
+/* True if the Tx FIFO is not completely full */
+#define NPCX_UART_TX_IS_READY() \
+ (!(GET_FIELD(NPCX_UFTSTS, NPCX_UFTSTS_TEMPTY_LVL) == 0))
+/*
+ * True if Tx is in progress
+ * (i.e. FIFO is not empty or last byte in TSFT (Transmit Shift register)
+ * is not sent)
+ */
+#define NPCX_UART_TX_IN_XMIT() \
+ (!IS_BIT_SET(NPCX_UFTSTS, NPCX_UFTSTS_NXMIP))
+
+/*
+ * Enable to generate interrupt when there is at least one byte
+ * in the receive FIFO
+ */
+#define NPCX_UART_RX_INT_EN() \
+ (SET_BIT(NPCX_UFRCTL, NPCX_UFRCTL_RNEMPTY_EN))
+/* True if at least one byte is in the receive FIFO */
+#define NPCX_UART_RX_IS_AVAILABLE() \
+ (IS_BIT_SET(NPCX_UFRSTS, NPCX_UFRSTS_RFIFO_NEMPTY_STS))
+#else
+/* Enable UART Tx buffer empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_EN() (NPCX_UICTRL |= 0x20)
+/* True if UART Tx buffer empty interrupt is enabled */
+#define NPCX_UART_TX_EMPTY_INT_IS_EN() (NPCX_UICTRL & 0x20)
+/* Disable UART Tx buffer empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_DIS() (NPCX_UICTRL &= ~0x20)
+/* True if 1-byte Tx buffer is empty */
+#define NPCX_UART_TX_IS_READY() (NPCX_UICTRL & 0x01)
+/*
+ * True if Tx is in progress
+ * (i.e. Tx buffer is not empty or last byte in TSFT (Transmit Shift register)
+ * is not sent)
+ */
+#define NPCX_UART_TX_IN_XMIT() (NPCX_USTAT & 0x40)
+ /* Enable to generate interrupt when there is data in the receive buffer */
+#define NPCX_UART_RX_INT_EN() (NPCX_UICTRL = 0x40)
+/* True if there is data in the 1-byte Receive buffer */
+#define NPCX_UART_RX_IS_AVAILABLE() (NPCX_UICTRL & 0x02)
+#endif
+
static int init_done;
#ifdef CONFIG_UART_PAD_SWITCH
@@ -111,7 +162,7 @@ void uart_tx_start(void)
#endif
/* If interrupt is already enabled, nothing to do */
- if (NPCX_UICTRL & 0x20)
+ if (NPCX_UART_TX_EMPTY_INT_IS_EN())
return;
/* Do not allow deep sleep while transmit in progress */
@@ -123,14 +174,15 @@ void uart_tx_start(void)
* UART where the FIFO only triggers the interrupt when its
* threshold is _crossed_, not just met.
*/
- NPCX_UICTRL |= 0x20;
+ NPCX_UART_TX_EMPTY_INT_EN();
task_trigger_irq(NPCX_IRQ_UART);
}
-void uart_tx_stop(void) /* Disable TX interrupt */
+void uart_tx_stop(void)
{
- NPCX_UICTRL &= ~0x20;
+ /* Disable TX interrupt */
+ NPCX_UART_TX_EMPTY_INT_DIS();
/*
* Re-allow deep sleep when transmiting on the default pad (deep sleep
@@ -142,28 +194,24 @@ void uart_tx_stop(void) /* Disable TX interrupt */
void uart_tx_flush(void)
{
- /* Wait for transmit FIFO empty */
- while (!(NPCX_UICTRL & 0x01))
- ;
- /* Wait for transmitting completed */
- while (NPCX_USTAT & 0x40)
+ /* Wait for transmit FIFO empty and last byte is sent */
+ while (NPCX_UART_TX_IN_XMIT())
;
}
int uart_tx_ready(void)
{
- return NPCX_UICTRL & 0x01; /*if TX FIFO is empty return 1*/
+ return NPCX_UART_TX_IS_READY();
}
int uart_tx_in_progress(void)
{
- /* Transmit is in progress if the TX busy bit is set. */
- return NPCX_USTAT & 0x40; /*BUSY bit , if busy return 1*/
+ return NPCX_UART_TX_IN_XMIT();
}
int uart_rx_available(void)
{
- int rx_available = NPCX_UICTRL & 0x02;
+ int rx_available = NPCX_UART_RX_IS_AVAILABLE();
if (rx_available && pad == UART_DEFAULT_PAD) {
#ifdef CONFIG_LOW_POWER_IDLE
@@ -201,7 +249,7 @@ void uart_clear_rx_fifo(int channel)
int scratch __attribute__ ((unused));
if (channel == 0) { /* suppose '0' is EC UART*/
/*if '1' that mean have a RX data on the FIFO register*/
- while ((NPCX_UICTRL & 0x02))
+ while (NPCX_UART_RX_IS_AVAILABLE())
scratch = NPCX_URBUF;
}
}
@@ -234,7 +282,11 @@ void uart_ec_interrupt(void)
uart_process_input();
uart_process_output();
}
+#ifdef NPCX_UART_FIFO_SUPPORT
+DECLARE_IRQ(NPCX_IRQ_UART, uart_ec_interrupt, 4);
+#else
DECLARE_IRQ(NPCX_IRQ_UART, uart_ec_interrupt, 1);
+#endif
#ifdef CONFIG_UART_PAD_SWITCH
/*
@@ -255,7 +307,12 @@ void uart_reset_default_pad_panic(void)
static void uart_set_pad(enum uart_pad newpad)
{
+#ifdef NPCX_UART_FIFO_SUPPORT
+ NPCX_UFTCTL &= ~0xE0;
+ NPCX_UFRCTL &= ~0xE0;
+#else
NPCX_UICTRL = 0x00;
+#endif
task_disable_irq(NPCX_IRQ_UART);
/* Flush the last byte */
@@ -277,7 +334,7 @@ static void uart_set_pad(enum uart_pad newpad)
npcx_gpio2uart();
/* Re-enable receive interrupt. */
- NPCX_UICTRL = 0x40;
+ NPCX_UART_RX_INT_EN();
/*
* If pad is switched while a byte is being received, the last byte may
@@ -374,6 +431,19 @@ out:
}
#endif
+#ifdef NPCX_UART_FIFO_SUPPORT
+static void uart_set_fifo_mode(void)
+{
+ /* Enable the UART FIFO mode */
+ SET_BIT(NPCX_UMDSL, NPCX_UMDSL_FIFO_MD);
+ /* Disable all Tx interrupts */
+ NPCX_UFTCTL &= ~((1 << NPCX_UFTCTL_TEMPTY_LVL_EN) |
+ (1 << NPCX_UFTCTL_TEMPTY_EN) |
+ (1 << NPCX_UFTCTL_NXIMPEN));
+}
+
+#endif
+
static void uart_config(void)
{
/* Configure pins from GPIOs to CR_UART */
@@ -410,7 +480,10 @@ static void uart_config(void)
* the divisor for the new divisor to take effect.
*/
NPCX_UFRS = 0x00;
- NPCX_UICTRL = 0x40; /* receive int enable only */
+#ifdef NPCX_UART_FIFO_SUPPORT
+ uart_set_fifo_mode();
+#endif
+ NPCX_UART_RX_INT_EN();
}
void uart_init(void)