diff options
author | Tzung-Bi Shih <tzungbi@chromium.org> | 2020-05-13 17:08:49 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-06-04 10:27:53 +0000 |
commit | cb2a4b7a3b8ccb123ffb270057228d8635d357a8 (patch) | |
tree | 91b383a7f8554fbd64c51095ba8f79875a14ac59 /chip | |
parent | 45f96454b8663375bbf45df9bd321615976d830e (diff) | |
download | chrome-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.c | 8 | ||||
-rw-r--r-- | chip/mt8192_scp/registers.h | 71 | ||||
-rw-r--r-- | chip/mt8192_scp/uart.c | 114 | ||||
-rw-r--r-- | chip/mt8192_scp/uart_regs.h | 77 |
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 */ |