Ravi kumar has uploaded this change for review.

View Change

sc7280: Add UART support

This implements the UART driver in SoC

Change-Id: Idc91f05c530ae41f212d6a4124dd5796aeaa8dfc
Signed-off-by: Roja Rani Yarubandi <rojay@codeaurora.org>
---
M src/soc/qualcomm/sc7280/Kconfig
M src/soc/qualcomm/sc7280/Makefile.inc
A src/soc/qualcomm/sc7280/qupv3_uart.c
3 files changed, 162 insertions(+), 3 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/47526/1
diff --git a/src/soc/qualcomm/sc7280/Kconfig b/src/soc/qualcomm/sc7280/Kconfig
index 2fef404..d6f56ba 100644
--- a/src/soc/qualcomm/sc7280/Kconfig
+++ b/src/soc/qualcomm/sc7280/Kconfig
@@ -36,4 +36,10 @@
int
default 16

+config UART_FOR_CONSOLE
+ int
+ default 5
+ help
+ Select the QUP instance to be used for UART console output.
+
endif
diff --git a/src/soc/qualcomm/sc7280/Makefile.inc b/src/soc/qualcomm/sc7280/Makefile.inc
index 876d7d9..acbb36d 100644
--- a/src/soc/qualcomm/sc7280/Makefile.inc
+++ b/src/soc/qualcomm/sc7280/Makefile.inc
@@ -19,7 +19,7 @@
verstage-$(CONFIG_SC7280_QSPI) += qspi.c
verstage-y += clock.c
verstage-y += gpio.c
-verstage-$(CONFIG_DRIVERS_UART) += uart_bitbang.c
+verstage-$(CONFIG_DRIVERS_UART) += qupv3_uart.c
verstage-y += qupv3_config.c
verstage-y += qcom_qup_se.c

@@ -34,7 +34,7 @@
romstage-$(CONFIG_SC7280_QSPI) += qspi.c
romstage-y += clock.c
romstage-y += gpio.c
-romstage-$(CONFIG_DRIVERS_UART) += uart_bitbang.c
+romstage-$(CONFIG_DRIVERS_UART) += qupv3_uart.c
romstage-y += qupv3_config.c
romstage-y += qcom_qup_se.c

@@ -46,7 +46,7 @@
ramstage-$(CONFIG_SC7280_QSPI) += qspi.c
ramstage-y += clock.c
ramstage-y += gpio.c
-ramstage-$(CONFIG_DRIVERS_UART) += uart_bitbang.c
+ramstage-$(CONFIG_DRIVERS_UART) += qupv3_uart.c
ramstage-y += qupv3_config.c
ramstage-y += qcom_qup_se.c

