mturney mturney has uploaded this change for review.

View Change

trogdor: libpayload uart/serial driver support

Change-Id: I5be3904298cd88c60dbc6d8d662beeede2abe442
Signed-off-by: T Michael Turney <mturney@codeaurora.org>
---
M payloads/libpayload/Kconfig
A payloads/libpayload/configs/config.trogdor
M payloads/libpayload/drivers/Makefile.inc
A payloads/libpayload/drivers/serial/sc7180.c
4 files changed, 292 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/60/35960/1
diff --git a/payloads/libpayload/Kconfig b/payloads/libpayload/Kconfig
index 97b970b..aa044bd 100644
--- a/payloads/libpayload/Kconfig
+++ b/payloads/libpayload/Kconfig
@@ -263,6 +263,16 @@
depends on SERIAL_CONSOLE
default n

+config SC7180_SERIAL_CONSOLE
+ bool "SC7180 SOC compatible serial port driver"
+ depends on SERIAL_CONSOLE
+ default n
+
+config CONSOLE_UART_ADDR
+ hex "Default I/O base for the serial port"
+ depends on SC7180_SERIAL_CONSOLE
+ default 0x00A88000
+
config PL011_SERIAL_CONSOLE
bool "PL011 compatible serial port driver"
depends on 8250_SERIAL_CONSOLE
diff --git a/payloads/libpayload/configs/config.trogdor b/payloads/libpayload/configs/config.trogdor
new file mode 100644
index 0000000..0625ff5
--- /dev/null
+++ b/payloads/libpayload/configs/config.trogdor
@@ -0,0 +1,5 @@
+CONFIG_LP_CHROMEOS=y
+CONFIG_LP_ARCH_ARM64=y
+CONFIG_LP_TIMER_ARM64_ARCH=y
+CONFIG_LP_SERIAL_CONSOLE=y
+CONFIG_LP_SC7180_SERIAL_CONSOLE=y
diff --git a/payloads/libpayload/drivers/Makefile.inc b/payloads/libpayload/drivers/Makefile.inc
index b4e7594..701434d 100644
--- a/payloads/libpayload/drivers/Makefile.inc
+++ b/payloads/libpayload/drivers/Makefile.inc
@@ -38,6 +38,7 @@
libc-$(CONFIG_LP_IPQ806X_SERIAL_CONSOLE) += serial/ipq806x.c serial/serial.c
libc-$(CONFIG_LP_IPQ40XX_SERIAL_CONSOLE) += serial/ipq40xx.c serial/serial.c
libc-$(CONFIG_LP_QCS405_SERIAL_CONSOLE) += serial/qcs405.c serial/serial.c
+libc-$(CONFIG_LP_SC7180_SERIAL_CONSOLE) += serial/sc7180.c serial/serial.c
libc-$(CONFIG_LP_PC_KEYBOARD) += i8042/keyboard.c
libc-$(CONFIG_LP_PC_MOUSE) += i8042/mouse.c
libc-$(CONFIG_LP_PC_I8042) += i8042/i8042.c
diff --git a/payloads/libpayload/drivers/serial/sc7180.c b/payloads/libpayload/drivers/serial/sc7180.c
new file mode 100644
index 0000000..d104cd6
--- /dev/null
+++ b/payloads/libpayload/drivers/serial/sc7180.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2010-2012, 2014, 2016, 2019, The Linux Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libpayload.h>
+
+/* For simplicity sake let's rely on coreboot initalizing the UART. */
+#include <sys/types.h>
+#include <config.h>
+
+#define true 1
+#define false 0
+typedef uint8_t bool;
+
+#define REG_IN(base, offset) (*(volatile unsigned int *)(base + offset))
+
+#define REG_OUT(base, offset, value) \
+ (*(volatile unsigned int *)(base + offset) = value)
+
+/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */
+
+#define GENI4_CFG 0x0
+#define GENI4_IMAGE_REGS 0x100
+#define GENI4_DATA 0x600
+#define QUPV3_SE_DMA 0xC00
+#define GENI4_IMAGE 0x1000
+#define QUPV3_SEC 0x2000
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+
+#define SE_HW_PARAM_0_REG (QUPV3_SE_DMA + 0x00000224)
+#define SE_HW_PARAM_0_TX_FIFO_DEPTH_MASK 0x3f0000
+#define SE_HW_PARAM_0_TX_FIFO_DEPTH_SHIFT 0x10
+
+#define SE_HW_PARAM_1_REG (QUPV3_SE_DMA + 0x00000228)
+#define SE_HW_PARAM_1_RX_FIFO_DEPTH_MASK 0x3f0000
+#define SE_HW_PARAM_1_RX_FIFO_DEPTH_SHIFT 0x10
+
+#define GENI_FW_REVISION_RO_REG (GENI4_CFG + 0x00000068)
+#define GENI_FW_REVISION_RO_PROTOCOL_MASK 0x0000FF00
+#define GENI_FW_REVISION_RO_PROTOCOL_SHIFT 0x00000008
+
+#define GENI_SER_M_CLK_CFG_REG (GENI4_CFG + 0x00000048)
+#define GENI_SER_S_CLK_CFG_REG (GENI4_CFG + 0x0000004c)
+
+#define GENI_STATUS_REG (GENI4_CFG + 0x00000040)
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK 0x1
+#define GENI_STATUS_S_GENI_CMD_ACTIVE_MASK 0x1000
+
+#define GENI_TX_WATERMARK_REG (GENI4_DATA + 0x0000020c)
+#define GENI_RX_WATERMARK_REG (GENI4_DATA + 0x00000210)
+#define GENI_RX_RFR_WATERMARK_REG (GENI4_DATA + 0x00000214)
+
+#define UART_TX_WORD_LEN_REG (GENI4_IMAGE_REGS + 0x00000168)
+#define UART_RX_WORD_LEN_REG (GENI4_IMAGE_REGS + 0x0000018c)
+
+#define UART_TX_PARITY_CFG_REG (GENI4_IMAGE_REGS + 0x000001a4)
+#define UART_TX_TRANS_CFG_REG (GENI4_IMAGE_REGS + 0x0000015c)
+#define UART_RX_PARITY_CFG_REG (GENI4_IMAGE_REGS + 0x000001a8)
+#define UART_RX_TRANS_CFG_REG (GENI4_IMAGE_REGS + 0x00000180)
+
+#define UART_TX_STOP_BIT_LEN_REG (GENI4_IMAGE_REGS + 0x0000016c)
+
+#define UART_RX_STALE_CNT_REG (GENI4_IMAGE_REGS + 0x00000194)
+
+#define GENI_TX_PACKING_CFG0_REG (GENI4_IMAGE_REGS + 0x00000160)
+#define GENI_TX_PACKING_CFG1_REG (GENI4_IMAGE_REGS + 0x00000164)
+#define GENI_RX_PACKING_CFG0_REG (GENI4_IMAGE_REGS + 0x00000184)
+#define GENI_RX_PACKING_CFG1_REG (GENI4_IMAGE_REGS + 0x00000188)
+
+#define UART_TX_TRANS_LEN_REG (GENI4_IMAGE_REGS + 0x00000170)
+
+/* FIFO, STATUS REGISTERS AND MASKS */
+
+#define GENI_TX_FIFOn_REG (GENI4_DATA + 0x00000100)
+#define GENI_RX_FIFOn_REG (GENI4_DATA + 0x00000180)
+
+#define GENI_TX_FIFO_STATUS_REG (GENI4_DATA + 0x00000200)
+#define GENI_TX_FIFO_STATUS_TX_FIFO_WC_MASK 0xfffffff
+
+#define GENI_RX_FIFO_STATUS_REG (GENI4_DATA + 0x00000204)
+#define GENI_RX_FIFO_STATUS_RX_LAST_VALID_BYTES_MASK 0x70000000
+#define GENI_RX_FIFO_STATUS_RX_LAST_VALID_BYTES_SHIFT 0x1c
+#define GENI_RX_FIFO_STATUS_RX_FIFO_WC_MASK 0x1ffffff
+#define GENI_RX_FIFO_STATUS_RX_FIFO_WC_SHIFT 0x0
+
+/* MASTER/TX ENGINE REGISTERS */
+
+#define GENI_M_CMD0_REG (GENI4_DATA + 0x00000000)
+
+/* SECONDARY/RX ENGINE REGISTERS */
+
+#define GENI_S_CMD0_REG (GENI4_DATA + 0x00000030)
+
+#define TX_WATERMARK_MARGIN 4 /* Represented in words */
+#define RX_WATERMARK_MARGIN 8 /* Represented in words */
+#define RX_RFR_WATERMARK_MARGIN 4 /* Represented in words */
+
+#define PROTOCOL_UART 0x2
+
+static struct console_input_driver consin = {
+ .next = 0,
+ .input_type = 0,
+};
+
+static struct console_output_driver consout = {
+ .next = 0,
+};
+
+static bool uart_initialized = false;
+
+static bool uart_qupv3_init(void);
+static unsigned char uart_qupv3_rx_byte(void);
+static void uart_qupv3_tx_byte(unsigned char data);
+
+uintptr_t uart_platform_base(int idx);
+
+static bool uart_qupv3_init(void)
+{
+ uintptr_t base = uart_platform_base(0);
+ unsigned int reg_value;
+
+ reg_value = REG_IN(base, GENI_FW_REVISION_RO_REG);
+ reg_value &= GENI_FW_REVISION_RO_PROTOCOL_MASK;
+ reg_value >>= GENI_FW_REVISION_RO_PROTOCOL_SHIFT;
+
+ if (reg_value != PROTOCOL_UART)
+ return false;
+
+ /*
+ * If the RX (secondary) sequencer is already active, it means the core
+ * has been already initialized in the previous stage. Skip
+ * configuration
+ */
+ if (REG_IN(base, GENI_STATUS_REG) &
+ GENI_STATUS_S_GENI_CMD_ACTIVE_MASK) {
+ uart_initialized = true;
+ return true;
+ }
+
+ REG_OUT(base, GENI_TX_WATERMARK_REG, TX_WATERMARK_MARGIN);
+
+ /* To get RX FIFO size */
+ reg_value = REG_IN(base, SE_HW_PARAM_1_REG);
+ reg_value &= SE_HW_PARAM_1_RX_FIFO_DEPTH_MASK;
+ reg_value >>= SE_HW_PARAM_1_RX_FIFO_DEPTH_SHIFT;
+
+ REG_OUT(base, GENI_RX_WATERMARK_REG, reg_value - RX_WATERMARK_MARGIN);
+
+ REG_OUT(base, GENI_RX_RFR_WATERMARK_REG,
+ reg_value - RX_RFR_WATERMARK_MARGIN);
+
+ REG_OUT(base, UART_TX_WORD_LEN_REG, 0x8);
+ REG_OUT(base, UART_RX_WORD_LEN_REG, 0x8);
+
+ REG_OUT(base, UART_TX_PARITY_CFG_REG, 0x0);
+ REG_OUT(base, UART_TX_TRANS_CFG_REG, 0x2);
+ REG_OUT(base, UART_RX_PARITY_CFG_REG, 0x0);
+ REG_OUT(base, UART_RX_TRANS_CFG_REG, 0x0);
+
+ REG_OUT(base, UART_TX_STOP_BIT_LEN_REG, 0x0);
+
+ REG_OUT(base, UART_RX_STALE_CNT_REG, 0x16 * 10);
+
+ REG_OUT(base, GENI_TX_PACKING_CFG0_REG, 0x4380E);
+ REG_OUT(base, GENI_TX_PACKING_CFG1_REG, 0xC3E0E);
+ REG_OUT(base, GENI_RX_PACKING_CFG0_REG, 0xF);
+ REG_OUT(base, GENI_RX_PACKING_CFG1_REG, 0x0);
+
+ REG_OUT(base, GENI_S_CMD0_REG, 0x8000000);
+
+ uart_initialized = true;
+ return true;
+}
+
+unsigned char uart_qupv3_rx_byte(void)
+{
+ uintptr_t base = uart_platform_base(0);
+ unsigned char data;
+
+ if (uart_initialized) {
+ if (REG_IN(base, GENI_RX_FIFO_STATUS_REG) &
+ GENI_RX_FIFO_STATUS_RX_FIFO_WC_MASK) {
+ data = (unsigned char)REG_IN(base, GENI_RX_FIFOn_REG) &
+ 0xFF;
+ return data;
+ }
+ }
+ return 0x0;
+}
+
+void uart_qupv3_tx_byte(unsigned char data)
+{
+ uintptr_t base = uart_platform_base(0);
+
+ if (uart_initialized == false) {
+ if (!uart_qupv3_init())
+ return;
+ }
+
+ while (REG_IN(base, GENI_STATUS_REG) &
+ GENI_STATUS_M_GENI_CMD_ACTIVE_MASK)
+ ;
+
+ REG_OUT(base, UART_TX_TRANS_LEN_REG, 1);
+ REG_OUT(base, GENI_M_CMD0_REG, 0x08000000);
+ REG_OUT(base, GENI_TX_FIFOn_REG, (unsigned int)data);
+}
+
+uintptr_t uart_platform_base(int idx)
+{
+ return CONFIG_LP_CONSOLE_UART_ADDR;
+}
+
+void serial_putchar(unsigned int data)
+{
+ if (data == 0xa)
+ uart_qupv3_tx_byte(0xd);
+ uart_qupv3_tx_byte(data);
+}
+
+int serial_havechar(void)
+{
+ uintptr_t base = uart_platform_base(0);
+
+ if (uart_initialized) {
+ if (REG_IN(base, GENI_RX_FIFO_STATUS_REG) &
+ GENI_RX_FIFO_STATUS_RX_FIFO_WC_MASK) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int serial_getchar(void)
+{
+ return uart_qupv3_rx_byte();
+}
+
+void serial_console_init(void)
+{
+ uart_qupv3_init();
+
+ consout.putchar = &serial_putchar;
+ console_add_output_driver(&consout);
+
+ consin.havekey = &serial_havechar;
+ consin.getchar = &serial_getchar;
+ console_add_input_driver(&consin);
+}

To view, visit change 35960. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I5be3904298cd88c60dbc6d8d662beeede2abe442
Gerrit-Change-Number: 35960
Gerrit-PatchSet: 1
Gerrit-Owner: mturney mturney <mturney@codeaurora.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: mturney mturney <mturney@codeaurora.org>
Gerrit-MessageType: newchange