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