summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@chromium.org>2020-05-13 17:08:49 +0800
committerCommit Bot <commit-bot@chromium.org>2020-06-04 10:27:53 +0000
commitcb2a4b7a3b8ccb123ffb270057228d8635d357a8 (patch)
tree91b383a7f8554fbd64c51095ba8f79875a14ac59 /chip
parent45f96454b8663375bbf45df9bd321615976d830e (diff)
downloadchrome-ec-cb2a4b7a3b8ccb123ffb270057228d8635d357a8.tar.gz
chip/mt8192_scp: support UART
BRANCH=none BUG=b:146213943 BUG=b:156221696 TEST=make BOARD=asurada_scp Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> Change-Id: I95a547b9d1763dc7faa6d7a1c18cf9ae675bae39 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2198821 Reviewed-by: Eric Yilun Lin <yllin@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/mt8192_scp/intc.c8
-rw-r--r--chip/mt8192_scp/registers.h71
-rw-r--r--chip/mt8192_scp/uart.c114
-rw-r--r--chip/mt8192_scp/uart_regs.h77
4 files changed, 262 insertions, 8 deletions
diff --git a/chip/mt8192_scp/intc.c b/chip/mt8192_scp/intc.c
index d7c4d475ef..c8f68fd40e 100644
--- a/chip/mt8192_scp/intc.c
+++ b/chip/mt8192_scp/intc.c
@@ -46,8 +46,8 @@ static struct {
[SCP_IRQ_EINT] = { INTC_GRP_0 },
[SCP_IRQ_PMIC] = { INTC_GRP_0 },
/* 8 */
- [SCP_IRQ_UART0_TX] = { INTC_GRP_0 },
- [SCP_IRQ_UART1_TX] = { INTC_GRP_0 },
+ [SCP_IRQ_UART0_TX] = { INTC_GRP_12 },
+ [SCP_IRQ_UART1_TX] = { INTC_GRP_12 },
[SCP_IRQ_I2C0] = { INTC_GRP_0 },
[SCP_IRQ_I2C1_0] = { INTC_GRP_0 },
/* 12 */
@@ -63,8 +63,8 @@ static struct {
/* 20 */
[SCP_IRQ_TIMER5] = { INTC_GRP_0 },
[SCP_IRQ_OS_TIMER] = { INTC_GRP_0 },
- [SCP_IRQ_UART0_RX] = { INTC_GRP_0 },
- [SCP_IRQ_UART1_RX] = { INTC_GRP_0 },
+ [SCP_IRQ_UART0_RX] = { INTC_GRP_12 },
+ [SCP_IRQ_UART1_RX] = { INTC_GRP_12 },
/* 24 */
[SCP_IRQ_GDMA] = { INTC_GRP_0 },
[SCP_IRQ_AUDIO] = { INTC_GRP_0 },
diff --git a/chip/mt8192_scp/registers.h b/chip/mt8192_scp/registers.h
index 08609ab962..1cfc7a6bcc 100644
--- a/chip/mt8192_scp/registers.h
+++ b/chip/mt8192_scp/registers.h
@@ -15,6 +15,64 @@
#define SCP_REG_BASE 0x70000000
+/* clock control */
+#define SCP_CLK_CTRL_BASE (SCP_REG_BASE + 0x21000)
+/* clock gate */
+#define SCP_SET_CLK_CG REG32(SCP_CLK_CTRL_BASE + 0x0030)
+#define CG_TIMER_MCLK BIT(0)
+#define CG_TIMER_BCLK BIT(1)
+#define CG_MAD_MCLK BIT(2)
+#define CG_I2C_MCLK BIT(3)
+#define CG_I2C_BCLK BIT(4)
+#define CG_GPIO_MCLK BIT(5)
+#define CG_AP2P_MCLK BIT(6)
+#define CG_UART0_MCLK BIT(7)
+#define CG_UART0_BCLK BIT(8)
+#define CG_UART0_RST BIT(9)
+#define CG_UART1_MCLK BIT(10)
+#define CG_UART1_BCLK BIT(11)
+#define CG_UART1_RST BIT(12)
+#define CG_SPI0 BIT(13)
+#define CG_SPI1 BIT(14)
+#define CG_SPI2 BIT(15)
+#define CG_DMA_CH0 BIT(16)
+#define CG_DMA_CH1 BIT(17)
+#define CG_DMA_CH2 BIT(18)
+#define CG_DMA_CH3 BIT(19)
+#define CG_I3C0 BIT(21)
+#define CG_I3C1 BIT(22)
+#define CG_DMA2_CH0 BIT(23)
+#define CG_DMA2_CH1 BIT(24)
+#define CG_DMA2_CH2 BIT(25)
+#define CG_DMA2_CH3 BIT(26)
+/* UART clock select */
+#define SCP_UART_CK_SEL REG32(SCP_CLK_CTRL_BASE + 0x0044)
+#define UART0_CK_SEL_SHIFT 0
+#define UART0_CK_SEL_MASK (0x3 << UART0_CK_SEL_SHIFT)
+#define UART0_CK_SEL_VAL(v) ((v) & UART0_CK_SEL_MASK)
+#define UART0_CK_SW_STATUS_MASK (0xf << 8)
+#define UART0_CK_SW_STATUS_VAL(v) ((v) & UART0_CK_SW_STATUS_MASK)
+#define UART1_CK_SEL_SHIFT 16
+#define UART1_CK_SEL_MASK (0x3 << UART1_CK_SEL_SHIFT)
+#define UART1_CK_SEL_VAL(v) ((v) & UART1_CK_SEL_MASK)
+#define UART1_CK_SW_STATUS_MASK (0xf << 24)
+#define UART1_CK_SW_STATUS_VAL(v) ((v) & UART1_CK_SW_STATUS_MASK)
+#define UART_CK_SEL_26M 0
+#define UART_CK_SEL_32K 1
+#define UART_CK_SEL_ULPOSC 2
+#define UART_CK_SW_STATUS_26M BIT(0)
+#define UART_CK_SW_STATUS_32K BIT(1)
+#define UART_CK_SW_STATUS_ULPOS BIT(2)
+
+/* UART */
+#define SCP_UART_COUNT 2
+#define UART_TX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _TX)
+#define UART_RX_IRQ(n) CONCAT3(SCP_IRQ_UART, n, _RX)
+#define SCP_UART0_BASE (SCP_REG_BASE + 0x26000)
+#define SCP_UART1_BASE (SCP_REG_BASE + 0x27000)
+#define SCP_UART_BASE(n) CONCAT3(SCP_UART, n, _BASE)
+#define UART_REG(n, offset) REG32_ADDR(SCP_UART_BASE(n))[offset]
+
/* INTC */
#define SCP_INTC_IRQ_POL0 0xef001f20
#define SCP_INTC_IRQ_POL1 0x0800001d
@@ -41,6 +99,10 @@
#define SCP_CORE0_INTC_SLP_WAKE_EN(w) \
REG32_ADDR(SCP_CORE0_INTC_IRQ_BASE + 0x0240)[(w)]
#define SCP_CORE0_INTC_IRQ_OUT REG32(SCP_CORE0_INTC_IRQ_BASE + 0x0250)
+/* UART */
+#define SCP_CORE0_INTC_UART0_RX_IRQ REG32(SCP_CORE0_INTC_IRQ_BASE + 0x0258)
+#define SCP_CORE0_INTC_UART1_RX_IRQ REG32(SCP_CORE0_INTC_IRQ_BASE + 0x025C)
+#define SCP_CORE0_INTC_UART_RX_IRQ(n) CONCAT3(SCP_CORE0_INTC_UART, n, _RX_IRQ)
/* memory remap */
#define SCP_R_REMAP_0X0123 REG32(SCP_REG_BASE + 0xA5060)
@@ -48,6 +110,15 @@
#define SCP_R_REMAP_0X89AB REG32(SCP_REG_BASE + 0xA5068)
#define SCP_R_REMAP_0XCDEF REG32(SCP_REG_BASE + 0xA506C)
+/* external address: AP */
+#define AP_REG_BASE 0x60000000 /* 0x10000000 remap to 0x6 */
+/* AP GPIO */
+#define AP_GPIO_BASE (AP_REG_BASE + 0x5000)
+#define AP_GPIO_MODE11_SET REG32(AP_GPIO_BASE + 0x03B4)
+#define AP_GPIO_MODE11_CLR REG32(AP_GPIO_BASE + 0x03B8)
+#define AP_GPIO_MODE20_SET REG32(AP_GPIO_BASE + 0x0444)
+#define AP_GPIO_MODE20_CLR REG32(AP_GPIO_BASE + 0x0448)
+
/* IRQ numbers */
#define SCP_IRQ_GIPC_IN0 0
#define SCP_IRQ_GIPC_IN1 1
diff --git a/chip/mt8192_scp/uart.c b/chip/mt8192_scp/uart.c
index 960e42944d..b4f8300d24 100644
--- a/chip/mt8192_scp/uart.c
+++ b/chip/mt8192_scp/uart.c
@@ -5,48 +5,154 @@
/* SCP UART module */
+#include "system.h"
#include "uart.h"
+#include "uart_regs.h"
+#include "util.h"
+
+/*
+ * UARTN == 0, SCP UART0
+ * UARTN == 1, SCP UART1
+ * UARTN == 2, AP UART1
+ */
+#define UARTN CONFIG_UART_CONSOLE
+#define UART_IDLE_WAIT_US 500
+
+static uint8_t init_done, tx_started;
void uart_init(void)
{
+ const uint32_t baud_rate = CONFIG_UART_BAUD_RATE;
+ /* TODO: use ULPOSC1 for S3 */
+ const uint32_t uart_clock = 26000000;
+ const uint32_t div = DIV_ROUND_NEAREST(uart_clock, baud_rate * 16);
+
+#if UARTN == 0
+ SCP_UART_CK_SEL |= UART0_CK_SEL_VAL(UART_CK_SEL_26M);
+ SCP_SET_CLK_CG |= CG_UART0_MCLK | CG_UART0_BCLK | CG_UART0_RST;
+
+ /* set AP GPIO164 and GPIO165 to alt func 3 */
+ AP_GPIO_MODE20_CLR = 0x00770000;
+ AP_GPIO_MODE20_SET = 0x00330000;
+#elif UARTN == 1
+ SCP_UART_CK_SEL |= UART1_CK_SEL_VAL(UART_CK_SEL_26M);
+ SCP_SET_CLK_CG |= CG_UART1_MCLK | CG_UART1_BCLK | CG_UART1_RST;
+#endif
+
+ /* Clear FIFO */
+ UART_FCR(UARTN) = UART_FCR_ENABLE_FIFO
+ | UART_FCR_CLEAR_RCVR
+ | UART_FCR_CLEAR_XMIT;
+ /* Line control: parity none, 8 bit, 1 stop bit */
+ UART_LCR(UARTN) = UART_LCR_WLEN8;
+ /* For baud rate <= 115200 */
+ UART_HIGHSPEED(UARTN) = 0;
+
+ /* DLAB start */
+ UART_LCR(UARTN) |= UART_LCR_DLAB;
+ UART_DLL(UARTN) = div & 0xff;
+ UART_DLH(UARTN) = (div >> 8) & 0xff;
+ UART_LCR(UARTN) &= ~UART_LCR_DLAB;
+ /* DLAB end */
+
+ /* Enable received data interrupt */
+ UART_IER(UARTN) |= UART_IER_RDI;
+
+#if (UARTN < SCP_UART_COUNT)
+ task_enable_irq(UART_TX_IRQ(UARTN));
+ task_enable_irq(UART_RX_IRQ(UARTN));
+#endif
+
+ init_done = 1;
}
int uart_init_done(void)
{
- return 0;
+ return init_done;
}
void uart_tx_flush(void)
{
+ while (!(UART_LSR(UARTN) & UART_LSR_TEMT))
+ ;
}
int uart_tx_ready(void)
{
- return 0;
+ return UART_LSR(UARTN) & UART_LSR_THRE;
}
int uart_rx_available(void)
{
- return 0;
+ return UART_LSR(UARTN) & UART_LSR_DR;
}
void uart_write_char(char c)
{
+ while (!uart_tx_ready())
+ ;
+
+ UART_THR(UARTN) = c;
}
int uart_read_char(void)
{
- return 0;
+ return UART_RBR(UARTN);
}
void uart_tx_start(void)
{
+ tx_started = 1;
+ if (UART_IER(UARTN) & UART_IER_THRI)
+ return;
+ disable_sleep(SLEEP_MASK_UART);
+ UART_IER(UARTN) |= UART_IER_THRI;
}
void uart_tx_stop(void)
{
+ tx_started = 0;
+ UART_IER(UARTN) &= ~UART_IER_THRI;
+ enable_sleep(SLEEP_MASK_UART);
}
void uart_process(void)
{
+ uart_process_input();
+ uart_process_output();
+}
+
+#if (UARTN < SCP_UART_COUNT)
+void irq_group12_handler(void)
+{
+ extern volatile int ec_int;
+
+ switch (ec_int) {
+ case UART_TX_IRQ(UARTN):
+ uart_process();
+ task_clear_pending_irq(ec_int);
+ break;
+ case UART_RX_IRQ(UARTN):
+ uart_process();
+ SCP_CORE0_INTC_UART_RX_IRQ(UARTN) = BIT(0);
+ task_clear_pending_irq(ec_int);
+ break;
+ }
+}
+DECLARE_IRQ(12, irq_group12_handler, 2);
+#else
+
+#ifndef HAS_TASK_APUART
+#error "APUART task hasn't defined in ec.tasklist."
+#endif
+
+void uart_task(void)
+{
+ while (1) {
+ if (uart_rx_available() || tx_started)
+ uart_process();
+ else
+ task_wait_event(UART_IDLE_WAIT_US);
+ }
}
+#endif
diff --git a/chip/mt8192_scp/uart_regs.h b/chip/mt8192_scp/uart_regs.h
new file mode 100644
index 0000000000..1a421a413b
--- /dev/null
+++ b/chip/mt8192_scp/uart_regs.h
@@ -0,0 +1,77 @@
+/* Copyright 2020 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.
+ */
+
+/* SCP UART module registers */
+
+#ifndef __CROS_EC_UART_REGS_H
+#define __CROS_EC_UART_REGS_H
+
+#include "registers.h"
+
+/* DLAB (Divisor Latch Access Bit) == 0 */
+
+/* (Read) receiver buffer register */
+#define UART_RBR(n) UART_REG(n, 0)
+/* (Write) transmitter holding register */
+#define UART_THR(n) UART_REG(n, 0)
+/* (Write) interrupt enable register */
+#define UART_IER(n) UART_REG(n, 1)
+#define UART_IER_RDI BIT(0) /* received data */
+#define UART_IER_THRI BIT(1) /* THR empty */
+#define UART_IER_RLSI BIT(2) /* receiver LSR change */
+#define UART_IER_MSI BIT(3) /* MSR change */
+/* (Read) interrupt identification register */
+#define UART_IIR(n) UART_REG(n, 2)
+#define UART_IIR_ID_MASK 0x0e
+#define UART_IIR_MSI 0x00 /* modem status change */
+#define UART_IIR_NO_INT 0x01 /* no int pending */
+#define UART_IIR_THRI 0x02 /* THR empty */
+#define UART_IIR_RDI 0x04 /* received data available */
+#define UART_IIR_RLSI 0x06 /* line status change */
+/* (Write) FIFO control register */
+#define UART_FCR(n) UART_REG(n, 2)
+#define UART_FCR_ENABLE_FIFO BIT(0) /* enable FIFO */
+#define UART_FCR_CLEAR_RCVR BIT(1) /* clear receive FIFO */
+#define UART_FCR_CLEAR_XMIT BIT(2) /* clear transmit FIFO */
+#define UART_FCR_DMA_SELECT BIT(3) /* select DMA mode */
+/* (Write) line control register */
+#define UART_LCR(n) UART_REG(n, 3)
+#define UART_LCR_WLEN5 0 /* word length 5 bits */
+#define UART_LCR_WLEN6 1
+#define UART_LCR_WLEN7 2
+#define UART_LCR_WLEN8 3
+#define UART_LCR_STOP BIT(2) /* stop bits: 1bit, 2bits */
+#define UART_LCR_PARITY BIT(3) /* parity enable */
+#define UART_LCR_EPAR BIT(4) /* even parity */
+#define UART_LCR_SPAR BIT(5) /* stick parity */
+#define UART_LCR_SBC BIT(6) /* set break control */
+#define UART_LCR_DLAB BIT(7) /* divisor latch access */
+/* (Write) modem control register */
+#define UART_MCR(n) UART_REG(n, 4)
+/* (Read) line status register */
+#define UART_LSR(n) UART_REG(n, 5)
+#define UART_LSR_DR BIT(0) /* data ready */
+#define UART_LSR_OE BIT(1) /* overrun error */
+#define UART_LSR_PE BIT(2) /* parity error */
+#define UART_LSR_FE BIT(3) /* frame error */
+#define UART_LSR_BI BIT(4) /* break interrupt */
+#define UART_LSR_THRE BIT(5) /* THR empty */
+#define UART_LSR_TEMT BIT(6) /* THR empty, line idle */
+#define UART_LSR_FIFOE BIT(7) /* FIFO error */
+/* (Read) modem status register */
+#define UART_MSR(n) UART_REG(n, 6)
+/* (Read/Write) scratch register */
+#define UART_SCR(n) UART_REG(n, 7)
+
+/* DLAB == 1 */
+
+/* (Write) divisor latch */
+#define UART_DLL(n) UART_REG(n, 0)
+#define UART_DLH(n) UART_REG(n, 1)
+
+/* MTK extension */
+#define UART_HIGHSPEED(n) UART_REG(n, 9)
+
+#endif /* __CROS_EC_UART_REGS_H */