1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun #include <linux/console.h>
6*4882a593Smuzhiyun #include <linux/delay.h>
7*4882a593Smuzhiyun #include <linux/io.h>
8*4882a593Smuzhiyun #include <linux/serial_core.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #define SE_GENI_DMA_MODE_EN 0x258
11*4882a593Smuzhiyun #define SE_UART_TX_TRANS_CFG 0x25C
12*4882a593Smuzhiyun #define SE_UART_TX_WORD_LEN 0x268
13*4882a593Smuzhiyun #define SE_UART_TX_STOP_BIT_LEN 0x26C
14*4882a593Smuzhiyun #define SE_UART_TX_TRANS_LEN 0x270
15*4882a593Smuzhiyun #define SE_UART_TX_PARITY_CFG 0x2A4
16*4882a593Smuzhiyun /* SE_UART_TRANS_CFG */
17*4882a593Smuzhiyun #define UART_CTS_MASK BIT(1)
18*4882a593Smuzhiyun /* UART M_CMD OP codes */
19*4882a593Smuzhiyun #define UART_START_TX 0x1
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define UART_OVERSAMPLING 32
22*4882a593Smuzhiyun #define DEF_FIFO_DEPTH_WORDS 16
23*4882a593Smuzhiyun #define DEF_TX_WM 2
24*4882a593Smuzhiyun #define DEF_FIFO_WIDTH_BITS 32
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #define GENI_FORCE_DEFAULT_REG 0x20
27*4882a593Smuzhiyun #define GENI_OUTPUT_CTRL 0x24
28*4882a593Smuzhiyun #define GENI_CGC_CTRL 0x28
29*4882a593Smuzhiyun #define GENI_SER_M_CLK_CFG 0x48
30*4882a593Smuzhiyun #define GENI_FW_REVISION_RO 0x68
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define SE_GENI_TX_PACKING_CFG0 0x260
33*4882a593Smuzhiyun #define SE_GENI_TX_PACKING_CFG1 0x264
34*4882a593Smuzhiyun #define SE_GENI_M_CMD0 0x600
35*4882a593Smuzhiyun #define SE_GENI_M_CMD_CTRL_REG 0x604
36*4882a593Smuzhiyun #define SE_GENI_M_IRQ_STATUS 0x610
37*4882a593Smuzhiyun #define SE_GENI_M_IRQ_EN 0x614
38*4882a593Smuzhiyun #define SE_GENI_M_IRQ_CLEAR 0x618
39*4882a593Smuzhiyun #define SE_GENI_TX_FIFOn 0x700
40*4882a593Smuzhiyun #define SE_GENI_TX_WATERMARK_REG 0x80C
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define SE_IRQ_EN 0xE1C
43*4882a593Smuzhiyun #define SE_HW_PARAM_0 0xE24
44*4882a593Smuzhiyun #define SE_HW_PARAM_1 0xE28
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* GENI_OUTPUT_CTRL fields */
47*4882a593Smuzhiyun #define DEFAULT_IO_OUTPUT_CTRL_MSK GENMASK(6, 0)
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* GENI_FORCE_DEFAULT_REG fields */
50*4882a593Smuzhiyun #define FORCE_DEFAULT BIT(0)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* GENI_CGC_CTRL fields */
53*4882a593Smuzhiyun #define CFG_AHB_CLK_CGC_ON BIT(0)
54*4882a593Smuzhiyun #define CFG_AHB_WR_ACLK_CGC_ON BIT(1)
55*4882a593Smuzhiyun #define DATA_AHB_CLK_CGC_ON BIT(2)
56*4882a593Smuzhiyun #define SCLK_CGC_ON BIT(3)
57*4882a593Smuzhiyun #define TX_CLK_CGC_ON BIT(4)
58*4882a593Smuzhiyun #define RX_CLK_CGC_ON BIT(5)
59*4882a593Smuzhiyun #define EXT_CLK_CGC_ON BIT(6)
60*4882a593Smuzhiyun #define PROG_RAM_HCLK_OFF BIT(8)
61*4882a593Smuzhiyun #define PROG_RAM_SCLK_OFF BIT(9)
62*4882a593Smuzhiyun #define DEFAULT_CGC_EN GENMASK(6, 0)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* GENI_STATUS fields */
65*4882a593Smuzhiyun #define M_GENI_CMD_ACTIVE BIT(0)
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */
68*4882a593Smuzhiyun #define SER_CLK_EN BIT(0)
69*4882a593Smuzhiyun #define CLK_DIV_MSK GENMASK(15, 4)
70*4882a593Smuzhiyun #define CLK_DIV_SHFT 4
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /* CLK_CTRL_RO fields */
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* FIFO_IF_DISABLE_RO fields */
75*4882a593Smuzhiyun #define FIFO_IF_DISABLE BIT(0)
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* FW_REVISION_RO fields */
78*4882a593Smuzhiyun #define FW_REV_PROTOCOL_MSK GENMASK(15, 8)
79*4882a593Smuzhiyun #define FW_REV_PROTOCOL_SHFT 8
80*4882a593Smuzhiyun #define FW_REV_VERSION_MSK GENMASK(7, 0)
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* GENI_CLK_SEL fields */
83*4882a593Smuzhiyun #define CLK_SEL_MSK GENMASK(2, 0)
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* SE_GENI_DMA_MODE_EN */
86*4882a593Smuzhiyun #define GENI_DMA_MODE_EN BIT(0)
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /* GENI_M_CMD0 fields */
89*4882a593Smuzhiyun #define M_OPCODE_MSK GENMASK(31, 27)
90*4882a593Smuzhiyun #define M_OPCODE_SHFT 27
91*4882a593Smuzhiyun #define M_PARAMS_MSK GENMASK(26, 0)
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /* GENI_M_CMD_CTRL_REG */
94*4882a593Smuzhiyun #define M_GENI_CMD_CANCEL BIT(2)
95*4882a593Smuzhiyun #define M_GENI_CMD_ABORT BIT(1)
96*4882a593Smuzhiyun #define M_GENI_DISABLE BIT(0)
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* GENI_M_IRQ_EN fields */
99*4882a593Smuzhiyun #define M_CMD_DONE_EN BIT(0)
100*4882a593Smuzhiyun #define M_CMD_OVERRUN_EN BIT(1)
101*4882a593Smuzhiyun #define M_ILLEGAL_CMD_EN BIT(2)
102*4882a593Smuzhiyun #define M_CMD_FAILURE_EN BIT(3)
103*4882a593Smuzhiyun #define M_CMD_CANCEL_EN BIT(4)
104*4882a593Smuzhiyun #define M_CMD_ABORT_EN BIT(5)
105*4882a593Smuzhiyun #define M_TIMESTAMP_EN BIT(6)
106*4882a593Smuzhiyun #define M_GP_SYNC_IRQ_0_EN BIT(8)
107*4882a593Smuzhiyun #define M_IO_DATA_DEASSERT_EN BIT(22)
108*4882a593Smuzhiyun #define M_IO_DATA_ASSERT_EN BIT(23)
109*4882a593Smuzhiyun #define M_TX_FIFO_RD_ERR_EN BIT(28)
110*4882a593Smuzhiyun #define M_TX_FIFO_WR_ERR_EN BIT(29)
111*4882a593Smuzhiyun #define M_TX_FIFO_WATERMARK_EN BIT(30)
112*4882a593Smuzhiyun #define M_SEC_IRQ_EN BIT(31)
113*4882a593Smuzhiyun #define M_COMMON_GENI_M_IRQ_EN (GENMASK(6, 1) | \
114*4882a593Smuzhiyun M_IO_DATA_DEASSERT_EN | \
115*4882a593Smuzhiyun M_IO_DATA_ASSERT_EN | M_TX_FIFO_RD_ERR_EN | \
116*4882a593Smuzhiyun M_TX_FIFO_WR_ERR_EN)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* GENI_TX_FIFO_STATUS fields */
119*4882a593Smuzhiyun #define TX_FIFO_WC GENMASK(27, 0)
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* SE_IRQ_EN fields */
122*4882a593Smuzhiyun #define GENI_M_IRQ_EN BIT(2)
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #define UART_PROTOCOL 2
125*4882a593Smuzhiyun
get_se_proto_earlycon(void __iomem * base)126*4882a593Smuzhiyun static int get_se_proto_earlycon(void __iomem *base)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun int proto;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun proto = ((readl_relaxed(base + GENI_FW_REVISION_RO)
131*4882a593Smuzhiyun & FW_REV_PROTOCOL_MSK) >> FW_REV_PROTOCOL_SHFT);
132*4882a593Smuzhiyun return proto;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
se_get_packing_config_earlycon(int bpw,int pack_words,bool msb_to_lsb,unsigned long * cfg0,unsigned long * cfg1)135*4882a593Smuzhiyun static void se_get_packing_config_earlycon(int bpw, int pack_words,
136*4882a593Smuzhiyun bool msb_to_lsb, unsigned long *cfg0, unsigned long *cfg1)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun u32 cfg[4] = {0};
139*4882a593Smuzhiyun int len, i;
140*4882a593Smuzhiyun int temp_bpw = bpw;
141*4882a593Smuzhiyun int idx_start = (msb_to_lsb ? (bpw - 1) : 0);
142*4882a593Smuzhiyun int idx_delta = (msb_to_lsb ? -BITS_PER_BYTE : BITS_PER_BYTE);
143*4882a593Smuzhiyun int ceil_bpw = ((bpw & (BITS_PER_BYTE - 1)) ?
144*4882a593Smuzhiyun ((bpw & ~(BITS_PER_BYTE - 1)) + BITS_PER_BYTE) : bpw);
145*4882a593Smuzhiyun int iter = (ceil_bpw * pack_words) >> 3;
146*4882a593Smuzhiyun int idx = idx_start;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (iter <= 0 || iter > 4) {
149*4882a593Smuzhiyun *cfg0 = 0;
150*4882a593Smuzhiyun *cfg1 = 0;
151*4882a593Smuzhiyun return;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun for (i = 0; i < iter; i++) {
155*4882a593Smuzhiyun len = (temp_bpw < BITS_PER_BYTE) ?
156*4882a593Smuzhiyun (temp_bpw - 1) : BITS_PER_BYTE - 1;
157*4882a593Smuzhiyun cfg[i] = ((idx << 5) | (msb_to_lsb << 4) | (len << 1));
158*4882a593Smuzhiyun idx = ((temp_bpw - BITS_PER_BYTE) <= 0) ?
159*4882a593Smuzhiyun ((i + 1) * BITS_PER_BYTE) + idx_start :
160*4882a593Smuzhiyun idx + idx_delta;
161*4882a593Smuzhiyun temp_bpw = ((temp_bpw - BITS_PER_BYTE) <= 0) ?
162*4882a593Smuzhiyun bpw : (temp_bpw - BITS_PER_BYTE);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun cfg[iter - 1] |= 1;
165*4882a593Smuzhiyun *cfg0 = cfg[0] | (cfg[1] << 10);
166*4882a593Smuzhiyun *cfg1 = cfg[2] | (cfg[3] << 10);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
se_io_init_earlycon(void __iomem * base)169*4882a593Smuzhiyun static void se_io_init_earlycon(void __iomem *base)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun u32 io_op_ctrl;
172*4882a593Smuzhiyun u32 geni_cgc_ctrl;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun geni_cgc_ctrl = readl_relaxed(base + GENI_CGC_CTRL);
175*4882a593Smuzhiyun geni_cgc_ctrl |= DEFAULT_CGC_EN;
176*4882a593Smuzhiyun io_op_ctrl = DEFAULT_IO_OUTPUT_CTRL_MSK;
177*4882a593Smuzhiyun writel_relaxed(geni_cgc_ctrl, base + GENI_CGC_CTRL);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun writel_relaxed(io_op_ctrl, base + GENI_OUTPUT_CTRL);
180*4882a593Smuzhiyun writel_relaxed(FORCE_DEFAULT, base + GENI_FORCE_DEFAULT_REG);
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
geni_se_select_fifo_mode_earlycon(void __iomem * base)183*4882a593Smuzhiyun static void geni_se_select_fifo_mode_earlycon(void __iomem *base)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun u32 val;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun val = readl_relaxed(base + SE_GENI_DMA_MODE_EN);
188*4882a593Smuzhiyun val &= ~GENI_DMA_MODE_EN;
189*4882a593Smuzhiyun writel_relaxed(val, base + SE_GENI_M_IRQ_EN);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
msm_geni_serial_wr_char(struct uart_port * uport,int ch)192*4882a593Smuzhiyun static void msm_geni_serial_wr_char(struct uart_port *uport, int ch)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun writel_relaxed(ch, uport->membase + SE_GENI_TX_FIFOn);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
msm_geni_serial_poll_bit(struct uart_port * uport,int offset,int bit_field,bool set)197*4882a593Smuzhiyun static int msm_geni_serial_poll_bit(struct uart_port *uport,
198*4882a593Smuzhiyun int offset, int bit_field, bool set)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun int iter = 0;
201*4882a593Smuzhiyun bool met = false, cond = false;
202*4882a593Smuzhiyun unsigned int reg, total_iter = 1000;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun while (iter < total_iter) {
205*4882a593Smuzhiyun reg = readl_relaxed(uport->membase + offset);
206*4882a593Smuzhiyun cond = reg & bit_field;
207*4882a593Smuzhiyun if (cond == set) {
208*4882a593Smuzhiyun met = true;
209*4882a593Smuzhiyun break;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun udelay(10);
212*4882a593Smuzhiyun iter++;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun return met;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
msm_geni_serial_poll_abort_tx(struct uart_port * uport)217*4882a593Smuzhiyun static void msm_geni_serial_poll_abort_tx(struct uart_port *uport)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun int done = 0;
220*4882a593Smuzhiyun u32 irq_clear = M_CMD_DONE_EN;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun done = msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
223*4882a593Smuzhiyun M_CMD_DONE_EN, true);
224*4882a593Smuzhiyun if (!done) {
225*4882a593Smuzhiyun writel_relaxed(M_GENI_CMD_ABORT,
226*4882a593Smuzhiyun uport->membase + SE_GENI_M_CMD_CTRL_REG);
227*4882a593Smuzhiyun irq_clear |= M_CMD_ABORT_EN;
228*4882a593Smuzhiyun msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
229*4882a593Smuzhiyun M_CMD_ABORT_EN, true);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun writel_relaxed(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
msm_geni_serial_setup_tx(struct uart_port * uport,unsigned int xmit_size)234*4882a593Smuzhiyun static void msm_geni_serial_setup_tx(struct uart_port *uport,
235*4882a593Smuzhiyun unsigned int xmit_size)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun u32 m_cmd = 0;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun writel_relaxed(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN);
240*4882a593Smuzhiyun m_cmd |= (UART_START_TX << M_OPCODE_SHFT);
241*4882a593Smuzhiyun writel_relaxed(m_cmd, uport->membase + SE_GENI_M_CMD0);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun static void
__msm_geni_serial_console_write(struct uart_port * uport,const char * s,unsigned int count)245*4882a593Smuzhiyun __msm_geni_serial_console_write(struct uart_port *uport, const char *s,
246*4882a593Smuzhiyun unsigned int count)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun int new_line = 0;
249*4882a593Smuzhiyun int i;
250*4882a593Smuzhiyun int bytes_to_send = count;
251*4882a593Smuzhiyun int fifo_depth = DEF_FIFO_DEPTH_WORDS;
252*4882a593Smuzhiyun int tx_wm = DEF_TX_WM;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun for (i = 0; i < count; i++) {
255*4882a593Smuzhiyun if (s[i] == '\n')
256*4882a593Smuzhiyun new_line++;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun bytes_to_send += new_line;
260*4882a593Smuzhiyun writel_relaxed(tx_wm, uport->membase + SE_GENI_TX_WATERMARK_REG);
261*4882a593Smuzhiyun msm_geni_serial_setup_tx(uport, bytes_to_send);
262*4882a593Smuzhiyun i = 0;
263*4882a593Smuzhiyun while (i < count) {
264*4882a593Smuzhiyun u32 chars_to_write = 0;
265*4882a593Smuzhiyun u32 avail_fifo_bytes = (fifo_depth - tx_wm);
266*4882a593Smuzhiyun /*
267*4882a593Smuzhiyun * If the WM bit never set, then the Tx state machine is not
268*4882a593Smuzhiyun * in a valid state, so break, cancel/abort any existing
269*4882a593Smuzhiyun * command. Unfortunately the current data being written is
270*4882a593Smuzhiyun * lost.
271*4882a593Smuzhiyun */
272*4882a593Smuzhiyun while (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
273*4882a593Smuzhiyun M_TX_FIFO_WATERMARK_EN, true))
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun chars_to_write = min((unsigned int)(count - i),
276*4882a593Smuzhiyun avail_fifo_bytes);
277*4882a593Smuzhiyun if ((chars_to_write << 1) > avail_fifo_bytes)
278*4882a593Smuzhiyun chars_to_write = (avail_fifo_bytes >> 1);
279*4882a593Smuzhiyun uart_console_write(uport, (s + i), chars_to_write,
280*4882a593Smuzhiyun msm_geni_serial_wr_char);
281*4882a593Smuzhiyun writel_relaxed(M_TX_FIFO_WATERMARK_EN,
282*4882a593Smuzhiyun uport->membase + SE_GENI_M_IRQ_CLEAR);
283*4882a593Smuzhiyun i += chars_to_write;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun msm_geni_serial_poll_abort_tx(uport);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static void
msm_geni_serial_early_console_write(struct console * con,const char * s,unsigned int n)289*4882a593Smuzhiyun msm_geni_serial_early_console_write(struct console *con, const char *s,
290*4882a593Smuzhiyun unsigned int n)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun struct earlycon_device *dev = con->data;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun __msm_geni_serial_console_write(&dev->port, s, n);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static int __init
msm_geni_serial_earlycon_setup(struct earlycon_device * dev,const char * opt)298*4882a593Smuzhiyun msm_geni_serial_earlycon_setup(struct earlycon_device *dev,
299*4882a593Smuzhiyun const char *opt)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun int ret = 0;
302*4882a593Smuzhiyun u32 tx_trans_cfg = 0;
303*4882a593Smuzhiyun u32 tx_parity_cfg = 0;
304*4882a593Smuzhiyun u32 stop_bit = 0;
305*4882a593Smuzhiyun u32 bits_per_char = 0;
306*4882a593Smuzhiyun unsigned long cfg0, cfg1;
307*4882a593Smuzhiyun struct uart_port *uport = &dev->port;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (!uport->membase) {
310*4882a593Smuzhiyun ret = -ENOMEM;
311*4882a593Smuzhiyun goto exit;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (get_se_proto_earlycon(uport->membase) != UART_PROTOCOL) {
315*4882a593Smuzhiyun ret = -ENXIO;
316*4882a593Smuzhiyun goto exit;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /*
320*4882a593Smuzhiyun * Ignore Flow control.
321*4882a593Smuzhiyun * Disable Tx Parity.
322*4882a593Smuzhiyun * Don't check Parity during Rx.
323*4882a593Smuzhiyun * Disable Rx Parity.
324*4882a593Smuzhiyun * n = 8.
325*4882a593Smuzhiyun * Stop bit = 0.
326*4882a593Smuzhiyun * Stale timeout in bit-time (3 chars worth).
327*4882a593Smuzhiyun */
328*4882a593Smuzhiyun tx_trans_cfg |= UART_CTS_MASK;
329*4882a593Smuzhiyun tx_parity_cfg = 0;
330*4882a593Smuzhiyun bits_per_char = 0x8;
331*4882a593Smuzhiyun stop_bit = 0;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun msm_geni_serial_poll_abort_tx(uport);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun se_get_packing_config_earlycon(8, 1, false, &cfg0, &cfg1);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun se_io_init_earlycon(uport->membase);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun geni_se_select_fifo_mode_earlycon(uport->membase);
340*4882a593Smuzhiyun writel_relaxed(cfg0, uport->membase + SE_GENI_TX_PACKING_CFG0);
341*4882a593Smuzhiyun writel_relaxed(cfg1, uport->membase + SE_GENI_TX_PACKING_CFG1);
342*4882a593Smuzhiyun writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG);
343*4882a593Smuzhiyun writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG);
344*4882a593Smuzhiyun writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN);
345*4882a593Smuzhiyun writel_relaxed(stop_bit, uport->membase + SE_UART_TX_STOP_BIT_LEN);
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun dev->con->write = msm_geni_serial_early_console_write;
348*4882a593Smuzhiyun dev->con->setup = NULL;
349*4882a593Smuzhiyun exit:
350*4882a593Smuzhiyun return ret;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun OF_EARLYCON_DECLARE(msm_geni_serial, "qcom,msm-geni-console",
354*4882a593Smuzhiyun msm_geni_serial_earlycon_setup);
355