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