xref: /rk3399_ARM-atf/drivers/arm/pl011/aarch32/pl011_console.S (revision a5aa25af6514ff04721efce05e46b4daf8729a85)
166be868eSSoby Mathew/*
27e2bbef9SDaniel Boulby * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
366be868eSSoby Mathew *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
566be868eSSoby Mathew */
666be868eSSoby Mathew#include <arch.h>
766be868eSSoby Mathew#include <asm_macros.S>
87e2bbef9SDaniel Boulby#include <assert_macros.S>
9cc5859caSSoby Mathew#define USE_FINISH_CONSOLE_REG_2
107e2bbef9SDaniel Boulby#include <console_macros.S>
1109d40e0eSAntonio Nino Diaz#include <drivers/arm/pl011.h>
1266be868eSSoby Mathew
13985ee0b7SJulius Werner#if !MULTI_CONSOLE_API
1466be868eSSoby Mathew/*
1566be868eSSoby Mathew * Pull in generic functions to provide backwards compatibility for
1666be868eSSoby Mathew * platform makefiles
1766be868eSSoby Mathew */
1866be868eSSoby Mathew#include "../../../console/aarch32/console.S"
19985ee0b7SJulius Werner#endif
2066be868eSSoby Mathew
217e2bbef9SDaniel Boulby	/*
227e2bbef9SDaniel Boulby	 * "core" functions are low-level implementations that don't require
237e2bbef9SDaniel Boulby	 * writeable memory and are thus safe to call in BL1 crash context.
247e2bbef9SDaniel Boulby	 */
257e2bbef9SDaniel Boulby	.globl	console_pl011_core_init
267e2bbef9SDaniel Boulby	.globl	console_pl011_core_putc
277e2bbef9SDaniel Boulby	.globl	console_pl011_core_getc
287e2bbef9SDaniel Boulby	.globl	console_pl011_core_flush
297e2bbef9SDaniel Boulby
307e2bbef9SDaniel Boulby	.globl	console_pl011_putc
317e2bbef9SDaniel Boulby	.globl	console_pl011_getc
327e2bbef9SDaniel Boulby	.globl	console_pl011_flush
3366be868eSSoby Mathew
3466be868eSSoby Mathew
3566be868eSSoby Mathew	/* -----------------------------------------------
3666be868eSSoby Mathew	 * int console_core_init(uintptr_t base_addr,
3766be868eSSoby Mathew	 * unsigned int uart_clk, unsigned int baud_rate)
3866be868eSSoby Mathew	 * Function to initialize the console without a
3966be868eSSoby Mathew	 * C Runtime to print debug information. This
4066be868eSSoby Mathew	 * function will be accessed by console_init and
4166be868eSSoby Mathew	 * crash reporting.
4266be868eSSoby Mathew	 * In: r0 - console base address
4366be868eSSoby Mathew	 *     r1 - Uart clock in Hz
4466be868eSSoby Mathew	 *     r2 - Baud rate
4566be868eSSoby Mathew	 * Out: return 1 on success else 0 on error
4666be868eSSoby Mathew	 * Clobber list : r1, r2, r3
4766be868eSSoby Mathew	 * -----------------------------------------------
4866be868eSSoby Mathew	 */
497e2bbef9SDaniel Boulbyfunc console_pl011_core_init
5066be868eSSoby Mathew	/* Check the input base address */
5166be868eSSoby Mathew	cmp	r0, #0
5266be868eSSoby Mathew	beq	core_init_fail
5366be868eSSoby Mathew#if !PL011_GENERIC_UART
5466be868eSSoby Mathew	/* Check baud rate and uart clock for sanity */
5566be868eSSoby Mathew	cmp	r1, #0
5666be868eSSoby Mathew	beq	core_init_fail
5766be868eSSoby Mathew	cmp	r2, #0
5866be868eSSoby Mathew	beq	core_init_fail
5966be868eSSoby Mathew	/* Disable the UART before initialization */
6066be868eSSoby Mathew	ldr	r3, [r0, #UARTCR]
6166be868eSSoby Mathew	bic	r3, r3, #PL011_UARTCR_UARTEN
6266be868eSSoby Mathew	str	r3, [r0, #UARTCR]
6366be868eSSoby Mathew	/* Program the baudrate */
6466be868eSSoby Mathew	/* Divisor =  (Uart clock * 4) / baudrate */
6566be868eSSoby Mathew	lsl	r1, r1, #2
66*a5aa25afSUsama Arif#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_VIRTUALIZATION)
67*a5aa25afSUsama Arif	push	{r0,r3}
68*a5aa25afSUsama Arif	softudiv	r0,r1,r2,r3
69*a5aa25afSUsama Arif	mov	r1, r0
70*a5aa25afSUsama Arif	pop	{r0,r3}
71*a5aa25afSUsama Arif#else
7266be868eSSoby Mathew	udiv	r2, r1, r2
73*a5aa25afSUsama Arif#endif
7466be868eSSoby Mathew	/* IBRD = Divisor >> 6 */
7566be868eSSoby Mathew	lsr	r1, r2, #6
7666be868eSSoby Mathew	/* Write the IBRD */
7766be868eSSoby Mathew	str	r1, [r0, #UARTIBRD]
7866be868eSSoby Mathew	/* FBRD = Divisor & 0x3F */
7966be868eSSoby Mathew	and	r1, r2, #0x3f
8066be868eSSoby Mathew	/* Write the FBRD */
8166be868eSSoby Mathew	str	r1, [r0, #UARTFBRD]
8266be868eSSoby Mathew	mov	r1, #PL011_LINE_CONTROL
8366be868eSSoby Mathew	str	r1, [r0, #UARTLCR_H]
8466be868eSSoby Mathew	/* Clear any pending errors */
8566be868eSSoby Mathew	mov	r1, #0
8666be868eSSoby Mathew	str	r1, [r0, #UARTECR]
8766be868eSSoby Mathew	/* Enable tx, rx, and uart overall */
8866be868eSSoby Mathew	ldr	r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
8966be868eSSoby Mathew	str	r1, [r0, #UARTCR]
9066be868eSSoby Mathew#endif
9166be868eSSoby Mathew	mov	r0, #1
9266be868eSSoby Mathew	bx	lr
9366be868eSSoby Mathewcore_init_fail:
9466be868eSSoby Mathew	mov	r0, #0
9566be868eSSoby Mathew	bx	lr
967e2bbef9SDaniel Boulbyendfunc console_pl011_core_init
977e2bbef9SDaniel Boulby
987e2bbef9SDaniel Boulby#if MULTI_CONSOLE_API
997e2bbef9SDaniel Boulby	.globl console_pl011_register
1007e2bbef9SDaniel Boulby
1017e2bbef9SDaniel Boulby	/* -------------------------------------------------------
10265199dc8SAntonio Nino Diaz	 * int console_pl011_register(uintptr_t baseaddr,
10365199dc8SAntonio Nino Diaz	 *     uint32_t clock, uint32_t baud,
10465199dc8SAntonio Nino Diaz	 *     console_pl011_t *console);
1057e2bbef9SDaniel Boulby	 * Function to initialize and register a new PL011
1067e2bbef9SDaniel Boulby	 * console. Storage passed in for the console struct
1077e2bbef9SDaniel Boulby	 * *must* be persistent (i.e. not from the stack).
1087e2bbef9SDaniel Boulby	 * In: r0 - UART register base address
1097e2bbef9SDaniel Boulby	 *     r1 - UART clock in Hz
1107e2bbef9SDaniel Boulby	 *     r2 - Baud rate
1117e2bbef9SDaniel Boulby	 *     r3 - pointer to empty console_pl011_t struct
1127e2bbef9SDaniel Boulby	 * Out: return 1 on success, 0 on error
1137e2bbef9SDaniel Boulby	 * Clobber list : r0, r1, r2
1147e2bbef9SDaniel Boulby	 * -------------------------------------------------------
1157e2bbef9SDaniel Boulby	 */
1167e2bbef9SDaniel Boulbyfunc console_pl011_register
1177e2bbef9SDaniel Boulby	push	{r4, lr}
1187e2bbef9SDaniel Boulby	mov	r4, r3
1197e2bbef9SDaniel Boulby	cmp	r4, #0
1207e2bbef9SDaniel Boulby	beq	register_fail
1217e2bbef9SDaniel Boulby	str	r0, [r4, #CONSOLE_T_PL011_BASE]
1227e2bbef9SDaniel Boulby
1237e2bbef9SDaniel Boulby	bl console_pl011_core_init
1247e2bbef9SDaniel Boulby	cmp	r0, #0
1257e2bbef9SDaniel Boulby	beq	register_fail
1267e2bbef9SDaniel Boulby
1277e2bbef9SDaniel Boulby	mov	r0, r4
1287e2bbef9SDaniel Boulby	pop	{r4, lr}
129cc5859caSSoby Mathew	finish_console_register pl011 putc=1, getc=1, flush=1
1307e2bbef9SDaniel Boulby
1317e2bbef9SDaniel Boulbyregister_fail:
1327e2bbef9SDaniel Boulby	pop	{r4, pc}
1337e2bbef9SDaniel Boulbyendfunc console_pl011_register
1347e2bbef9SDaniel Boulby#else
1357e2bbef9SDaniel Boulby	.globl console_core_init
1367e2bbef9SDaniel Boulby	.globl console_core_putc
1377e2bbef9SDaniel Boulby	.globl console_core_getc
1387e2bbef9SDaniel Boulby	.globl console_core_flush
1397e2bbef9SDaniel Boulby	.equ console_core_init, console_pl011_core_init
1407e2bbef9SDaniel Boulby	.equ console_core_putc, console_pl011_core_putc
1417e2bbef9SDaniel Boulby	.equ console_core_getc, console_pl011_core_getc
1427e2bbef9SDaniel Boulby	.equ console_core_flush, console_pl011_core_flush
1437e2bbef9SDaniel Boulby#endif
14466be868eSSoby Mathew
14566be868eSSoby Mathew	/* --------------------------------------------------------
14666be868eSSoby Mathew	 * int console_core_putc(int c, uintptr_t base_addr)
14766be868eSSoby Mathew	 * Function to output a character over the console. It
14866be868eSSoby Mathew	 * returns the character printed on success or -1 on error.
14966be868eSSoby Mathew	 * In : r0 - character to be printed
15066be868eSSoby Mathew	 *      r1 - console base address
15166be868eSSoby Mathew	 * Out : return -1 on error else return character.
15266be868eSSoby Mathew	 * Clobber list : r2
15366be868eSSoby Mathew	 * --------------------------------------------------------
15466be868eSSoby Mathew	 */
1557e2bbef9SDaniel Boulbyfunc console_pl011_core_putc
15666be868eSSoby Mathew	/* Check the input parameter */
15766be868eSSoby Mathew	cmp	r1, #0
15866be868eSSoby Mathew	beq	putc_error
15966be868eSSoby Mathew	/* Prepend '\r' to '\n' */
16066be868eSSoby Mathew	cmp	r0, #0xA
16166be868eSSoby Mathew	bne	2f
16266be868eSSoby Mathew1:
16366be868eSSoby Mathew	/* Check if the transmit FIFO is full */
16466be868eSSoby Mathew	ldr	r2, [r1, #UARTFR]
16569d59e0cSYatharth Kochar	tst	r2, #PL011_UARTFR_TXFF
16669d59e0cSYatharth Kochar	bne	1b
16766be868eSSoby Mathew	mov	r2, #0xD
16866be868eSSoby Mathew	str	r2, [r1, #UARTDR]
16966be868eSSoby Mathew2:
17066be868eSSoby Mathew	/* Check if the transmit FIFO is full */
17166be868eSSoby Mathew	ldr	r2, [r1, #UARTFR]
17269d59e0cSYatharth Kochar	tst	r2, #PL011_UARTFR_TXFF
17369d59e0cSYatharth Kochar	bne	2b
17466be868eSSoby Mathew	str	r0, [r1, #UARTDR]
17566be868eSSoby Mathew	bx	lr
17666be868eSSoby Mathewputc_error:
17766be868eSSoby Mathew	mov	r0, #-1
17866be868eSSoby Mathew	bx	lr
1797e2bbef9SDaniel Boulbyendfunc console_pl011_core_putc
1807e2bbef9SDaniel Boulby
1817e2bbef9SDaniel Boulby	/* --------------------------------------------------------
1827e2bbef9SDaniel Boulby	 * int console_pl011_putc(int c, console_pl011_t *console)
1837e2bbef9SDaniel Boulby	 * Function to output a character over the console. It
1847e2bbef9SDaniel Boulby	 * returns the character printed on success or -1 on error.
1857e2bbef9SDaniel Boulby	 * In: r0 - character to be printed
1867e2bbef9SDaniel Boulby	 *     r1 - pointer to console_t structure
1877e2bbef9SDaniel Boulby	 * Out : return -1 on error else return character.
1887e2bbef9SDaniel Boulby	 * Clobber list: r2
1897e2bbef9SDaniel Boulby	 * -------------------------------------------------------
1907e2bbef9SDaniel Boulby	 */
1917e2bbef9SDaniel Boulbyfunc console_pl011_putc
1927e2bbef9SDaniel Boulby#if ENABLE_ASSERTIONS
1937e2bbef9SDaniel Boulby	cmp	r1, #0
1947e2bbef9SDaniel Boulby	ASM_ASSERT(ne)
1957e2bbef9SDaniel Boulby#endif /* ENABLE_ASSERTIONS */
1967e2bbef9SDaniel Boulby	ldr	r1, [r1, #CONSOLE_T_PL011_BASE]
1977e2bbef9SDaniel Boulby	b	console_pl011_core_putc
1987e2bbef9SDaniel Boulbyendfunc console_pl011_putc
19966be868eSSoby Mathew
20066be868eSSoby Mathew	/* ---------------------------------------------
20166be868eSSoby Mathew	 * int console_core_getc(uintptr_t base_addr)
20266be868eSSoby Mathew	 * Function to get a character from the console.
20366be868eSSoby Mathew	 * It returns the character grabbed on success
20466be868eSSoby Mathew	 * or -1 on error.
20566be868eSSoby Mathew	 * In : r0 - console base address
20666be868eSSoby Mathew	 * Clobber list : r0, r1
20766be868eSSoby Mathew	 * ---------------------------------------------
20866be868eSSoby Mathew	 */
2097e2bbef9SDaniel Boulbyfunc console_pl011_core_getc
21066be868eSSoby Mathew	cmp	r0, #0
21166be868eSSoby Mathew	beq	getc_error
21266be868eSSoby Mathew1:
21366be868eSSoby Mathew	/* Check if the receive FIFO is empty */
21466be868eSSoby Mathew	ldr	r1, [r0, #UARTFR]
21569d59e0cSYatharth Kochar	tst	r1, #PL011_UARTFR_RXFE
21669d59e0cSYatharth Kochar	bne	1b
21766be868eSSoby Mathew	ldr	r1, [r0, #UARTDR]
21866be868eSSoby Mathew	mov	r0, r1
21966be868eSSoby Mathew	bx	lr
22066be868eSSoby Mathewgetc_error:
22166be868eSSoby Mathew	mov	r0, #-1
22266be868eSSoby Mathew	bx	lr
2237e2bbef9SDaniel Boulbyendfunc console_pl011_core_getc
2247e2bbef9SDaniel Boulby
2257e2bbef9SDaniel Boulby	/* ------------------------------------------------
2267e2bbef9SDaniel Boulby	 * int console_pl011_getc(console_pl011_t *console)
2277e2bbef9SDaniel Boulby	 * Function to get a character from the console.
2287e2bbef9SDaniel Boulby	 * It returns the character grabbed on success
2297e2bbef9SDaniel Boulby	 * or -1 if no character is available.
2307e2bbef9SDaniel Boulby	 * In : r0 - pointer to console_t structure
2317e2bbef9SDaniel Boulby	 * Out: r0 - character if available, else -1
2327e2bbef9SDaniel Boulby	 * Clobber list: r0, r1
2337e2bbef9SDaniel Boulby	 * ------------------------------------------------
2347e2bbef9SDaniel Boulby	 */
2357e2bbef9SDaniel Boulbyfunc console_pl011_getc
2367e2bbef9SDaniel Boulby#if ENABLE_ASSERTIONS
2377e2bbef9SDaniel Boulby	cmp	r0, #0
2387e2bbef9SDaniel Boulby	ASM_ASSERT(ne)
2397e2bbef9SDaniel Boulby#endif /* ENABLE_ASSERTIONS */
2407e2bbef9SDaniel Boulby	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
2417e2bbef9SDaniel Boulby	b	console_pl011_core_getc
2427e2bbef9SDaniel Boulbyendfunc console_pl011_getc
24373e05284SAntonio Nino Diaz
24473e05284SAntonio Nino Diaz	/* ---------------------------------------------
24573e05284SAntonio Nino Diaz	 * int console_core_flush(uintptr_t base_addr)
24673e05284SAntonio Nino Diaz	 * Function to force a write of all buffered
24773e05284SAntonio Nino Diaz	 * data that hasn't been output.
24873e05284SAntonio Nino Diaz	 * In : r0 - console base address
24973e05284SAntonio Nino Diaz	 * Out : return -1 on error else return 0.
25073e05284SAntonio Nino Diaz	 * Clobber list : r0, r1
25173e05284SAntonio Nino Diaz	 * ---------------------------------------------
25273e05284SAntonio Nino Diaz	 */
2537e2bbef9SDaniel Boulbyfunc console_pl011_core_flush
25473e05284SAntonio Nino Diaz	cmp	r0, #0
25573e05284SAntonio Nino Diaz	beq	flush_error
25673e05284SAntonio Nino Diaz
25773e05284SAntonio Nino Diaz1:
25873e05284SAntonio Nino Diaz	/* Loop while the transmit FIFO is busy */
25973e05284SAntonio Nino Diaz	ldr	r1, [r0, #UARTFR]
26073e05284SAntonio Nino Diaz	tst	r1, #PL011_UARTFR_BUSY
26173e05284SAntonio Nino Diaz	bne	1b
26273e05284SAntonio Nino Diaz
26373e05284SAntonio Nino Diaz	mov	r0, #0
26473e05284SAntonio Nino Diaz	bx	lr
26573e05284SAntonio Nino Diazflush_error:
26673e05284SAntonio Nino Diaz	mov	r0, #-1
26773e05284SAntonio Nino Diaz	bx	lr
2687e2bbef9SDaniel Boulbyendfunc console_pl011_core_flush
2697e2bbef9SDaniel Boulby
2707e2bbef9SDaniel Boulby	/* ---------------------------------------------
2717e2bbef9SDaniel Boulby	 * int console_pl011_flush(console_pl011_t *console)
2727e2bbef9SDaniel Boulby	 * Function to force a write of all buffered
2737e2bbef9SDaniel Boulby	 * data that hasn't been output.
2747e2bbef9SDaniel Boulby	 * In : r0 - pointer to console_t structure
2757e2bbef9SDaniel Boulby	 * Out : return -1 on error else return 0.
2767e2bbef9SDaniel Boulby	 * Clobber list: r0, r1
2777e2bbef9SDaniel Boulby	 * ---------------------------------------------
2787e2bbef9SDaniel Boulby	 */
2797e2bbef9SDaniel Boulbyfunc console_pl011_flush
2807e2bbef9SDaniel Boulby#if ENABLE_ASSERTIONS
2817e2bbef9SDaniel Boulby	cmp	r0, #0
2827e2bbef9SDaniel Boulby	ASM_ASSERT(ne)
2837e2bbef9SDaniel Boulby#endif /* ENABLE_ASSERTIONS */
2847e2bbef9SDaniel Boulby	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
2857e2bbef9SDaniel Boulby	b	console_pl011_core_flush
2867e2bbef9SDaniel Boulbyendfunc console_pl011_flush
287