treewide: replace GPLv2 long form headers with SPDX header
[coreboot.git] / src / soc / qualcomm / sc7180 / qupv3_uart.c
blob88e7f13f95faf561f3051ccd08096cb1f725e0d0
1 /* This file is part of the coreboot project. */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <assert.h>
5 #include <boot/coreboot_tables.h>
6 #include <console/uart.h>
7 #include <soc/clock.h>
8 #include <soc/qcom_qup_se.h>
9 #include <soc/qupv3_config.h>
10 #include <types.h>
12 /* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
14 #define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK 0x1
15 #define GENI_STATUS_S_GENI_CMD_ACTIVE_MASK 0x1000
17 #define UART_TX_WATERMARK_MARGIN 4 /* Represented in words */
18 #define UART_RX_WATERMARK_MARGIN 8 /* Represented in words */
19 #define UART_RX_RFR_WATERMARK_MARGIN 4 /* Represented in words */
20 #define UART_TX_BITS_PER_WORD 8
21 #define UART_RX_BITS_PER_WORD 8
22 #define START_UART_TX 0x8000000
23 #define START_UART_RX 0x8000000
25 /* UART FIFO Packing Configuration. */
26 /* Start_idx:0, direction:0, len:7, stop:0 */
27 #define UART_TX_PACK_VECTOR0 0x0E
28 /* Start_idx:8, direction:0, len:7, stop:0 */
29 #define UART_TX_PACK_VECTOR1 0x10E
30 /* Start_idx:16, direction:0, len:7, stop:0 */
31 #define UART_TX_PACK_VECTOR2 0x20E
32 /* Start_idx:24, direction:0, len:7, stop:1 */
33 #define UART_TX_PACK_VECTOR3 0x30F
34 /* Start_idx:0, direction:0, len:7, stop:1 */
35 #define UART_RX_PACK_VECTOR0 0xF
36 #define UART_RX_PACK_VECTOR2 0x00
38 void uart_tx_flush(int idx)
40 struct qup_regs *regs = qup[idx].regs;
42 while (read32(&regs->geni_status) &
43 GENI_STATUS_M_GENI_CMD_ACTIVE_MASK)
47 void uart_init(int idx)
49 struct qup_regs *regs = qup[idx].regs;
50 unsigned int reg_value;
51 unsigned int div, baud_rate, uart_freq;
54 * If the RX (secondary) sequencer is already active, it means the core
55 * has been already initialized in the previous stage. Skip
56 * configuration
58 if (read32(&regs->geni_status) & GENI_STATUS_S_GENI_CMD_ACTIVE_MASK)
59 return;
61 qupv3_se_fw_load_and_init(idx, SE_PROTOCOL_UART, FIFO);
62 clock_enable_qup(idx);
64 reg_value = read32(&regs->geni_fw_revision_ro);
65 reg_value &= GENI_FW_REVISION_RO_PROTOCOL_MASK;
66 reg_value >>= GENI_FW_REVISION_RO_PROTOCOL_SHIFT;
68 assert(reg_value == SE_PROTOCOL_UART);
70 baud_rate = get_uart_baudrate();
72 /* sc7180 requires 16 clock pulses to sample 1 bit of data */
73 uart_freq = baud_rate * 16;
75 div = DIV_ROUND_CLOSEST(QUPV3_UART_SRC_HZ, uart_freq);
76 write32(&regs->geni_ser_m_clk_cfg, (div << 4) | 1);
77 write32(&regs->geni_ser_s_clk_cfg, (div << 4) | 1);
79 /* GPIO Configuration */
80 gpio_configure(qup[idx].pin[2], qup[idx].func[2], GPIO_PULL_UP,
81 GPIO_2MA, GPIO_OUTPUT);
82 gpio_configure(qup[idx].pin[3], qup[idx].func[3], GPIO_PULL_UP,
83 GPIO_2MA, GPIO_INPUT);
85 write32(&regs->geni_tx_watermark_reg, UART_TX_WATERMARK_MARGIN);
86 write32(&regs->geni_rx_watermark_reg, FIFO_DEPTH
87 - UART_RX_WATERMARK_MARGIN);
88 write32(&regs->geni_rx_rfr_watermark_reg,
89 FIFO_DEPTH - UART_RX_RFR_WATERMARK_MARGIN);
91 write32(&regs->uart_tx_word_len, UART_TX_BITS_PER_WORD);
92 write32(&regs->uart_rx_word_len, UART_RX_BITS_PER_WORD);
94 /* Disable TX parity calculation */
95 write32(&regs->uart_tx_parity_cfg, 0x0);
96 /* Ignore CTS line status for TX communication */
97 write32(&regs->uart_tx_trans_cfg_reg, 0x2);
98 /* Disable RX parity calculation */
99 write32(&regs->uart_rx_parity_cfg, 0x0);
100 /* Disable parity, framing and break check on received word */
101 write32(&regs->uart_rx_trans_cfg, 0x0);
102 /* Set UART TX stop bit len to one UART bit length */
103 write32(&regs->uart_tx_stop_bit_len, 0x0);
104 write32(&regs->uart_rx_stale_cnt, 0x16 * 10);
106 write32(&regs->geni_tx_packing_cfg0, UART_TX_PACK_VECTOR0 |
107 (UART_TX_PACK_VECTOR1 << 10));
108 write32(&regs->geni_tx_packing_cfg1, UART_TX_PACK_VECTOR2 |
109 (UART_TX_PACK_VECTOR3 << 10));
110 write32(&regs->geni_rx_packing_cfg0, UART_RX_PACK_VECTOR0);
111 write32(&regs->geni_rx_packing_cfg1, UART_RX_PACK_VECTOR2);
113 /* Start RX */
114 write32(&regs->geni_s_cmd0, START_UART_RX);
117 unsigned char uart_rx_byte(int idx)
119 struct qup_regs *regs = qup[idx].regs;
121 if (read32(&regs->geni_rx_fifo_status) & RX_FIFO_WC_MSK)
122 return read32(&regs->geni_rx_fifon) & 0xFF;
123 return 0;
126 void uart_tx_byte(int idx, unsigned char data)
128 struct qup_regs *regs = qup[idx].regs;
130 uart_tx_flush(idx);
132 write32(&regs->uart_tx_trans_len, 1);
133 /* Start TX */
134 write32(&regs->geni_m_cmd0, START_UART_TX);
135 write32(&regs->geni_tx_fifon, data);
138 uintptr_t uart_platform_base(int idx)
140 return (uintptr_t)qup[idx].regs;
143 void uart_fill_lb(void *data)
145 struct lb_serial serial = {0};
147 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
148 serial.baseaddr = (uint32_t)uart_platform_base(CONFIG_UART_FOR_CONSOLE);
149 serial.baud = get_uart_baudrate();
150 serial.regwidth = 4;
151 serial.input_hertz = QUPV3_UART_SRC_HZ;
153 lb_add_serial(&serial, data);