diff --git a/src/soc/qualcomm/sc7280/qupv3_uart.c b/src/soc/qualcomm/sc7280/qupv3_uart.c
new file mode 100644
index 0000000..5679a25
--- /dev/null
+++ b/src/soc/qualcomm/sc7280/qupv3_uart.c
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <assert.h>
+#include <boot/coreboot_tables.h>
+#include <console/uart.h>
+#include <soc/clock.h>
+#include <soc/qcom_qup_se.h>
+#include <soc/qupv3_config.h>
+#include <types.h>
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK 0x1
+#define GENI_STATUS_S_GENI_CMD_ACTIVE_MASK 0x1000
+
+#define UART_TX_WATERMARK_MARGIN 4 /* Represented in words */
+#define UART_RX_WATERMARK_MARGIN 8 /* Represented in words */
+#define UART_RX_RFR_WATERMARK_MARGIN 4 /* Represented in words */
+#define UART_TX_BITS_PER_WORD 8
+#define UART_RX_BITS_PER_WORD 8
+#define START_UART_TX 0x8000000
+#define START_UART_RX 0x8000000
+
+/* UART FIFO Packing Configuration. */
+/* Start_idx:0, direction:0, len:7, stop:0 */
+#define UART_TX_PACK_VECTOR0 0x0E
+/* Start_idx:8, direction:0, len:7, stop:0 */
+#define UART_TX_PACK_VECTOR1 0x10E
+/* Start_idx:16, direction:0, len:7, stop:0 */
+#define UART_TX_PACK_VECTOR2 0x20E
+/* Start_idx:24, direction:0, len:7, stop:1 */
+#define UART_TX_PACK_VECTOR3 0x30F
+/* Start_idx:0, direction:0, len:7, stop:1 */
+#define UART_RX_PACK_VECTOR0 0xF
+#define UART_RX_PACK_VECTOR2 0x00
+
+void uart_tx_flush(unsigned int idx)
+{
+ struct qup_regs *regs = qup[idx].regs;
+
+ while (read32(&regs->geni_status) &
+ GENI_STATUS_M_GENI_CMD_ACTIVE_MASK)
+ ;
+}
+
+void uart_init(unsigned int idx)
+{
+ struct qup_regs *regs = qup[idx].regs;
+ unsigned int reg_value;
+ unsigned int div, baud_rate, uart_freq;
+
+ /*
+ * If the RX (secondary) sequencer is already active, it means the core
+ * has been already initialized in the previous stage. Skip
+ * configuration
+ */
+ if (read32(&regs->geni_status) & GENI_STATUS_S_GENI_CMD_ACTIVE_MASK)
+ return;
+
+ qupv3_se_fw_load_and_init(idx, SE_PROTOCOL_UART, FIFO);
+ clock_enable_qup(idx);
+
+ reg_value = read32(&regs->geni_fw_revision_ro);
+ reg_value &= GENI_FW_REVISION_RO_PROTOCOL_MASK;
+ reg_value >>= GENI_FW_REVISION_RO_PROTOCOL_SHIFT;
+
+ assert(reg_value == SE_PROTOCOL_UART);
+
+ baud_rate = get_uart_baudrate();
+
+ /* sc7280 requires 16 clock pulses to sample 1 bit of data */
+ uart_freq = baud_rate * 16;
+
+ div = DIV_ROUND_CLOSEST(SRC_XO_HZ, uart_freq);
+ write32(&regs->geni_ser_m_clk_cfg, (div << 4) | 1);
+ write32(&regs->geni_ser_s_clk_cfg, (div << 4) | 1);
+
+ /* GPIO Configuration */
+ gpio_configure(qup[idx].pin[2], qup[idx].func[2], GPIO_PULL_UP,
+ GPIO_2MA, GPIO_OUTPUT);
+ gpio_configure(qup[idx].pin[3], qup[idx].func[3], GPIO_PULL_UP,
+ GPIO_2MA, GPIO_INPUT);
+
+ write32(&regs->geni_tx_watermark_reg, UART_TX_WATERMARK_MARGIN);
+ write32(&regs->geni_rx_watermark_reg, FIFO_DEPTH
+ - UART_RX_WATERMARK_MARGIN);
+ write32(&regs->geni_rx_rfr_watermark_reg,
+ FIFO_DEPTH - UART_RX_RFR_WATERMARK_MARGIN);
+
+ write32(&regs->uart_tx_word_len, UART_TX_BITS_PER_WORD);
+ write32(&regs->uart_rx_word_len, UART_RX_BITS_PER_WORD);
+
+ /* Disable TX parity calculation */
+ write32(&regs->uart_tx_parity_cfg, 0x0);
+ /* Ignore CTS line status for TX communication */
+ write32(&regs->uart_tx_trans_cfg_reg, 0x2);
+ /* Disable RX parity calculation */
+ write32(&regs->uart_rx_parity_cfg, 0x0);
+ /* Disable parity, framing and break check on received word */
+ write32(&regs->uart_rx_trans_cfg, 0x0);
+ /* Set UART TX stop bit len to one UART bit length */
+ write32(&regs->uart_tx_stop_bit_len, 0x0);
+ write32(&regs->uart_rx_stale_cnt, 0x16 * 10);
+
+ write32(&regs->geni_tx_packing_cfg0, UART_TX_PACK_VECTOR0 |
+ (UART_TX_PACK_VECTOR1 << 10));
+ write32(&regs->geni_tx_packing_cfg1, UART_TX_PACK_VECTOR2 |
+ (UART_TX_PACK_VECTOR3 << 10));
+ write32(&regs->geni_rx_packing_cfg0, UART_RX_PACK_VECTOR0);
+ write32(&regs->geni_rx_packing_cfg1, UART_RX_PACK_VECTOR2);
+
+ /* Start RX */
+ write32(&regs->geni_s_cmd0, START_UART_RX);
+}
+
+unsigned char uart_rx_byte(unsigned int idx)
+{
+ struct qup_regs *regs = qup[idx].regs;
+
+ if (read32(&regs->geni_rx_fifo_status) & RX_FIFO_WC_MSK)
+ return read32(&regs->geni_rx_fifon) & 0xFF;
+ return 0;
+}
+
+void uart_tx_byte(unsigned int idx, unsigned char data)
+{
+ struct qup_regs *regs = qup[idx].regs;
+
+ uart_tx_flush(idx);
+
+ write32(&regs->uart_tx_trans_len, 1);
+ /* Start TX */
+ write32(&regs->geni_m_cmd0, START_UART_TX);
+ write32(&regs->geni_tx_fifon, data);
+}
+
+uintptr_t uart_platform_base(unsigned int idx)
+{
+ return (uintptr_t)qup[idx].regs;
+}
+
+void uart_fill_lb(void *data)
+{
+ struct lb_serial serial = {0};
+
+ serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
+ serial.baseaddr = (uint32_t)uart_platform_base(CONFIG_UART_FOR_CONSOLE);
+ serial.baud = get_uart_baudrate();
+ serial.regwidth = 4;
+ serial.input_hertz = SRC_XO_HZ;
+
+ lb_add_serial(&serial, data);
+}

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

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Idc91f05c530ae41f212d6a4124dd5796aeaa8dfc
Gerrit-Change-Number: 47526
Gerrit-PatchSet: 1
Gerrit-Owner: Ravi kumar <rbokka@codeaurora.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange