summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/npcx7_evb/board.h9
-rw-r--r--board/npcx7_evb/gpio.inc8
-rw-r--r--chip/npcx/build.mk2
-rw-r--r--chip/npcx/clock.c6
-rw-r--r--chip/npcx/config_chip-npcx5.h4
-rw-r--r--chip/npcx/config_chip-npcx7.h5
-rw-r--r--chip/npcx/config_chip.h2
-rw-r--r--chip/npcx/gpio.c34
-rw-r--r--chip/npcx/gpio_chip-npcx7.h22
-rw-r--r--chip/npcx/gpio_chip.h6
-rw-r--r--chip/npcx/registers.h71
-rw-r--r--chip/npcx/uart.c218
-rw-r--r--chip/npcx/uartn.c261
-rw-r--r--chip/npcx/uartn.h63
14 files changed, 484 insertions, 227 deletions
diff --git a/board/npcx7_evb/board.h b/board/npcx7_evb/board.h
index bcc9437270..9080615006 100644
--- a/board/npcx7_evb/board.h
+++ b/board/npcx7_evb/board.h
@@ -74,6 +74,15 @@
#endif
/* Optional feature to configure npcx7 chip */
+
+/* Select which UART Controller is the Console UART */
+#undef CONFIG_CONSOLE_UART
+#define CONFIG_CONSOLE_UART 0 /* 0:UART1 1:UART2 */
+/*
+ * This definition below actually doesn't define which UART controller to be
+ * used. Instead, it defines which pinouts (GPIO10/11 or GPIO64/65) are
+ * connected to "UART1" controller.
+ */
#if (BOARD_VERSION == 2)
#define NPCX_UART_MODULE2 1 /* 1:GPIO64/65 as UART1 */
#else
diff --git a/board/npcx7_evb/gpio.inc b/board/npcx7_evb/gpio.inc
index 2acec02f09..e0bb9c1df8 100644
--- a/board/npcx7_evb/gpio.inc
+++ b/board/npcx7_evb/gpio.inc
@@ -52,12 +52,18 @@ GPIO(BOARD_VERSION2, PIN(6, 5), GPIO_INPUT)
GPIO(BOARD_VERSION3, PIN(6, 6), GPIO_INPUT)
/*********************** Alternate pins for npcx7 series **********************/
-/* UART Tx/Rx */
+#if (CONFIG_CONSOLE_UART == 0)
+/* UART1 Tx/Rx */
#if NPCX_UART_MODULE2
ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO64/65 */
#else
ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */
#endif
+#else
+/* UART2 Tx/Rx */
+ALTERNATE(PIN_MASK(7, 0x20), 1, MODULE_UART, 0) /* CR_SIN2 GPIO75 */
+ALTERNATE(PIN_MASK(8, 0x40), 1, MODULE_UART, 0) /* CR_SOUT2 GPIO86 */
+#endif
/* ADC */
ALTERNATE(PIN_MASK(4, 0x3E), 1, MODULE_ADC, 0) /* ADC0/1/2/3/4 GPIO45/44/43/42/41 */
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk
index e4783439a3..166519db62 100644
--- a/chip/npcx/build.mk
+++ b/chip/npcx/build.mk
@@ -17,7 +17,7 @@ CHIP_FAMILY:=npcx5
endif
# Required chip modules
-chip-y=header.o clock.o gpio.o hwtimer.o system.o uart.o
+chip-y=header.o clock.o gpio.o hwtimer.o system.o uart.o uartn.o
chip-y+=system-$(CHIP_FAMILY).o
# Optional chip modules
diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c
index 9411959515..ca3ebf88d8 100644
--- a/chip/npcx/clock.c
+++ b/chip/npcx/clock.c
@@ -20,6 +20,7 @@
#include "task.h"
#include "timer.h"
#include "uart.h"
+#include "uartn.h"
#include "util.h"
#include "watchdog.h"
@@ -324,10 +325,7 @@ void __idle(void)
/* UART-rx(console) become to GPIO (NONE INT mode) */
clock_uart2gpio();
#elif defined(CHIP_FAMILY_NPCX7)
- /* Clear pending bit before enable uart wake-up */
- SET_BIT(NPCX_WKPCL(MIWU_TABLE_1, MIWU_GROUP_8), 7);
- /* Enable UART wake-up and interrupt request */
- SET_BIT(NPCX_WKEN(MIWU_TABLE_1, MIWU_GROUP_8), 7);
+ uartn_wui_en(CONFIG_CONSOLE_UART);
#endif
/*
diff --git a/chip/npcx/config_chip-npcx5.h b/chip/npcx/config_chip-npcx5.h
index 9abe21d1c9..e1ad4923b8 100644
--- a/chip/npcx/config_chip-npcx5.h
+++ b/chip/npcx/config_chip-npcx5.h
@@ -15,6 +15,10 @@
/*****************************************************************************/
/* Hardware features */
+
+/* Number of UART modules. */
+#define UART_MODULE_COUNT 1
+
/*
* Number of I2C controllers. Controller 0 has 2 ports, so the chip has one
* additional port.
diff --git a/chip/npcx/config_chip-npcx7.h b/chip/npcx/config_chip-npcx7.h
index 93525fadc7..65668b7b38 100644
--- a/chip/npcx/config_chip-npcx7.h
+++ b/chip/npcx/config_chip-npcx7.h
@@ -28,6 +28,11 @@
#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M7WB)
#define NPCX_UART_FIFO_SUPPORT
+/* Number of UART modules. */
+#define NPCX_SECOND_UART
+#define UART_MODULE_COUNT 2
+#else
+#define UART_MODULE_COUNT 1
#endif
#ifdef CHIP_VARIANT_NPCX7M7WB
diff --git a/chip/npcx/config_chip.h b/chip/npcx/config_chip.h
index 9dac257850..e956e4cf6a 100644
--- a/chip/npcx/config_chip.h
+++ b/chip/npcx/config_chip.h
@@ -69,6 +69,8 @@
/* Chip needs to do custom pre-init */
#define CONFIG_CHIP_PRE_INIT
+/* Default use UART1 as console */
+#define CONFIG_CONSOLE_UART 0
#define GPIO_PIN(port, index) GPIO_##port, (1 << index)
#define GPIO_PIN_MASK(p, m) .port = GPIO_##p, .mask = (m)
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
index 01a0a6897f..cabda69b15 100644
--- a/chip/npcx/gpio.c
+++ b/chip/npcx/gpio.c
@@ -31,12 +31,6 @@
#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
#endif
-struct npcx_wui {
- uint8_t table : 2;
- uint8_t group : 3;
- uint8_t bit : 3;
-};
-
/* Constants for GPIO interrupt mapping */
#define GPIO_INT(name, pin, flags, signal) NPCX_WUI_GPIO_##pin,
#ifdef CONFIG_LOW_POWER_IDLE
@@ -605,17 +599,35 @@ void __gpio_rtc_interrupt(void)
/* Clear pending bit for WUI */
SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_4), 7);
host_set_single_event(EC_HOST_EVENT_RTC);
- } else
+ return;
+ }
#endif
- {
- gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_1));
- gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_4));
+#if defined(CHIP_FAMILY_NPCX7) && defined(CONFIG_LOW_POWER_IDLE) && \
+ (CONFIG_CONSOLE_UART == 1)
+ /* Handle the interrupt from UART wakeup event */
+ if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_1), 6) &&
+ IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_1), 6)) {
+ /*
+ * Disable WKEN bit to avoid the other unnecessary interrupts
+ * from the coming data bits after the start bit. (Pending bit
+ * of CR_SIN is set when a high-to-low transaction occurs.)
+ */
+ CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_1), 6);
+ /* Clear pending bit for WUI */
+ SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_1), 6);
+ /* Notify the clock module that the console is in use. */
+ clock_refresh_console_in_use();
+ return;
}
+#endif
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_1));
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_4));
}
void __gpio_wk1h_interrupt(void)
{
-#if defined(CHIP_FAMILY_NPCX7) && defined(CONFIG_LOW_POWER_IDLE)
+#if defined(CHIP_FAMILY_NPCX7) && defined(CONFIG_LOW_POWER_IDLE) && \
+ (CONFIG_CONSOLE_UART == 0)
/* Handle the interrupt from UART wakeup event */
if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_1, MIWU_GROUP_8), 7) &&
IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_1, MIWU_GROUP_8), 7)) {
diff --git a/chip/npcx/gpio_chip-npcx7.h b/chip/npcx/gpio_chip-npcx7.h
index e0081b761a..3511ad8ac2 100644
--- a/chip/npcx/gpio_chip-npcx7.h
+++ b/chip/npcx/gpio_chip-npcx7.h
@@ -229,11 +229,23 @@
/* UART Module 1/2 */
#if NPCX_UART_MODULE2
-#define NPCX_ALT_CR_SIN ALT(6, 4, NPCX_ALT(C, UART_SL2)) /* CR_SIN2 */
-#define NPCX_ALT_CR_SOUT ALT(6, 5, NPCX_ALT(C, UART_SL2)) /* CR_SOUT2 */
+/* CR_SIN Select 2 */
+#define NPCX_ALT_CR_SIN ALT(6, 4, NPCX_ALT(C, UART_SL2))
+/* CR_SOUT Select 2 */
+#define NPCX_ALT_CR_SOUT ALT(6, 5, NPCX_ALT(C, UART_SL2))
#else
-#define NPCX_ALT_CR_SIN ALT(1, 0, NPCX_ALT_INV(9, NO_KSO08_SL)) /* CR_SIN */
-#define NPCX_ALT_CR_SOUT ALT(1, 1, NPCX_ALT_INV(9, NO_KSO09_SL)) /* CR_SOUT */
+/* CR_SIN Select 1 */
+#define NPCX_ALT_CR_SIN ALT(1, 0, NPCX_ALT_INV(9, NO_KSO08_SL))
+/* CR_SOUT Select 1 */
+#define NPCX_ALT_CR_SOUT ALT(1, 1, NPCX_ALT_INV(9, NO_KSO09_SL))
+#endif
+
+#ifdef NPCX_SECOND_UART
+#define NPCX_ALT_CR_SIN2 ALT(7, 5, NPCX_ALT(A, UART2_SL)) /* CR_SIN2 */
+#define NPCX_ALT_CR_SOUT2 ALT(8, 6, NPCX_ALT(A, UART2_SL)) /* CR_SOUT2 */
+#else
+#define NPCX_ALT_CR_SIN2
+#define NPCX_ALT_CR_SOUT2
#endif
/* SPI Module */
@@ -370,6 +382,8 @@
NPCX_ALT_ADC9 \
NPCX_ALT_CR_SIN \
NPCX_ALT_CR_SOUT \
+ NPCX_ALT_CR_SIN2 \
+ NPCX_ALT_CR_SOUT2 \
NPCX_ALT_SPIP_MISO \
NPCX_ALT_SPIP_CS1 \
NPCX_ALT_SPIP_MOSI \
diff --git a/chip/npcx/gpio_chip.h b/chip/npcx/gpio_chip.h
index 6d704a5e6a..6282794e44 100644
--- a/chip/npcx/gpio_chip.h
+++ b/chip/npcx/gpio_chip.h
@@ -6,6 +6,12 @@
#ifndef __CROS_EC_GPIO_CHIP_H
#define __CROS_EC_GPIO_CHIP_H
+struct npcx_wui {
+ uint8_t table : 2;
+ uint8_t group : 3;
+ uint8_t bit : 3;
+};
+
/* Macros to initialize the MIWU mapping table. */
#define NPCX_WUI_GPIO_PIN(port, index) NPCX_WUI_GPIO_##port##_##index
#define WUI(tbl, grp, idx) ((struct npcx_wui) { .table = tbl, .group = grp, \
diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h
index 9e3ee1938d..94c34f34f6 100644
--- a/chip/npcx/registers.h
+++ b/chip/npcx/registers.h
@@ -87,7 +87,6 @@
#define NPCX_MTC_BASE_ADDR 0x400B7000
#define NPCX_MSWC_BASE_ADDR 0x400C1000
#define NPCX_SCFG_BASE_ADDR 0x400C3000
-#define NPCX_CR_UART_BASE_ADDR 0x400C4000
#define NPCX_KBC_BASE_ADDR 0x400C7000
#define NPCX_ADC_BASE_ADDR 0x400D1000
#define NPCX_SPI_BASE_ADDR 0x400D2000
@@ -101,6 +100,7 @@
#define NPCX_ITIM32_BASE_ADDR 0x400BC000
#define NPCX_MIWU_BASE_ADDR(mdl) (0x400BB000 + ((mdl) * 0x2000L))
#define NPCX_MFT_BASE_ADDR(mdl) (0x400E1000 + ((mdl) * 0x2000L))
+#define NPCX_CR_UART_BASE_ADDR(mdl) (0x400C4000 + ((mdl) * 0x2000L))
#define NPCX_PM_CH_BASE_ADDR(mdl) (0x400C9000 + ((mdl) * 0x2000L))
#if defined(CHIP_FAMILY_NPCX7)
#define NPCX_SMB_BASE_ADDR(mdl) (((mdl) < 2) ? \
@@ -217,7 +217,7 @@
#define NPCX_IRQ29_NOUSED NPCX_IRQ_29
#define NPCX_IRQ30_NOUSED NPCX_IRQ_30
#define NPCX_IRQ_TWD_WKINTB_0 NPCX_IRQ_31
-#define NPCX_IRQ32_NOUSED NPCX_IRQ_32
+#define NPCX_IRQ_UART2 NPCX_IRQ_32
#define NPCX_IRQ_UART NPCX_IRQ_33
#define NPCX_IRQ34_NOUSED NPCX_IRQ_34
#define NPCX_IRQ35_NOUSED NPCX_IRQ_35
@@ -294,20 +294,20 @@
/******************************************************************************/
/* 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)
-#define NPCX_USTAT REG8(NPCX_CR_UART_BASE_ADDR + 0x006)
-#define NPCX_UFRS REG8(NPCX_CR_UART_BASE_ADDR + 0x008)
-#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)
+#define NPCX_UTBUF(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x000)
+#define NPCX_URBUF(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x002)
+#define NPCX_UICTRL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x004)
+#define NPCX_USTAT(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x006)
+#define NPCX_UFRS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x008)
+#define NPCX_UMDSL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00A)
+#define NPCX_UBAUD(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x00C)
+#define NPCX_UPSR(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 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)
+#define NPCX_UFTSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x020)
+#define NPCX_UFRSTS(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x022)
+#define NPCX_UFTCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x024)
+#define NPCX_UFRCTL(n) REG8(NPCX_CR_UART_BASE_ADDR(n) + 0x026)
/* UART FIFO register fields */
#define NPCX_UMDSL_FIFO_MD 0
@@ -333,6 +333,23 @@
#endif
+#if defined(CHIP_FAMILY_NPCX5)
+enum {
+ NPCX_UART_PORT0 = 0, /* UART port 0 */
+ NPCX_UART_COUNT
+};
+#elif defined(CHIP_FAMILY_NPCX7)
+enum {
+ NPCX_UART_PORT0 = 0, /* UART port 0 */
+#ifdef NPCX_SECOND_UART
+ NPCX_UART_PORT1 = 1, /* UART port 1 */
+#endif
+ NPCX_UART_COUNT
+};
+#else
+#error "Unsupported chip family for uart ports."
+#endif
+
/******************************************************************************/
/* KBSCAN registers */
#define NPCX_KBSIN REG8(NPCX_KBSCAN_REGS_BASE + 0x04)
@@ -713,6 +730,9 @@ enum {
#define NPCX_DEVALTA_32KCLKIN_SL 3
#endif
#define NPCX_DEVALTA_NO_VCC1_RST 4
+#ifdef NPCX_SECOND_UART
+#define NPCX_DEVALTA_UART2_SL 5
+#endif
#define NPCX_DEVALTA_NO_PECI_EN 6
#define NPCX_DEVALTA_UART_SL1 7
#define NPCX_DEVALTC_UART_SL2 0
@@ -930,8 +950,12 @@ enum {
#define NPCX_PWDWN_CTL7_SMB5_PD 0
#define NPCX_PWDWN_CTL7_SMB6_PD 1
#define NPCX_PWDWN_CTL7_SMB7_PD 2
+#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M7WB)
+#define NPCX_PWDWN_CTL7_ITIM64_PD 5
+#define NPCX_PWDWN_CTL7_UART2_PD 6
#define NPCX_PWDWN_CTL7_WOV_PD 7
#endif
+#endif
/*
* PMC enumeration
@@ -952,9 +976,12 @@ enum {
CGC_OFFSET_ESPI = 5,
#if defined(CHIP_FAMILY_NPCX7)
CGC_OFFSET_I2C2 = 6,
+#ifdef NPCX_SECOND_UART
+ CGC_OFFSET_UART2 = 6,
#endif
#ifdef NPCX_WOV_SUPPORT
- CGC_OFFSET_WOV = 6,
+ CGC_OFFSET_WOV = 6,
+#endif
#endif
};
@@ -991,10 +1018,13 @@ enum NPCX_PMC_PWDWN_CTL_T {
#define CGC_I2C_MASK2 ((1 << NPCX_PWDWN_CTL7_SMB5_PD) | \
(1 << NPCX_PWDWN_CTL7_SMB6_PD) | \
(1 << NPCX_PWDWN_CTL7_SMB7_PD))
+#ifdef NPCX_SECOND_UART
+#define CGC_UART2_MASK (1 << NPCX_PWDWN_CTL7_UART2_PD)
#endif
#ifdef NPCX_WOV_SUPPORT
#define CGC_WOV_MASK (1 << NPCX_PWDWN_CTL7_WOV_PD)
#endif
+#endif
#define CGC_ADC_MASK (1 << NPCX_PWDWN_CTL4_ADC_PD)
#define CGC_PECI_MASK (1 << NPCX_PWDWN_CTL4_PECI_PD)
#define CGC_SPI_MASK (1 << NPCX_PWDWN_CTL4_SPIP_PD)
@@ -2061,7 +2091,6 @@ enum {
#define NPCX_UART_DEVALT_SL NPCX_DEVALTC_UART_SL2
#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0A)
#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTA_UART_SL1
-
#else /* !NPCX_UART_MODULE2 */
#ifdef CHIP_FAMILY_NPCX5
@@ -2073,12 +2102,16 @@ enum {
#define NPCX_UART_DEVALT_SL NPCX_DEVALTA_UART_SL1
#define NPCX_UART_ALT_DEVALT NPCX_DEVALT(0x0C)
#define NPCX_UART_ALT_DEVALT_SL NPCX_DEVALTC_UART_SL2
-
#endif /* NPCX_UART_MODULE2 */
#ifdef CHIP_FAMILY_NPCX7
-#define NPCX_UART_WK_GROUP MIWU_GROUP_8
-#define NPCX_UART_WK_BIT 7
+#define NPCX_UART_WK_GROUP MIWU_GROUP_8
+#define NPCX_UART_WK_BIT 7
+#ifdef NPCX_SECOND_UART
+#define NPCX_UART2_WK_GROUP MIWU_GROUP_1
+#define NPCX_UART2_WK_BIT 6
+#endif
+
#endif
/* This routine checks pending bit of GPIO wake-up functionality */
diff --git a/chip/npcx/uart.c b/chip/npcx/uart.c
index 384f71d8be..40d3ee391f 100644
--- a/chip/npcx/uart.c
+++ b/chip/npcx/uart.c
@@ -18,57 +18,15 @@
#include "task.h"
#include "timer.h"
#include "uart.h"
+#include "uartn.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))
+#define CONSOLE_UART CONFIG_CONSOLE_UART
-/*
- * 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))
+#if CONSOLE_UART
+#define CONSOLE_UART_IRQ NPCX_IRQ_UART2
#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)
+#define CONSOLE_UART_IRQ NPCX_IRQ_UART
#endif
static int init_done;
@@ -149,7 +107,6 @@ int uart_init_done(void)
void uart_tx_start(void)
{
- /* We needn't to switch uart from gpio again in npcx7. */
#if defined(CHIP_FAMILY_NPCX5)
if (uart_is_enable_wakeup() && pad == UART_DEFAULT_PAD) {
/* disable MIWU */
@@ -161,57 +118,35 @@ void uart_tx_start(void)
}
#endif
- /* If interrupt is already enabled, nothing to do */
- if (NPCX_UART_TX_EMPTY_INT_IS_EN())
- return;
-
- /* Do not allow deep sleep while transmit in progress */
- disable_sleep(SLEEP_MASK_UART);
-
- /*
- * Re-enable the transmit interrupt, then forcibly trigger the
- * interrupt. This works around a hardware problem with the
- * UART where the FIFO only triggers the interrupt when its
- * threshold is _crossed_, not just met.
- */
- NPCX_UART_TX_EMPTY_INT_EN();
-
- task_trigger_irq(NPCX_IRQ_UART);
+ uartn_tx_start(CONSOLE_UART);
}
void uart_tx_stop(void)
{
- /* Disable TX interrupt */
- NPCX_UART_TX_EMPTY_INT_DIS();
+ uint8_t sleep_ena;
- /*
- * Re-allow deep sleep when transmiting on the default pad (deep sleep
- * is always disabled when alternate pad is selected).
- */
- if (pad == UART_DEFAULT_PAD)
- enable_sleep(SLEEP_MASK_UART);
+ sleep_ena = (pad == UART_DEFAULT_PAD) ? 1 : 0;
+ uartn_tx_stop(CONSOLE_UART, sleep_ena);
}
void uart_tx_flush(void)
{
- /* Wait for transmit FIFO empty and last byte is sent */
- while (NPCX_UART_TX_IN_XMIT())
- ;
+ uartn_tx_flush(CONSOLE_UART);
}
int uart_tx_ready(void)
{
- return NPCX_UART_TX_IS_READY();
+ return uartn_tx_ready(CONSOLE_UART);
}
int uart_tx_in_progress(void)
{
- return NPCX_UART_TX_IN_XMIT();
+ return uartn_tx_in_progress(CONSOLE_UART);
}
int uart_rx_available(void)
{
- int rx_available = NPCX_UART_RX_IS_AVAILABLE();
+ int rx_available = uartn_rx_available(CONSOLE_UART);
if (rx_available && pad == UART_DEFAULT_PAD) {
#ifdef CONFIG_LOW_POWER_IDLE
@@ -232,44 +167,29 @@ int uart_rx_available(void)
void uart_write_char(char c)
{
- /* Wait for space in transmit FIFO. */
- while (!uart_tx_ready())
- ;
-
- NPCX_UTBUF = c;
+ uartn_write_char(CONSOLE_UART, c);
}
int uart_read_char(void)
{
- return NPCX_URBUF;
-}
-
-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_UART_RX_IS_AVAILABLE())
- scratch = NPCX_URBUF;
- }
+ return uartn_read_char(CONSOLE_UART);
}
-/**
- * Interrupt handler for UART0
- */
+/* Interrupt handler for Console UART */
void uart_ec_interrupt(void)
{
#ifdef CONFIG_UART_PAD_SWITCH
if (pad == UART_ALTERNATE_PAD) {
- if (uart_rx_available()) {
- uint8_t c = uart_read_char();
+ if (uartn_rx_available(NPCX_UART_PORT0)) {
+ uint8_t c = uartn_read_char(NPCX_UART_PORT0);
if (altpad_rx_pos < altpad_rx_len)
altpad_rx_buf[altpad_rx_pos++] = c;
}
- if (uart_tx_ready()) {
+ if (uartn_tx_ready(NPCX_UART_PORT0)) {
if (altpad_tx_pos < altpad_tx_len)
- uart_write_char(altpad_tx_buf[altpad_tx_pos++]);
+ uartn_write_char(NPCX_UART_PORT0,
+ altpad_tx_buf[altpad_tx_pos++]);
else
uart_tx_stop();
}
@@ -283,9 +203,9 @@ void uart_ec_interrupt(void)
uart_process_output();
}
#ifdef NPCX_UART_FIFO_SUPPORT
-DECLARE_IRQ(NPCX_IRQ_UART, uart_ec_interrupt, 4);
+DECLARE_IRQ(CONSOLE_UART_IRQ, uart_ec_interrupt, 4);
#else
-DECLARE_IRQ(NPCX_IRQ_UART, uart_ec_interrupt, 1);
+DECLARE_IRQ(CONSOLE_UART_IRQ, uart_ec_interrupt, 1);
#endif
#ifdef CONFIG_UART_PAD_SWITCH
@@ -308,15 +228,15 @@ 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;
+ NPCX_UFTCTL(NPCX_UART_PORT0) &= ~0xE0;
+ NPCX_UFRCTL(NPCX_UART_PORT0) &= ~0xE0;
#else
- NPCX_UICTRL = 0x00;
+ NPCX_UICTRL(NPCX_UART_PORT0) = 0x00;
#endif
task_disable_irq(NPCX_IRQ_UART);
/* Flush the last byte */
- uart_tx_flush();
+ uartn_tx_flush(NPCX_UART_PORT0);
uart_tx_stop();
/*
@@ -334,7 +254,7 @@ static void uart_set_pad(enum uart_pad newpad)
npcx_gpio2uart();
/* Re-enable receive interrupt. */
- NPCX_UART_RX_INT_EN();
+ uartn_rx_int_en(NPCX_UART_PORT0);
/*
* If pad is switched while a byte is being received, the last byte may
@@ -342,7 +262,7 @@ static void uart_set_pad(enum uart_pad newpad)
* then flush the FIFO. See b/65526215.
*/
udelay(100);
- uart_clear_rx_fifo(0);
+ uartn_clear_rx_fifo(NPCX_UART_PORT0);
task_enable_irq(NPCX_IRQ_UART);
}
@@ -393,7 +313,7 @@ int uart_alt_pad_write_read(uint8_t *tx, int tx_len, uint8_t *rx, int rx_len,
uart_set_pad(UART_ALTERNATE_PAD);
gpio_clear_pending_interrupt(GPIO_UART_MAIN_RX);
gpio_enable_interrupt(GPIO_UART_MAIN_RX);
- uart_tx_start();
+ uartn_tx_start(NPCX_UART_PORT0);
do {
usleep(100);
@@ -430,85 +350,9 @@ out:
return ret;
}
#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 */
- gpio_config_module(MODULE_UART, 1);
-
- /* Enable MIWU IRQ of UART */
- task_enable_irq(NPCX_UART_MIWU_IRQ);
-
-#ifdef CONFIG_LOW_POWER_IDLE
- /*
- * Configure the UART wake-up event triggered from a falling edge
- * on CR_SIN pin.
- */
- SET_BIT(NPCX_WKEDG(1, NPCX_UART_WK_GROUP), NPCX_UART_WK_BIT);
-#endif
-
- /*
- * If apb2's clock is not 15MHz, we need to find the other optimized
- * values of UPSR and UBAUD for baud rate 115200.
- */
-#if (NPCX_APB_CLOCK(2) != 15000000)
-#error "Unsupported apb2 clock for UART!"
-#endif
-
- /*
- * Fix baud rate to 115200. If this value is modified, please also
- * modify the delay in uart_set_pad and uart_reset_default_pad_panic.
- */
- NPCX_UPSR = 0x38;
- NPCX_UBAUD = 0x01;
-
- /*
- * 8-N-1, FIFO enabled. Must be done after setting
- * the divisor for the new divisor to take effect.
- */
- NPCX_UFRS = 0x00;
-#ifdef NPCX_UART_FIFO_SUPPORT
- uart_set_fifo_mode();
-#endif
- NPCX_UART_RX_INT_EN();
-}
-
void uart_init(void)
{
- uint32_t mask = 0;
-
- /*
- * Enable UART0 in run, sleep, and deep sleep modes. Enable the Host
- * UART in run and sleep modes.
- */
- mask = 0x10; /* bit 4 */
- clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL);
-
- /* Set pin-mask for UART */
- npcx_gpio2uart();
-
- /* Configure UARTs (identically) */
- uart_config();
-
- /*
- * Enable interrupts for UART0 only. Host UART will have to wait
- * until the LPC bus is initialized.
- */
- uart_clear_rx_fifo(0);
- task_enable_irq(NPCX_IRQ_UART);
+ uartn_init(CONSOLE_UART);
init_done = 1;
}
diff --git a/chip/npcx/uartn.c b/chip/npcx/uartn.c
new file mode 100644
index 0000000000..d7d46e849f
--- /dev/null
+++ b/chip/npcx/uartn.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* UART module for Chrome EC */
+
+#include <clock.h>
+#include "common.h"
+#include <gpio.h>
+#include <gpio_chip.h>
+#include "registers.h"
+#include "system.h"
+#include "task.h"
+#include "util.h"
+
+#ifdef NPCX_UART_FIFO_SUPPORT
+/* Enable UART Tx FIFO empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_EN(n) \
+ (SET_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN))
+/* True if UART Tx FIFO empty interrupt is enabled */
+#define NPCX_UART_TX_EMPTY_INT_IS_EN(n) \
+ (IS_BIT_SET(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN))
+/* Disable UART Tx FIFO empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_DIS(n) \
+ (CLEAR_BIT(NPCX_UFTCTL(n), NPCX_UFTCTL_TEMPTY_EN))
+/* True if the Tx FIFO is not completely full */
+#define NPCX_UART_TX_IS_READY(n) \
+ (!(GET_FIELD(NPCX_UFTSTS(n), 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(n) \
+ (!IS_BIT_SET(NPCX_UFTSTS(n), NPCX_UFTSTS_NXMIP))
+
+/*
+ * Enable to generate interrupt when there is at least one byte
+ * in the receive FIFO
+ */
+#define NPCX_UART_RX_INT_EN(n) \
+ (SET_BIT(NPCX_UFRCTL(n), NPCX_UFRCTL_RNEMPTY_EN))
+/* True if at least one byte is in the receive FIFO */
+#define NPCX_UART_RX_IS_AVAILABLE(n) \
+ (IS_BIT_SET(NPCX_UFRSTS(n), NPCX_UFRSTS_RFIFO_NEMPTY_STS))
+#else
+/* Enable UART Tx buffer empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_EN(n) (NPCX_UICTRL(n) |= 0x20)
+/* True if UART Tx buffer empty interrupt is enabled */
+#define NPCX_UART_TX_EMPTY_INT_IS_EN(n) (NPCX_UICTRL(n) & 0x20)
+/* Disable UART Tx buffer empty interrupt */
+#define NPCX_UART_TX_EMPTY_INT_DIS(n) (NPCX_UICTRL(n) &= ~0x20)
+/* True if 1-byte Tx buffer is empty */
+#define NPCX_UART_TX_IS_READY(n) (NPCX_UICTRL(n) & 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(n) (NPCX_USTAT(n) & 0x40)
+ /* Enable to generate interrupt when there is data in the receive buffer */
+#define NPCX_UART_RX_INT_EN(n) (NPCX_UICTRL(n) = 0x40)
+/* True if there is data in the 1-byte Receive buffer */
+#define NPCX_UART_RX_IS_AVAILABLE(n) (NPCX_UICTRL(n) & 0x02)
+#endif
+
+struct uart_configs {
+ uint32_t irq;
+ uint32_t clk_en_offset;
+ uint32_t clk_en_msk;
+};
+static const struct uart_configs uart_cfg[] = {
+ {NPCX_IRQ_UART, CGC_OFFSET_UART, CGC_UART_MASK},
+#ifdef NPCX_SECOND_UART
+ {NPCX_IRQ_UART2, CGC_OFFSET_UART2, CGC_UART2_MASK},
+#endif
+};
+BUILD_ASSERT(ARRAY_SIZE(uart_cfg) == UART_MODULE_COUNT);
+
+#ifdef CONFIG_LOW_POWER_IDLE
+static const struct npcx_wui uart_wui[] = {
+ WUI(1, NPCX_UART_WK_GROUP, NPCX_UART_WK_BIT),
+#ifdef NPCX_SECOND_UART
+ WUI(0, NPCX_UART2_WK_GROUP, NPCX_UART2_WK_BIT),
+#endif
+};
+BUILD_ASSERT(ARRAY_SIZE(uart_wui) == UART_MODULE_COUNT);
+
+void uartn_wui_en(uint8_t uart_num)
+{
+ struct npcx_wui wui;
+
+ wui = uart_wui[uart_num];
+ /* Clear pending bit before enable uart wake-up */
+ SET_BIT(NPCX_WKPCL(wui.table, wui.group), wui.bit);
+ /* Enable UART1 wake-up and interrupt request */
+ SET_BIT(NPCX_WKEN(wui.table, wui.group), wui.bit);
+}
+#endif
+
+void uartn_rx_int_en(uint8_t uart_num)
+{
+ NPCX_UART_RX_INT_EN(uart_num);
+}
+
+void uartn_tx_start(uint8_t uart_num)
+{
+ /* If interrupt is already enabled, nothing to do */
+ if (NPCX_UART_TX_EMPTY_INT_IS_EN(uart_num))
+ return;
+
+ /* Do not allow deep sleep while transmit in progress */
+ disable_sleep(SLEEP_MASK_UART);
+
+ /*
+ * Re-enable the transmit interrupt, then forcibly trigger the
+ * interrupt. This works around a hardware problem with the
+ * UART where the FIFO only triggers the interrupt when its
+ * threshold is _crossed_, not just met.
+ */
+ NPCX_UART_TX_EMPTY_INT_EN(uart_num);
+
+ task_trigger_irq(uart_cfg[uart_num].irq);
+}
+
+void uartn_tx_stop(uint8_t uart_num, uint8_t sleep_ena)
+{
+ /* Disable TX interrupt */
+ NPCX_UART_TX_EMPTY_INT_DIS(uart_num);
+ /*
+ * Re-allow deep sleep when transmiting on the default pad (deep sleep
+ * is always disabled when alternate pad is selected).
+ */
+ if (sleep_ena == 1)
+ enable_sleep(SLEEP_MASK_UART);
+}
+
+void uartn_tx_flush(uint8_t uart_num)
+{
+ /* Wait for transmit FIFO empty and last byte is sent */
+ while (NPCX_UART_TX_IN_XMIT(uart_num))
+ ;
+}
+
+int uartn_tx_ready(uint8_t uart_num)
+{
+ return NPCX_UART_TX_IS_READY(uart_num);
+}
+
+int uartn_tx_in_progress(uint8_t uart_num)
+{
+ return NPCX_UART_TX_IN_XMIT(uart_num);
+}
+
+int uartn_rx_available(uint8_t uart_num)
+{
+ return NPCX_UART_RX_IS_AVAILABLE(uart_num);
+}
+
+void uartn_write_char(uint8_t uart_num, char c)
+{
+ /* Wait for space in transmit FIFO. */
+ while (!uartn_tx_ready(uart_num))
+ ;
+
+ NPCX_UTBUF(uart_num) = c;
+}
+
+int uartn_read_char(uint8_t uart_num)
+{
+ return NPCX_URBUF(uart_num);
+}
+
+void uartn_clear_rx_fifo(int channel)
+{
+ int scratch __attribute__ ((unused));
+
+ /* If '1', that means there is RX data on the FIFO register */
+ while (NPCX_UART_RX_IS_AVAILABLE(channel))
+ scratch = NPCX_URBUF(channel);
+}
+
+#ifdef NPCX_UART_FIFO_SUPPORT
+static void uartn_set_fifo_mode(uint8_t uart_num)
+{
+ /* Enable the UART FIFO mode */
+ SET_BIT(NPCX_UMDSL(uart_num), NPCX_UMDSL_FIFO_MD);
+ /* Disable all Tx interrupts */
+ NPCX_UFTCTL(uart_num) &= ~((1 << NPCX_UFTCTL_TEMPTY_LVL_EN) |
+ (1 << NPCX_UFTCTL_TEMPTY_EN) |
+ (1 << NPCX_UFTCTL_NXIMPEN));
+}
+
+#endif
+
+static void uartn_config(uint8_t uart_num)
+{
+#ifdef CONFIG_LOW_POWER_IDLE
+ struct npcx_wui wui;
+#endif
+
+ /* Configure pins from GPIOs to CR_UART */
+ gpio_config_module(MODULE_UART, 1);
+
+#ifdef CONFIG_LOW_POWER_IDLE
+ /*
+ * Configure the UART wake-up event triggered from a falling edge
+ * on CR_SIN pin.
+ */
+ wui = uart_wui[uart_num];
+ SET_BIT(NPCX_WKEDG(wui.table, wui.group), wui.bit);
+#endif
+ /*
+ * If apb2's clock is not 15MHz, we need to find the other optimized
+ * values of UPSR and UBAUD for baud rate 115200.
+ */
+#if (NPCX_APB_CLOCK(2) != 15000000)
+#error "Unsupported apb2 clock for UART!"
+#endif
+
+ /*
+ * Fix baud rate to 115200. If this value is modified, please also
+ * modify the delay in uart_set_pad and uart_reset_default_pad_panic.
+ */
+ NPCX_UPSR(uart_num) = 0x38;
+ NPCX_UBAUD(uart_num) = 0x01;
+
+ /*
+ * 8-N-1, FIFO enabled. Must be done after setting
+ * the divisor for the new divisor to take effect.
+ */
+ NPCX_UFRS(uart_num) = 0x00;
+#ifdef NPCX_UART_FIFO_SUPPORT
+ uartn_set_fifo_mode(uart_num);
+#endif
+ NPCX_UART_RX_INT_EN(uart_num);
+}
+
+void uartn_init(uint8_t uart_num)
+{
+ uint32_t offset, mask;
+
+ offset = uart_cfg[uart_num].clk_en_offset;
+ mask = uart_cfg[uart_num].clk_en_msk;
+ clock_enable_peripheral(offset, mask, CGC_MODE_ALL);
+
+ if (uart_num == NPCX_UART_PORT0)
+ npcx_gpio2uart();
+
+ /* Configure UARTs (identically) */
+ uartn_config(uart_num);
+
+ /*
+ * Enable interrupts for UART0 only. Host UART will have to wait
+ * until the LPC bus is initialized.
+ */
+ uartn_clear_rx_fifo(uart_num);
+ task_enable_irq(uart_cfg[uart_num].irq);
+}
diff --git a/chip/npcx/uartn.h b/chip/npcx/uartn.h
new file mode 100644
index 0000000000..fc5c2599d0
--- /dev/null
+++ b/chip/npcx/uartn.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_UARTN_H
+#define __CROS_EC_UARTN_H
+
+#include "common.h"
+
+/*
+ * Initialize the UART module.
+ */
+void uartn_init(uint8_t uart_num);
+
+/*
+ * Re-enable the UART transmit interrupt.
+ *
+ * This also forces triggering a UART interrupt, if the transmit interrupt was
+ * disabled.
+ */
+void uartn_tx_start(uint8_t uart_num);
+
+ /* Disable the UART transmit interrupt. */
+void uartn_tx_stop(uint8_t uart_num, uint8_t sleep_ena);
+
+/* Flush the transmit FIFO. */
+void uartn_tx_flush(uint8_t uart_num);
+
+/* Return non-zero if there is room to transmit a character immediately. */
+int uartn_tx_ready(uint8_t uart_num);
+
+/* Return non-zero if a transmit is in progress. */
+int uartn_tx_in_progress(uint8_t uart_num);
+
+/* Return non-zero if the UART has a character available to read. */
+int uartn_rx_available(uint8_t uart_num);
+
+/*
+ * Send a character to the UART data register.
+ *
+ * If the transmit FIFO is full, blocks until there is space.
+ *
+ * @param c Character to send.
+ */
+void uartn_write_char(uint8_t uart_num, char c);
+
+/*
+ * Read one char from the UART data register.
+ *
+ * @return The character read.
+ */
+int uartn_read_char(uint8_t uart_num);
+
+/* Clear all data in the UART Rx FIFO */
+void uartn_clear_rx_fifo(int channel);
+
+/* Enable the UART Rx interrupt */
+void uartn_rx_int_en(uint8_t uart_num);
+/* Enable the UART Wake-up */
+void uartn_wui_en(uint8_t uart_num);
+#endif /* __CROS_EC_UARTN_H */