xref: /rk3399_ARM-atf/drivers/ti/uart/aarch64/16550_console.S (revision 36c42ca111ea44e10d3589e93fa18a2b8162b6a3)
19c94d3b3SSoby Mathew/*
2ad4c2ec6SAntonio Nino Diaz * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
39c94d3b3SSoby Mathew *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
59c94d3b3SSoby Mathew */
69c94d3b3SSoby Mathew
79c94d3b3SSoby Mathew#include <arch.h>
89c94d3b3SSoby Mathew#include <asm_macros.S>
9*36c42ca1SJulius Werner#include <assert_macros.S>
10*36c42ca1SJulius Werner#include <console_macros.S>
119c94d3b3SSoby Mathew#include <uart_16550.h>
129c94d3b3SSoby Mathew
13*36c42ca1SJulius Werner	/*
14*36c42ca1SJulius Werner	 * "core" functions are low-level implementations that don't require
15*36c42ca1SJulius Werner	 * writable memory and are thus safe to call in BL1 crash context.
16*36c42ca1SJulius Werner	 */
17*36c42ca1SJulius Werner	.globl console_16550_core_init
18*36c42ca1SJulius Werner	.globl console_16550_core_putc
19*36c42ca1SJulius Werner	.globl console_16550_core_getc
20*36c42ca1SJulius Werner
21*36c42ca1SJulius Werner	.globl console_16550_putc
22*36c42ca1SJulius Werner	.globl console_16550_getc
23*36c42ca1SJulius Werner
249c94d3b3SSoby Mathew
259c94d3b3SSoby Mathew	/* -----------------------------------------------
26*36c42ca1SJulius Werner	 * int console_16550_core_init(uintptr_t base_addr,
279c94d3b3SSoby Mathew	 * unsigned int uart_clk, unsigned int baud_rate)
289c94d3b3SSoby Mathew	 * Function to initialize the console without a
299c94d3b3SSoby Mathew	 * C Runtime to print debug information. This
309c94d3b3SSoby Mathew	 * function will be accessed by console_init and
319c94d3b3SSoby Mathew	 * crash reporting.
329c94d3b3SSoby Mathew	 * In: x0 - console base address
339c94d3b3SSoby Mathew	 *     w1 - Uart clock in Hz
349c94d3b3SSoby Mathew	 *     w2 - Baud rate
35*36c42ca1SJulius Werner	 * Out: return 1 on success, 0 on error
369c94d3b3SSoby Mathew	 * Clobber list : x1, x2, x3
379c94d3b3SSoby Mathew	 * -----------------------------------------------
389c94d3b3SSoby Mathew	 */
39*36c42ca1SJulius Wernerfunc console_16550_core_init
409c94d3b3SSoby Mathew	/* Check the input base address */
419c94d3b3SSoby Mathew	cbz	x0, init_fail
429c94d3b3SSoby Mathew	/* Check baud rate and uart clock for sanity */
439c94d3b3SSoby Mathew	cbz	w1, init_fail
449c94d3b3SSoby Mathew	cbz	w2, init_fail
459c94d3b3SSoby Mathew
469c94d3b3SSoby Mathew	/* Program the baudrate */
479c94d3b3SSoby Mathew	/* Divisor =  Uart clock / (16 * baudrate) */
489c94d3b3SSoby Mathew	lsl	w2, w2, #4
499c94d3b3SSoby Mathew	udiv	w2, w1, w2
509c94d3b3SSoby Mathew	and	w1, w2, #0xff		/* w1 = DLL */
519c94d3b3SSoby Mathew	lsr	w2, w2, #8
529c94d3b3SSoby Mathew	and	w2, w2, #0xff		/* w2 = DLLM */
539c94d3b3SSoby Mathew	ldr	w3, [x0, #UARTLCR]
549c94d3b3SSoby Mathew	orr	w3, w3, #UARTLCR_DLAB
559c94d3b3SSoby Mathew	str	w3, [x0, #UARTLCR]	/* enable DLL, DLLM programming */
569c94d3b3SSoby Mathew	str	w1, [x0, #UARTDLL]	/* program DLL */
579c94d3b3SSoby Mathew	str	w2, [x0, #UARTDLLM]	/* program DLLM */
589c94d3b3SSoby Mathew	mov	w2, #~UARTLCR_DLAB
599c94d3b3SSoby Mathew	and	w3, w3, w2
609c94d3b3SSoby Mathew	str	w3, [x0, #UARTLCR]	/* disable DLL, DLLM programming */
619c94d3b3SSoby Mathew
629c94d3b3SSoby Mathew	/* 8n1 */
639c94d3b3SSoby Mathew	mov	w3, #3
649c94d3b3SSoby Mathew	str	w3, [x0, #UARTLCR]
659c94d3b3SSoby Mathew	/* no interrupt */
669c94d3b3SSoby Mathew	mov	w3, #0
679c94d3b3SSoby Mathew	str	w3, [x0, #UARTIER]
689c94d3b3SSoby Mathew	/* enable fifo, DMA */
699c94d3b3SSoby Mathew	mov	w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
709c94d3b3SSoby Mathew	str	w3, [x0, #UARTFCR]
719c94d3b3SSoby Mathew	/* DTR + RTS */
729c94d3b3SSoby Mathew	mov	w3, #3
739c94d3b3SSoby Mathew	str	w3, [x0, #UARTMCR]
749c94d3b3SSoby Mathew	mov	w0, #1
759c94d3b3SSoby Mathew	ret
76*36c42ca1SJulius Wernerinit_fail:
77*36c42ca1SJulius Werner	mov	w0, #0
78*36c42ca1SJulius Werner	ret
79*36c42ca1SJulius Wernerendfunc console_16550_core_init
80*36c42ca1SJulius Werner
81*36c42ca1SJulius Werner#if MULTI_CONSOLE_API
82*36c42ca1SJulius Werner	.globl console_16550_register
83*36c42ca1SJulius Werner
84*36c42ca1SJulius Werner	/* -----------------------------------------------
85*36c42ca1SJulius Werner	 * int console_16550_register(console_16550_t *console,
86*36c42ca1SJulius Werner		uintptr_t base, uint32_t clk, uint32_t baud)
87*36c42ca1SJulius Werner	 * Function to initialize and register a new 16550
88*36c42ca1SJulius Werner	 * console. Storage passed in for the console struct
89*36c42ca1SJulius Werner	 * *must* be persistent (i.e. not from the stack).
90*36c42ca1SJulius Werner	 * In: x0 - UART register base address
91*36c42ca1SJulius Werner	 *     w1 - UART clock in Hz
92*36c42ca1SJulius Werner	 *     w2 - Baud rate
93*36c42ca1SJulius Werner	 *     x3 - pointer to empty console_16550_t struct
94*36c42ca1SJulius Werner	 * Out: return 1 on success, 0 on error
95*36c42ca1SJulius Werner	 * Clobber list : x0, x1, x2, x6, x7, x14
96*36c42ca1SJulius Werner	 * -----------------------------------------------
97*36c42ca1SJulius Werner	 */
98*36c42ca1SJulius Wernerfunc console_16550_register
99*36c42ca1SJulius Werner	mov	x7, x30
100*36c42ca1SJulius Werner	mov	x6, x3
101*36c42ca1SJulius Werner	cbz	x6, register_fail
102*36c42ca1SJulius Werner	str	x0, [x6, #CONSOLE_T_16550_BASE]
103*36c42ca1SJulius Werner
104*36c42ca1SJulius Werner	bl	console_16550_core_init
105*36c42ca1SJulius Werner	cbz	x0, register_fail
106*36c42ca1SJulius Werner
107*36c42ca1SJulius Werner	mov	x0, x6
108*36c42ca1SJulius Werner	mov	x30, x7
109*36c42ca1SJulius Werner	finish_console_register 16550
110*36c42ca1SJulius Werner
111*36c42ca1SJulius Wernerregister_fail:
112*36c42ca1SJulius Werner	ret	x7
113*36c42ca1SJulius Wernerendfunc console_16550_register
114*36c42ca1SJulius Werner#else
115*36c42ca1SJulius Werner	.globl console_core_init
116*36c42ca1SJulius Werner	.globl console_core_putc
117*36c42ca1SJulius Werner	.globl console_core_getc
118*36c42ca1SJulius Werner	.globl console_core_flush
119*36c42ca1SJulius Werner	.equ console_core_init,console_16550_core_init
120*36c42ca1SJulius Werner	.equ console_core_putc,console_16550_core_putc
121*36c42ca1SJulius Werner	.equ console_core_getc,console_16550_core_getc
122*36c42ca1SJulius Werner#endif
1239c94d3b3SSoby Mathew
1249c94d3b3SSoby Mathew	/* --------------------------------------------------------
125*36c42ca1SJulius Werner	 * int console_16550_core_putc(int c, uintptr_t base_addr)
1269c94d3b3SSoby Mathew	 * Function to output a character over the console. It
1279c94d3b3SSoby Mathew	 * returns the character printed on success or -1 on error.
1289c94d3b3SSoby Mathew	 * In : w0 - character to be printed
1299c94d3b3SSoby Mathew	 *      x1 - console base address
1309c94d3b3SSoby Mathew	 * Out : return -1 on error else return character.
1319c94d3b3SSoby Mathew	 * Clobber list : x2
1329c94d3b3SSoby Mathew	 * --------------------------------------------------------
1339c94d3b3SSoby Mathew	 */
134*36c42ca1SJulius Wernerfunc console_16550_core_putc
135*36c42ca1SJulius Werner#if ENABLE_ASSERTIONS
136*36c42ca1SJulius Werner	cmp	x1, #0
137*36c42ca1SJulius Werner	ASM_ASSERT(ne)
138*36c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
1399c94d3b3SSoby Mathew
1409c94d3b3SSoby Mathew	/* Prepend '\r' to '\n' */
1419c94d3b3SSoby Mathew	cmp	w0, #0xA
1429c94d3b3SSoby Mathew	b.ne	2f
1439c94d3b3SSoby Mathew	/* Check if the transmit FIFO is full */
1449c94d3b3SSoby Mathew1:	ldr	w2, [x1, #UARTLSR]
1459c94d3b3SSoby Mathew	and	w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
1469c94d3b3SSoby Mathew	cmp	w2, #(UARTLSR_TEMT | UARTLSR_THRE)
1479c94d3b3SSoby Mathew	b.ne	1b
1489c94d3b3SSoby Mathew	mov	w2, #0xD		/* '\r' */
1499c94d3b3SSoby Mathew	str	w2, [x1, #UARTTX]
1509c94d3b3SSoby Mathew
1519c94d3b3SSoby Mathew	/* Check if the transmit FIFO is full */
1529c94d3b3SSoby Mathew2:	ldr	w2, [x1, #UARTLSR]
1539c94d3b3SSoby Mathew	and	w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
1549c94d3b3SSoby Mathew	cmp	w2, #(UARTLSR_TEMT | UARTLSR_THRE)
1559c94d3b3SSoby Mathew	b.ne	2b
1569c94d3b3SSoby Mathew	str	w0, [x1, #UARTTX]
1579c94d3b3SSoby Mathew	ret
158*36c42ca1SJulius Wernerendfunc console_16550_core_putc
159*36c42ca1SJulius Werner
160*36c42ca1SJulius Werner	/* --------------------------------------------------------
161*36c42ca1SJulius Werner	 * int console_16550_putc(int c, console_16550_t *console)
162*36c42ca1SJulius Werner	 * Function to output a character over the console. It
163*36c42ca1SJulius Werner	 * returns the character printed on success or -1 on error.
164*36c42ca1SJulius Werner	 * In : w0 - character to be printed
165*36c42ca1SJulius Werner	 *      x1 - pointer to console_t structure
166*36c42ca1SJulius Werner	 * Out : return -1 on error else return character.
167*36c42ca1SJulius Werner	 * Clobber list : x2
168*36c42ca1SJulius Werner	 * --------------------------------------------------------
169*36c42ca1SJulius Werner	 */
170*36c42ca1SJulius Wernerfunc console_16550_putc
171*36c42ca1SJulius Werner#if ENABLE_ASSERTIONS
172*36c42ca1SJulius Werner	cmp	x1, #0
173*36c42ca1SJulius Werner	ASM_ASSERT(ne)
174*36c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
175*36c42ca1SJulius Werner	ldr	x1, [x1, #CONSOLE_T_16550_BASE]
176*36c42ca1SJulius Werner	b	console_16550_core_putc
177*36c42ca1SJulius Wernerendfunc console_16550_putc
1789c94d3b3SSoby Mathew
1799c94d3b3SSoby Mathew	/* ---------------------------------------------
180*36c42ca1SJulius Werner	 * int console_16550_core_getc(uintptr_t base_addr)
1819c94d3b3SSoby Mathew	 * Function to get a character from the console.
1829c94d3b3SSoby Mathew	 * It returns the character grabbed on success
183*36c42ca1SJulius Werner	 * or -1 on if no character is available.
184*36c42ca1SJulius Werner	 * In :  x0 - console base address
185*36c42ca1SJulius Werner	 * Out : w0 - character if available, else -1
1869c94d3b3SSoby Mathew	 * Clobber list : x0, x1
1879c94d3b3SSoby Mathew	 * ---------------------------------------------
1889c94d3b3SSoby Mathew	 */
189*36c42ca1SJulius Wernerfunc console_16550_core_getc
190*36c42ca1SJulius Werner#if ENABLE_ASSERTIONS
191*36c42ca1SJulius Werner	cmp	x0, #0
192*36c42ca1SJulius Werner	ASM_ASSERT(ne)
193*36c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
194*36c42ca1SJulius Werner
1959c94d3b3SSoby Mathew	/* Check if the receive FIFO is empty */
1969c94d3b3SSoby Mathew1:	ldr	w1, [x0, #UARTLSR]
197*36c42ca1SJulius Werner	tbz	w1, #UARTLSR_RDR_BIT, no_char
1989c94d3b3SSoby Mathew	ldr	w0, [x0, #UARTRX]
1999c94d3b3SSoby Mathew	ret
200*36c42ca1SJulius Wernerno_char:
201*36c42ca1SJulius Werner	mov	w0, #ERROR_NO_PENDING_CHAR
2029c94d3b3SSoby Mathew	ret
203*36c42ca1SJulius Wernerendfunc console_16550_core_getc
204*36c42ca1SJulius Werner
205*36c42ca1SJulius Werner	/* ---------------------------------------------
206*36c42ca1SJulius Werner	 * int console_16550_getc(console_16550_t *console)
207*36c42ca1SJulius Werner	 * Function to get a character from the console.
208*36c42ca1SJulius Werner	 * It returns the character grabbed on success
209*36c42ca1SJulius Werner	 * or -1 on if no character is available.
210*36c42ca1SJulius Werner	 * In :  x0 - pointer to console_t stucture
211*36c42ca1SJulius Werner	 * Out : w0 - character if available, else -1
212*36c42ca1SJulius Werner	 * Clobber list : x0, x1
213*36c42ca1SJulius Werner	 * ---------------------------------------------
214*36c42ca1SJulius Werner	 */
215*36c42ca1SJulius Wernerfunc console_16550_getc
216*36c42ca1SJulius Werner#if ENABLE_ASSERTIONS
217*36c42ca1SJulius Werner	cmp	x1, #0
218*36c42ca1SJulius Werner	ASM_ASSERT(ne)
219*36c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
220*36c42ca1SJulius Werner	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
221*36c42ca1SJulius Werner	b	console_16550_core_getc
222*36c42ca1SJulius Wernerendfunc console_16550_getc
223ad4c2ec6SAntonio Nino Diaz
224ad4c2ec6SAntonio Nino Diaz	/* ---------------------------------------------
225ad4c2ec6SAntonio Nino Diaz	 * int console_core_flush(uintptr_t base_addr)
226*36c42ca1SJulius Werner	 * DEPRECATED: Not used with MULTI_CONSOLE_API!
227ad4c2ec6SAntonio Nino Diaz	 * Function to force a write of all buffered
228ad4c2ec6SAntonio Nino Diaz	 * data that hasn't been output.
229ad4c2ec6SAntonio Nino Diaz	 * In : x0 - console base address
230ad4c2ec6SAntonio Nino Diaz	 * Out : return -1 on error else return 0.
231ad4c2ec6SAntonio Nino Diaz	 * Clobber list : x0, x1
232ad4c2ec6SAntonio Nino Diaz	 * ---------------------------------------------
233ad4c2ec6SAntonio Nino Diaz	 */
234ad4c2ec6SAntonio Nino Diazfunc console_core_flush
235ad4c2ec6SAntonio Nino Diaz	/* Placeholder */
236ad4c2ec6SAntonio Nino Diaz	mov	w0, #0
237ad4c2ec6SAntonio Nino Diaz	ret
238ad4c2ec6SAntonio Nino Diazendfunc console_core_flush
239