xref: /rk3399_ARM-atf/plat/mediatek/drivers/uart/8250_console.S (revision 04f28f895f1dc8683838a1382c8f92881f4cf21d)
1*3374752fSBo-Chen Chen/*
2*3374752fSBo-Chen Chen * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
3*3374752fSBo-Chen Chen *
4*3374752fSBo-Chen Chen * SPDX-License-Identifier: BSD-3-Clause
5*3374752fSBo-Chen Chen */
6*3374752fSBo-Chen Chen#include <asm_macros.S>
7*3374752fSBo-Chen Chen#include <uart8250.h>
8*3374752fSBo-Chen Chen
9*3374752fSBo-Chen Chen	.globl	console_core_init
10*3374752fSBo-Chen Chen	.globl	console_core_putc
11*3374752fSBo-Chen Chen	.globl	console_core_getc
12*3374752fSBo-Chen Chen	.globl	console_core_flush
13*3374752fSBo-Chen Chen
14*3374752fSBo-Chen Chen	/* -----------------------------------------------
15*3374752fSBo-Chen Chen	 * int console_core_init(unsigned long base_addr,
16*3374752fSBo-Chen Chen	 * unsigned int uart_clk, unsigned int baud_rate)
17*3374752fSBo-Chen Chen	 * Function to initialize the console without a
18*3374752fSBo-Chen Chen	 * C Runtime to print debug information. This
19*3374752fSBo-Chen Chen	 * function will be accessed by console_init and
20*3374752fSBo-Chen Chen	 * crash reporting.
21*3374752fSBo-Chen Chen	 * In: x0 - console base address
22*3374752fSBo-Chen Chen	 *     w1 - Uart clock in Hz
23*3374752fSBo-Chen Chen	 *     w2 - Baud rate
24*3374752fSBo-Chen Chen	 * Out: return 1 on success else 0 on error
25*3374752fSBo-Chen Chen	 * Clobber list : x1, x2, x3
26*3374752fSBo-Chen Chen	 * -----------------------------------------------
27*3374752fSBo-Chen Chen	 */
28*3374752fSBo-Chen Chenfunc console_core_init
29*3374752fSBo-Chen Chen	/* Check the input base address */
30*3374752fSBo-Chen Chen	cbz	x0, core_init_fail
31*3374752fSBo-Chen Chen	/* Check baud rate and uart clock for sanity */
32*3374752fSBo-Chen Chen	cbz	w1, core_init_fail
33*3374752fSBo-Chen Chen	cbz	w2, core_init_fail
34*3374752fSBo-Chen Chen
35*3374752fSBo-Chen Chen	/* Disable interrupt */
36*3374752fSBo-Chen Chen	str	wzr, [x0, #UART_IER]
37*3374752fSBo-Chen Chen
38*3374752fSBo-Chen Chen	/* Force DTR and RTS to high */
39*3374752fSBo-Chen Chen	mov	w3, #(UART_MCR_DTR | UART_MCR_RTS)
40*3374752fSBo-Chen Chen	str	w3, [x0, #UART_MCR]
41*3374752fSBo-Chen Chen
42*3374752fSBo-Chen Chen	/* Check high speed */
43*3374752fSBo-Chen Chen	movz	w3, #:abs_g1:115200
44*3374752fSBo-Chen Chen	movk	w3, #:abs_g0_nc:115200
45*3374752fSBo-Chen Chen	cmp	w2, w3
46*3374752fSBo-Chen Chen	b.hi	1f
47*3374752fSBo-Chen Chen
48*3374752fSBo-Chen Chen	/* Non high speed */
49*3374752fSBo-Chen Chen	lsl	w2, w2, #4
50*3374752fSBo-Chen Chen	mov	w3, wzr
51*3374752fSBo-Chen Chen	b	2f
52*3374752fSBo-Chen Chen
53*3374752fSBo-Chen Chen	/* High speed */
54*3374752fSBo-Chen Chen1:	lsl	w2, w2, #2
55*3374752fSBo-Chen Chen	mov	w3, #2
56*3374752fSBo-Chen Chen
57*3374752fSBo-Chen Chen	/* Set high speed UART register */
58*3374752fSBo-Chen Chen2:	str	w3, [x0, #UART_HIGHSPEED]
59*3374752fSBo-Chen Chen
60*3374752fSBo-Chen Chen	/* Calculate divisor */
61*3374752fSBo-Chen Chen	udiv	w3, w1, w2	/* divisor = uartclk / (quot * baudrate) */
62*3374752fSBo-Chen Chen	msub	w1, w3, w2, w1	/* remainder = uartclk % (quot * baudrate) */
63*3374752fSBo-Chen Chen	lsr	w2, w2, #1
64*3374752fSBo-Chen Chen	cmp	w1, w2
65*3374752fSBo-Chen Chen	cinc	w3, w3, hs
66*3374752fSBo-Chen Chen
67*3374752fSBo-Chen Chen	/* Set line configuration, access divisor latches */
68*3374752fSBo-Chen Chen	mov	w1, #(UART_LCR_DLAB | UART_LCR_WLS_8)
69*3374752fSBo-Chen Chen	str	w1, [x0, #UART_LCR]
70*3374752fSBo-Chen Chen
71*3374752fSBo-Chen Chen	/* Set the divisor */
72*3374752fSBo-Chen Chen	and	w1, w3, #0xff
73*3374752fSBo-Chen Chen	str	w1, [x0, #UART_DLL]
74*3374752fSBo-Chen Chen	lsr	w1, w3, #8
75*3374752fSBo-Chen Chen	and	w1, w1, #0xff
76*3374752fSBo-Chen Chen	str	w1, [x0, #UART_DLH]
77*3374752fSBo-Chen Chen
78*3374752fSBo-Chen Chen	/* Hide the divisor latches */
79*3374752fSBo-Chen Chen	mov	w1, #UART_LCR_WLS_8
80*3374752fSBo-Chen Chen	str	w1, [x0, #UART_LCR]
81*3374752fSBo-Chen Chen
82*3374752fSBo-Chen Chen	/* Enable FIFOs, and clear receive and transmit */
83*3374752fSBo-Chen Chen	mov	w1, #(UART_FCR_FIFO_EN | UART_FCR_CLEAR_RCVR |	\
84*3374752fSBo-Chen Chen			UART_FCR_CLEAR_XMIT)
85*3374752fSBo-Chen Chen	str	w1, [x0, #UART_FCR]
86*3374752fSBo-Chen Chen
87*3374752fSBo-Chen Chen	mov	w0, #1
88*3374752fSBo-Chen Chen	ret
89*3374752fSBo-Chen Chencore_init_fail:
90*3374752fSBo-Chen Chen	mov	w0, wzr
91*3374752fSBo-Chen Chen	ret
92*3374752fSBo-Chen Chenendfunc console_core_init
93*3374752fSBo-Chen Chen
94*3374752fSBo-Chen Chen	/* --------------------------------------------------------
95*3374752fSBo-Chen Chen	 * int console_core_putc(int c, unsigned long base_addr)
96*3374752fSBo-Chen Chen	 * Function to output a character over the console. It
97*3374752fSBo-Chen Chen	 * returns the character printed on success or -1 on error.
98*3374752fSBo-Chen Chen	 * In : w0 - character to be printed
99*3374752fSBo-Chen Chen	 *      x1 - console base address
100*3374752fSBo-Chen Chen	 * Out : return -1 on error else return character.
101*3374752fSBo-Chen Chen	 * Clobber list : x2
102*3374752fSBo-Chen Chen	 * --------------------------------------------------------
103*3374752fSBo-Chen Chen	 */
104*3374752fSBo-Chen Chenfunc console_core_putc
105*3374752fSBo-Chen Chen	/* Check the input parameter */
106*3374752fSBo-Chen Chen	cbz	x1, putc_error
107*3374752fSBo-Chen Chen	/* Prepend '\r' to '\n' */
108*3374752fSBo-Chen Chen	cmp	w0, #0xA
109*3374752fSBo-Chen Chen	b.ne	2f
110*3374752fSBo-Chen Chen
111*3374752fSBo-Chen Chen	/* Check if the transmit FIFO is full */
112*3374752fSBo-Chen Chen1:	ldr	w2, [x1, #UART_LSR]
113*3374752fSBo-Chen Chen	and	w2, w2, #UART_LSR_THRE
114*3374752fSBo-Chen Chen	cbz	w2, 1b
115*3374752fSBo-Chen Chen	mov	w2, #0xD
116*3374752fSBo-Chen Chen	str	w2, [x1, #UART_THR]
117*3374752fSBo-Chen Chen
118*3374752fSBo-Chen Chen	/* Check if the transmit FIFO is full */
119*3374752fSBo-Chen Chen2:	ldr	w2, [x1, #UART_LSR]
120*3374752fSBo-Chen Chen	and	w2, w2, #UART_LSR_THRE
121*3374752fSBo-Chen Chen	cbz	w2, 2b
122*3374752fSBo-Chen Chen	str	w0, [x1, #UART_THR]
123*3374752fSBo-Chen Chen	ret
124*3374752fSBo-Chen Chenputc_error:
125*3374752fSBo-Chen Chen	mov	w0, #-1
126*3374752fSBo-Chen Chen	ret
127*3374752fSBo-Chen Chenendfunc console_core_putc
128*3374752fSBo-Chen Chen
129*3374752fSBo-Chen Chen	/* ---------------------------------------------
130*3374752fSBo-Chen Chen	 * int console_core_getc(unsigned long base_addr)
131*3374752fSBo-Chen Chen	 * Function to get a character from the console.
132*3374752fSBo-Chen Chen	 * It returns the character grabbed on success
133*3374752fSBo-Chen Chen	 * or -1 on error.
134*3374752fSBo-Chen Chen	 * In : x0 - console base address
135*3374752fSBo-Chen Chen	 * Clobber list : x0, x1
136*3374752fSBo-Chen Chen	 * ---------------------------------------------
137*3374752fSBo-Chen Chen	 */
138*3374752fSBo-Chen Chenfunc console_core_getc
139*3374752fSBo-Chen Chen	cbz	x0, getc_error
140*3374752fSBo-Chen Chen
141*3374752fSBo-Chen Chen	/* Check if the receive FIFO is empty */
142*3374752fSBo-Chen Chen1:	ldr	w1, [x0, #UART_LSR]
143*3374752fSBo-Chen Chen	tbz	w1, #UART_LSR_DR, 1b
144*3374752fSBo-Chen Chen	ldr	w0, [x0, #UART_RBR]
145*3374752fSBo-Chen Chen	ret
146*3374752fSBo-Chen Chengetc_error:
147*3374752fSBo-Chen Chen	mov	w0, #-1
148*3374752fSBo-Chen Chen	ret
149*3374752fSBo-Chen Chenendfunc console_core_getc
150*3374752fSBo-Chen Chen
151*3374752fSBo-Chen Chen	/* ---------------------------------------------
152*3374752fSBo-Chen Chen	 * void console_core_flush(uintptr_t base_addr)
153*3374752fSBo-Chen Chen	 * Function to force a write of all buffered
154*3374752fSBo-Chen Chen	 * data that hasn't been output.
155*3374752fSBo-Chen Chen	 * In : x0 - console base address
156*3374752fSBo-Chen Chen	 * Out : void.
157*3374752fSBo-Chen Chen	 * Clobber list : x0, x1
158*3374752fSBo-Chen Chen	 * ---------------------------------------------
159*3374752fSBo-Chen Chen	 */
160*3374752fSBo-Chen Chenfunc console_core_flush
161*3374752fSBo-Chen Chen	/* Placeholder */
162*3374752fSBo-Chen Chen	ret
163*3374752fSBo-Chen Chenendfunc console_core_flush
164