xref: /rk3399_ARM-atf/drivers/ti/uart/aarch64/16550_console.S (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
19c94d3b3SSoby Mathew/*
24f8053ddSAntonio Nino Diaz * Copyright (c) 2015-2018, 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>
936c42ca1SJulius Werner#include <assert_macros.S>
10cc5859caSSoby Mathew#define USE_FINISH_CONSOLE_REG_2
1136c42ca1SJulius Werner#include <console_macros.S>
12*09d40e0eSAntonio Nino Diaz#include <drivers/ti/uart/uart_16550.h>
139c94d3b3SSoby Mathew
1436c42ca1SJulius Werner	/*
1536c42ca1SJulius Werner	 * "core" functions are low-level implementations that don't require
1636c42ca1SJulius Werner	 * writable memory and are thus safe to call in BL1 crash context.
1736c42ca1SJulius Werner	 */
1836c42ca1SJulius Werner	.globl console_16550_core_init
1936c42ca1SJulius Werner	.globl console_16550_core_putc
2036c42ca1SJulius Werner	.globl console_16550_core_getc
214f8053ddSAntonio Nino Diaz	.globl console_16550_core_flush
2236c42ca1SJulius Werner
2336c42ca1SJulius Werner	.globl console_16550_putc
2436c42ca1SJulius Werner	.globl console_16550_getc
254f8053ddSAntonio Nino Diaz	.globl console_16550_flush
269c94d3b3SSoby Mathew
279c94d3b3SSoby Mathew	/* -----------------------------------------------
2836c42ca1SJulius Werner	 * int console_16550_core_init(uintptr_t base_addr,
299c94d3b3SSoby Mathew	 * unsigned int uart_clk, unsigned int baud_rate)
309c94d3b3SSoby Mathew	 * Function to initialize the console without a
319c94d3b3SSoby Mathew	 * C Runtime to print debug information. This
329c94d3b3SSoby Mathew	 * function will be accessed by console_init and
339c94d3b3SSoby Mathew	 * crash reporting.
349c94d3b3SSoby Mathew	 * In: x0 - console base address
359c94d3b3SSoby Mathew	 *     w1 - Uart clock in Hz
369c94d3b3SSoby Mathew	 *     w2 - Baud rate
3736c42ca1SJulius Werner	 * Out: return 1 on success, 0 on error
389c94d3b3SSoby Mathew	 * Clobber list : x1, x2, x3
399c94d3b3SSoby Mathew	 * -----------------------------------------------
409c94d3b3SSoby Mathew	 */
4136c42ca1SJulius Wernerfunc console_16550_core_init
429c94d3b3SSoby Mathew	/* Check the input base address */
439c94d3b3SSoby Mathew	cbz	x0, init_fail
449c94d3b3SSoby Mathew	/* Check baud rate and uart clock for sanity */
459c94d3b3SSoby Mathew	cbz	w1, init_fail
469c94d3b3SSoby Mathew	cbz	w2, init_fail
479c94d3b3SSoby Mathew
489c94d3b3SSoby Mathew	/* Program the baudrate */
499c94d3b3SSoby Mathew	/* Divisor =  Uart clock / (16 * baudrate) */
509c94d3b3SSoby Mathew	lsl	w2, w2, #4
519c94d3b3SSoby Mathew	udiv	w2, w1, w2
529c94d3b3SSoby Mathew	and	w1, w2, #0xff		/* w1 = DLL */
539c94d3b3SSoby Mathew	lsr	w2, w2, #8
549c94d3b3SSoby Mathew	and	w2, w2, #0xff		/* w2 = DLLM */
559c94d3b3SSoby Mathew	ldr	w3, [x0, #UARTLCR]
569c94d3b3SSoby Mathew	orr	w3, w3, #UARTLCR_DLAB
579c94d3b3SSoby Mathew	str	w3, [x0, #UARTLCR]	/* enable DLL, DLLM programming */
589c94d3b3SSoby Mathew	str	w1, [x0, #UARTDLL]	/* program DLL */
599c94d3b3SSoby Mathew	str	w2, [x0, #UARTDLLM]	/* program DLLM */
609c94d3b3SSoby Mathew	mov	w2, #~UARTLCR_DLAB
619c94d3b3SSoby Mathew	and	w3, w3, w2
629c94d3b3SSoby Mathew	str	w3, [x0, #UARTLCR]	/* disable DLL, DLLM programming */
639c94d3b3SSoby Mathew
649c94d3b3SSoby Mathew	/* 8n1 */
659c94d3b3SSoby Mathew	mov	w3, #3
669c94d3b3SSoby Mathew	str	w3, [x0, #UARTLCR]
679c94d3b3SSoby Mathew	/* no interrupt */
689c94d3b3SSoby Mathew	mov	w3, #0
699c94d3b3SSoby Mathew	str	w3, [x0, #UARTIER]
70529b541eSBenjamin Fair#ifdef TI_16550_MDR_QUIRK
71529b541eSBenjamin Fair	/* UART must be enabled on some platforms via the MDR register */
72529b541eSBenjamin Fair	str	w3, [x0, #UARTMDR1]
73529b541eSBenjamin Fair#endif /* TI_16550_MDR_QUIRK */
749c94d3b3SSoby Mathew	/* enable fifo, DMA */
759c94d3b3SSoby Mathew	mov	w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
769c94d3b3SSoby Mathew	str	w3, [x0, #UARTFCR]
779c94d3b3SSoby Mathew	/* DTR + RTS */
789c94d3b3SSoby Mathew	mov	w3, #3
799c94d3b3SSoby Mathew	str	w3, [x0, #UARTMCR]
809c94d3b3SSoby Mathew	mov	w0, #1
819c94d3b3SSoby Mathew	ret
8236c42ca1SJulius Wernerinit_fail:
8336c42ca1SJulius Werner	mov	w0, #0
8436c42ca1SJulius Werner	ret
8536c42ca1SJulius Wernerendfunc console_16550_core_init
8636c42ca1SJulius Werner
8736c42ca1SJulius Werner#if MULTI_CONSOLE_API
8836c42ca1SJulius Werner	.globl console_16550_register
8936c42ca1SJulius Werner
9036c42ca1SJulius Werner	/* -----------------------------------------------
9165199dc8SAntonio Nino Diaz	 * int console_16550_register(uintptr_t baseaddr,
9265199dc8SAntonio Nino Diaz	 *     uint32_t clock, uint32_t baud,
9365199dc8SAntonio Nino Diaz	 *     console_16550_t *console);
9436c42ca1SJulius Werner	 * Function to initialize and register a new 16550
9536c42ca1SJulius Werner	 * console. Storage passed in for the console struct
9636c42ca1SJulius Werner	 * *must* be persistent (i.e. not from the stack).
9736c42ca1SJulius Werner	 * In: x0 - UART register base address
9836c42ca1SJulius Werner	 *     w1 - UART clock in Hz
9936c42ca1SJulius Werner	 *     w2 - Baud rate
10036c42ca1SJulius Werner	 *     x3 - pointer to empty console_16550_t struct
10136c42ca1SJulius Werner	 * Out: return 1 on success, 0 on error
10236c42ca1SJulius Werner	 * Clobber list : x0, x1, x2, x6, x7, x14
10336c42ca1SJulius Werner	 * -----------------------------------------------
10436c42ca1SJulius Werner	 */
10536c42ca1SJulius Wernerfunc console_16550_register
10636c42ca1SJulius Werner	mov	x7, x30
10736c42ca1SJulius Werner	mov	x6, x3
10836c42ca1SJulius Werner	cbz	x6, register_fail
10936c42ca1SJulius Werner	str	x0, [x6, #CONSOLE_T_16550_BASE]
11036c42ca1SJulius Werner
11136c42ca1SJulius Werner	bl	console_16550_core_init
11236c42ca1SJulius Werner	cbz	x0, register_fail
11336c42ca1SJulius Werner
11436c42ca1SJulius Werner	mov	x0, x6
11536c42ca1SJulius Werner	mov	x30, x7
116cc5859caSSoby Mathew	finish_console_register 16550 putc=1, getc=1, flush=1
11736c42ca1SJulius Werner
11836c42ca1SJulius Wernerregister_fail:
11936c42ca1SJulius Werner	ret	x7
12036c42ca1SJulius Wernerendfunc console_16550_register
12136c42ca1SJulius Werner#else
12236c42ca1SJulius Werner	.globl console_core_init
12336c42ca1SJulius Werner	.globl console_core_putc
12436c42ca1SJulius Werner	.globl console_core_getc
12536c42ca1SJulius Werner	.globl console_core_flush
12636c42ca1SJulius Werner	.equ console_core_init,console_16550_core_init
12736c42ca1SJulius Werner	.equ console_core_putc,console_16550_core_putc
12836c42ca1SJulius Werner	.equ console_core_getc,console_16550_core_getc
1294f8053ddSAntonio Nino Diaz	.equ console_core_flush,console_16550_core_flush
13036c42ca1SJulius Werner#endif
1319c94d3b3SSoby Mathew
1329c94d3b3SSoby Mathew	/* --------------------------------------------------------
13336c42ca1SJulius Werner	 * int console_16550_core_putc(int c, uintptr_t base_addr)
1349c94d3b3SSoby Mathew	 * Function to output a character over the console. It
1359c94d3b3SSoby Mathew	 * returns the character printed on success or -1 on error.
1369c94d3b3SSoby Mathew	 * In : w0 - character to be printed
1379c94d3b3SSoby Mathew	 *      x1 - console base address
1389c94d3b3SSoby Mathew	 * Out : return -1 on error else return character.
1399c94d3b3SSoby Mathew	 * Clobber list : x2
1409c94d3b3SSoby Mathew	 * --------------------------------------------------------
1419c94d3b3SSoby Mathew	 */
14236c42ca1SJulius Wernerfunc console_16550_core_putc
14336c42ca1SJulius Werner#if ENABLE_ASSERTIONS
14436c42ca1SJulius Werner	cmp	x1, #0
14536c42ca1SJulius Werner	ASM_ASSERT(ne)
14636c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
1479c94d3b3SSoby Mathew
1489c94d3b3SSoby Mathew	/* Prepend '\r' to '\n' */
1499c94d3b3SSoby Mathew	cmp	w0, #0xA
1509c94d3b3SSoby Mathew	b.ne	2f
1519c94d3b3SSoby Mathew	/* Check if the transmit FIFO is full */
1529c94d3b3SSoby Mathew1:	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	1b
1569c94d3b3SSoby Mathew	mov	w2, #0xD		/* '\r' */
1579c94d3b3SSoby Mathew	str	w2, [x1, #UARTTX]
1589c94d3b3SSoby Mathew
1599c94d3b3SSoby Mathew	/* Check if the transmit FIFO is full */
1609c94d3b3SSoby Mathew2:	ldr	w2, [x1, #UARTLSR]
1619c94d3b3SSoby Mathew	and	w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
1629c94d3b3SSoby Mathew	cmp	w2, #(UARTLSR_TEMT | UARTLSR_THRE)
1639c94d3b3SSoby Mathew	b.ne	2b
1649c94d3b3SSoby Mathew	str	w0, [x1, #UARTTX]
1659c94d3b3SSoby Mathew	ret
16636c42ca1SJulius Wernerendfunc console_16550_core_putc
16736c42ca1SJulius Werner
16836c42ca1SJulius Werner	/* --------------------------------------------------------
16936c42ca1SJulius Werner	 * int console_16550_putc(int c, console_16550_t *console)
17036c42ca1SJulius Werner	 * Function to output a character over the console. It
17136c42ca1SJulius Werner	 * returns the character printed on success or -1 on error.
17236c42ca1SJulius Werner	 * In : w0 - character to be printed
17336c42ca1SJulius Werner	 *      x1 - pointer to console_t structure
17436c42ca1SJulius Werner	 * Out : return -1 on error else return character.
17536c42ca1SJulius Werner	 * Clobber list : x2
17636c42ca1SJulius Werner	 * --------------------------------------------------------
17736c42ca1SJulius Werner	 */
17836c42ca1SJulius Wernerfunc console_16550_putc
17936c42ca1SJulius Werner#if ENABLE_ASSERTIONS
18036c42ca1SJulius Werner	cmp	x1, #0
18136c42ca1SJulius Werner	ASM_ASSERT(ne)
18236c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
18336c42ca1SJulius Werner	ldr	x1, [x1, #CONSOLE_T_16550_BASE]
18436c42ca1SJulius Werner	b	console_16550_core_putc
18536c42ca1SJulius Wernerendfunc console_16550_putc
1869c94d3b3SSoby Mathew
1879c94d3b3SSoby Mathew	/* ---------------------------------------------
18836c42ca1SJulius Werner	 * int console_16550_core_getc(uintptr_t base_addr)
1899c94d3b3SSoby Mathew	 * Function to get a character from the console.
1909c94d3b3SSoby Mathew	 * It returns the character grabbed on success
19136c42ca1SJulius Werner	 * or -1 on if no character is available.
19236c42ca1SJulius Werner	 * In :  x0 - console base address
19336c42ca1SJulius Werner	 * Out : w0 - character if available, else -1
1949c94d3b3SSoby Mathew	 * Clobber list : x0, x1
1959c94d3b3SSoby Mathew	 * ---------------------------------------------
1969c94d3b3SSoby Mathew	 */
19736c42ca1SJulius Wernerfunc console_16550_core_getc
19836c42ca1SJulius Werner#if ENABLE_ASSERTIONS
19936c42ca1SJulius Werner	cmp	x0, #0
20036c42ca1SJulius Werner	ASM_ASSERT(ne)
20136c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
20236c42ca1SJulius Werner
2039c94d3b3SSoby Mathew	/* Check if the receive FIFO is empty */
2049c94d3b3SSoby Mathew1:	ldr	w1, [x0, #UARTLSR]
20536c42ca1SJulius Werner	tbz	w1, #UARTLSR_RDR_BIT, no_char
2069c94d3b3SSoby Mathew	ldr	w0, [x0, #UARTRX]
2079c94d3b3SSoby Mathew	ret
20836c42ca1SJulius Wernerno_char:
20936c42ca1SJulius Werner	mov	w0, #ERROR_NO_PENDING_CHAR
2109c94d3b3SSoby Mathew	ret
21136c42ca1SJulius Wernerendfunc console_16550_core_getc
21236c42ca1SJulius Werner
21336c42ca1SJulius Werner	/* ---------------------------------------------
21436c42ca1SJulius Werner	 * int console_16550_getc(console_16550_t *console)
21536c42ca1SJulius Werner	 * Function to get a character from the console.
21636c42ca1SJulius Werner	 * It returns the character grabbed on success
21736c42ca1SJulius Werner	 * or -1 on if no character is available.
21836c42ca1SJulius Werner	 * In :  x0 - pointer to console_t stucture
21936c42ca1SJulius Werner	 * Out : w0 - character if available, else -1
22036c42ca1SJulius Werner	 * Clobber list : x0, x1
22136c42ca1SJulius Werner	 * ---------------------------------------------
22236c42ca1SJulius Werner	 */
22336c42ca1SJulius Wernerfunc console_16550_getc
22436c42ca1SJulius Werner#if ENABLE_ASSERTIONS
22536c42ca1SJulius Werner	cmp	x1, #0
22636c42ca1SJulius Werner	ASM_ASSERT(ne)
22736c42ca1SJulius Werner#endif /* ENABLE_ASSERTIONS */
22836c42ca1SJulius Werner	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
22936c42ca1SJulius Werner	b	console_16550_core_getc
23036c42ca1SJulius Wernerendfunc console_16550_getc
231ad4c2ec6SAntonio Nino Diaz
232ad4c2ec6SAntonio Nino Diaz	/* ---------------------------------------------
2334f8053ddSAntonio Nino Diaz	 * int console_16550_core_flush(uintptr_t base_addr)
234ad4c2ec6SAntonio Nino Diaz	 * Function to force a write of all buffered
235ad4c2ec6SAntonio Nino Diaz	 * data that hasn't been output.
236ad4c2ec6SAntonio Nino Diaz	 * In : x0 - console base address
237ad4c2ec6SAntonio Nino Diaz	 * Out : return -1 on error else return 0.
238ad4c2ec6SAntonio Nino Diaz	 * Clobber list : x0, x1
239ad4c2ec6SAntonio Nino Diaz	 * ---------------------------------------------
240ad4c2ec6SAntonio Nino Diaz	 */
2414f8053ddSAntonio Nino Diazfunc console_16550_core_flush
2424f8053ddSAntonio Nino Diaz#if ENABLE_ASSERTIONS
2434f8053ddSAntonio Nino Diaz	cmp	x0, #0
2444f8053ddSAntonio Nino Diaz	ASM_ASSERT(ne)
2454f8053ddSAntonio Nino Diaz#endif /* ENABLE_ASSERTIONS */
2464f8053ddSAntonio Nino Diaz
2474f8053ddSAntonio Nino Diaz	/* Loop until the transmit FIFO is empty */
2484f8053ddSAntonio Nino Diaz1:	ldr	w1, [x0, #UARTLSR]
2494f8053ddSAntonio Nino Diaz	and	w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE)
2504f8053ddSAntonio Nino Diaz	cmp	w1, #(UARTLSR_TEMT | UARTLSR_THRE)
2514f8053ddSAntonio Nino Diaz	b.ne	1b
2524f8053ddSAntonio Nino Diaz
253ad4c2ec6SAntonio Nino Diaz	mov	w0, #0
254ad4c2ec6SAntonio Nino Diaz	ret
2554f8053ddSAntonio Nino Diazendfunc console_16550_core_flush
2564f8053ddSAntonio Nino Diaz
2574f8053ddSAntonio Nino Diaz	/* ---------------------------------------------
2584f8053ddSAntonio Nino Diaz	 * int console_16550_flush(console_pl011_t *console)
2594f8053ddSAntonio Nino Diaz	 * Function to force a write of all buffered
2604f8053ddSAntonio Nino Diaz	 * data that hasn't been output.
2614f8053ddSAntonio Nino Diaz	 * In : x0 - pointer to console_t structure
2624f8053ddSAntonio Nino Diaz	 * Out : return -1 on error else return 0.
2634f8053ddSAntonio Nino Diaz	 * Clobber list : x0, x1
2644f8053ddSAntonio Nino Diaz	 * ---------------------------------------------
2654f8053ddSAntonio Nino Diaz	 */
2664f8053ddSAntonio Nino Diazfunc console_16550_flush
2674f8053ddSAntonio Nino Diaz#if ENABLE_ASSERTIONS
2684f8053ddSAntonio Nino Diaz	cmp	x0, #0
2694f8053ddSAntonio Nino Diaz	ASM_ASSERT(ne)
2704f8053ddSAntonio Nino Diaz#endif /* ENABLE_ASSERTIONS */
2714f8053ddSAntonio Nino Diaz	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
2724f8053ddSAntonio Nino Diaz	b	console_16550_core_flush
2734f8053ddSAntonio Nino Diazendfunc console_16550_flush
274