xref: /rk3399_ARM-atf/drivers/arm/pl011/aarch32/pl011_console.S (revision 7e2bbef9f979233bb6fc3d3cdce244dec2d9e18d)
166be868eSSoby Mathew/*
2*7e2bbef9SDaniel 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>
8*7e2bbef9SDaniel Boulby#include <assert_macros.S>
9*7e2bbef9SDaniel Boulby#include <console_macros.S>
1066be868eSSoby Mathew#include <pl011.h>
1166be868eSSoby Mathew
1266be868eSSoby Mathew/*
1366be868eSSoby Mathew * Pull in generic functions to provide backwards compatibility for
1466be868eSSoby Mathew * platform makefiles
1566be868eSSoby Mathew */
1666be868eSSoby Mathew#include "../../../console/aarch32/console.S"
1766be868eSSoby Mathew
18*7e2bbef9SDaniel Boulby	/*
19*7e2bbef9SDaniel Boulby	 * "core" functions are low-level implementations that don't require
20*7e2bbef9SDaniel Boulby	 * writeable memory and are thus safe to call in BL1 crash context.
21*7e2bbef9SDaniel Boulby	 */
22*7e2bbef9SDaniel Boulby	.globl	console_pl011_core_init
23*7e2bbef9SDaniel Boulby	.globl	console_pl011_core_putc
24*7e2bbef9SDaniel Boulby	.globl	console_pl011_core_getc
25*7e2bbef9SDaniel Boulby	.globl	console_pl011_core_flush
26*7e2bbef9SDaniel Boulby
27*7e2bbef9SDaniel Boulby	.globl	console_pl011_putc
28*7e2bbef9SDaniel Boulby	.globl	console_pl011_getc
29*7e2bbef9SDaniel Boulby	.globl	console_pl011_flush
3066be868eSSoby Mathew
3166be868eSSoby Mathew
3266be868eSSoby Mathew	/* -----------------------------------------------
3366be868eSSoby Mathew	 * int console_core_init(uintptr_t base_addr,
3466be868eSSoby Mathew	 * unsigned int uart_clk, unsigned int baud_rate)
3566be868eSSoby Mathew	 * Function to initialize the console without a
3666be868eSSoby Mathew	 * C Runtime to print debug information. This
3766be868eSSoby Mathew	 * function will be accessed by console_init and
3866be868eSSoby Mathew	 * crash reporting.
3966be868eSSoby Mathew	 * In: r0 - console base address
4066be868eSSoby Mathew	 *     r1 - Uart clock in Hz
4166be868eSSoby Mathew	 *     r2 - Baud rate
4266be868eSSoby Mathew	 * Out: return 1 on success else 0 on error
4366be868eSSoby Mathew	 * Clobber list : r1, r2, r3
4466be868eSSoby Mathew	 * -----------------------------------------------
4566be868eSSoby Mathew	 */
46*7e2bbef9SDaniel Boulbyfunc console_pl011_core_init
4766be868eSSoby Mathew	/* Check the input base address */
4866be868eSSoby Mathew	cmp	r0, #0
4966be868eSSoby Mathew	beq	core_init_fail
5066be868eSSoby Mathew#if !PL011_GENERIC_UART
5166be868eSSoby Mathew	/* Check baud rate and uart clock for sanity */
5266be868eSSoby Mathew	cmp	r1, #0
5366be868eSSoby Mathew	beq	core_init_fail
5466be868eSSoby Mathew	cmp	r2, #0
5566be868eSSoby Mathew	beq	core_init_fail
5666be868eSSoby Mathew	/* Disable the UART before initialization */
5766be868eSSoby Mathew	ldr	r3, [r0, #UARTCR]
5866be868eSSoby Mathew	bic	r3, r3, #PL011_UARTCR_UARTEN
5966be868eSSoby Mathew	str	r3, [r0, #UARTCR]
6066be868eSSoby Mathew	/* Program the baudrate */
6166be868eSSoby Mathew	/* Divisor =  (Uart clock * 4) / baudrate */
6266be868eSSoby Mathew	lsl	r1, r1, #2
6366be868eSSoby Mathew	udiv	r2, r1, r2
6466be868eSSoby Mathew	/* IBRD = Divisor >> 6 */
6566be868eSSoby Mathew	lsr	r1, r2, #6
6666be868eSSoby Mathew	/* Write the IBRD */
6766be868eSSoby Mathew	str	r1, [r0, #UARTIBRD]
6866be868eSSoby Mathew	/* FBRD = Divisor & 0x3F */
6966be868eSSoby Mathew	and	r1, r2, #0x3f
7066be868eSSoby Mathew	/* Write the FBRD */
7166be868eSSoby Mathew	str	r1, [r0, #UARTFBRD]
7266be868eSSoby Mathew	mov	r1, #PL011_LINE_CONTROL
7366be868eSSoby Mathew	str	r1, [r0, #UARTLCR_H]
7466be868eSSoby Mathew	/* Clear any pending errors */
7566be868eSSoby Mathew	mov	r1, #0
7666be868eSSoby Mathew	str	r1, [r0, #UARTECR]
7766be868eSSoby Mathew	/* Enable tx, rx, and uart overall */
7866be868eSSoby Mathew	ldr	r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
7966be868eSSoby Mathew	str	r1, [r0, #UARTCR]
8066be868eSSoby Mathew#endif
8166be868eSSoby Mathew	mov	r0, #1
8266be868eSSoby Mathew	bx	lr
8366be868eSSoby Mathewcore_init_fail:
8466be868eSSoby Mathew	mov	r0, #0
8566be868eSSoby Mathew	bx	lr
86*7e2bbef9SDaniel Boulbyendfunc console_pl011_core_init
87*7e2bbef9SDaniel Boulby
88*7e2bbef9SDaniel Boulby#if MULTI_CONSOLE_API
89*7e2bbef9SDaniel Boulby	.globl console_pl011_register
90*7e2bbef9SDaniel Boulby
91*7e2bbef9SDaniel Boulby	/* -------------------------------------------------------
92*7e2bbef9SDaniel Boulby	 * init console_pl011_register(console_pl011_t *console,
93*7e2bbef9SDaniel Boulby	 *	uintptr_t base, uint32_t clk, uint32_t baud)
94*7e2bbef9SDaniel Boulby	 * Function to initialize and register a new PL011
95*7e2bbef9SDaniel Boulby	 * console. Storage passed in for the console struct
96*7e2bbef9SDaniel Boulby	 * *must* be persistent (i.e. not from the stack).
97*7e2bbef9SDaniel Boulby	 * In: r0 - UART register base address
98*7e2bbef9SDaniel Boulby	 *     r1 - UART clock in Hz
99*7e2bbef9SDaniel Boulby	 *     r2 - Baud rate
100*7e2bbef9SDaniel Boulby	 *     r3 - pointer to empty console_pl011_t struct
101*7e2bbef9SDaniel Boulby	 * Out: return 1 on success, 0 on error
102*7e2bbef9SDaniel Boulby	 * Clobber list : r0, r1, r2
103*7e2bbef9SDaniel Boulby	 * -------------------------------------------------------
104*7e2bbef9SDaniel Boulby	 */
105*7e2bbef9SDaniel Boulbyfunc console_pl011_register
106*7e2bbef9SDaniel Boulby	push	{r4, lr}
107*7e2bbef9SDaniel Boulby	mov	r4, r3
108*7e2bbef9SDaniel Boulby	cmp	r4, #0
109*7e2bbef9SDaniel Boulby	beq	register_fail
110*7e2bbef9SDaniel Boulby	str	r0, [r4, #CONSOLE_T_PL011_BASE]
111*7e2bbef9SDaniel Boulby
112*7e2bbef9SDaniel Boulby	bl console_pl011_core_init
113*7e2bbef9SDaniel Boulby	cmp	r0, #0
114*7e2bbef9SDaniel Boulby	beq	register_fail
115*7e2bbef9SDaniel Boulby
116*7e2bbef9SDaniel Boulby	mov	r0, r4
117*7e2bbef9SDaniel Boulby	pop	{r4, lr}
118*7e2bbef9SDaniel Boulby	finish_console_register pl011
119*7e2bbef9SDaniel Boulby
120*7e2bbef9SDaniel Boulbyregister_fail:
121*7e2bbef9SDaniel Boulby	pop	{r4, pc}
122*7e2bbef9SDaniel Boulbyendfunc console_pl011_register
123*7e2bbef9SDaniel Boulby#else
124*7e2bbef9SDaniel Boulby	.globl console_core_init
125*7e2bbef9SDaniel Boulby	.globl console_core_putc
126*7e2bbef9SDaniel Boulby	.globl console_core_getc
127*7e2bbef9SDaniel Boulby	.globl console_core_flush
128*7e2bbef9SDaniel Boulby	.equ console_core_init, console_pl011_core_init
129*7e2bbef9SDaniel Boulby	.equ console_core_putc, console_pl011_core_putc
130*7e2bbef9SDaniel Boulby	.equ console_core_getc, console_pl011_core_getc
131*7e2bbef9SDaniel Boulby	.equ console_core_flush, console_pl011_core_flush
132*7e2bbef9SDaniel Boulby#endif
13366be868eSSoby Mathew
13466be868eSSoby Mathew	/* --------------------------------------------------------
13566be868eSSoby Mathew	 * int console_core_putc(int c, uintptr_t base_addr)
13666be868eSSoby Mathew	 * Function to output a character over the console. It
13766be868eSSoby Mathew	 * returns the character printed on success or -1 on error.
13866be868eSSoby Mathew	 * In : r0 - character to be printed
13966be868eSSoby Mathew	 *      r1 - console base address
14066be868eSSoby Mathew	 * Out : return -1 on error else return character.
14166be868eSSoby Mathew	 * Clobber list : r2
14266be868eSSoby Mathew	 * --------------------------------------------------------
14366be868eSSoby Mathew	 */
144*7e2bbef9SDaniel Boulbyfunc console_pl011_core_putc
14566be868eSSoby Mathew	/* Check the input parameter */
14666be868eSSoby Mathew	cmp	r1, #0
14766be868eSSoby Mathew	beq	putc_error
14866be868eSSoby Mathew	/* Prepend '\r' to '\n' */
14966be868eSSoby Mathew	cmp	r0, #0xA
15066be868eSSoby Mathew	bne	2f
15166be868eSSoby Mathew1:
15266be868eSSoby Mathew	/* Check if the transmit FIFO is full */
15366be868eSSoby Mathew	ldr	r2, [r1, #UARTFR]
15469d59e0cSYatharth Kochar	tst	r2, #PL011_UARTFR_TXFF
15569d59e0cSYatharth Kochar	bne	1b
15666be868eSSoby Mathew	mov	r2, #0xD
15766be868eSSoby Mathew	str	r2, [r1, #UARTDR]
15866be868eSSoby Mathew2:
15966be868eSSoby Mathew	/* Check if the transmit FIFO is full */
16066be868eSSoby Mathew	ldr	r2, [r1, #UARTFR]
16169d59e0cSYatharth Kochar	tst	r2, #PL011_UARTFR_TXFF
16269d59e0cSYatharth Kochar	bne	2b
16366be868eSSoby Mathew	str	r0, [r1, #UARTDR]
16466be868eSSoby Mathew	bx	lr
16566be868eSSoby Mathewputc_error:
16666be868eSSoby Mathew	mov	r0, #-1
16766be868eSSoby Mathew	bx	lr
168*7e2bbef9SDaniel Boulbyendfunc console_pl011_core_putc
169*7e2bbef9SDaniel Boulby
170*7e2bbef9SDaniel Boulby	/* --------------------------------------------------------
171*7e2bbef9SDaniel Boulby	 * int console_pl011_putc(int c, console_pl011_t *console)
172*7e2bbef9SDaniel Boulby	 * Function to output a character over the console. It
173*7e2bbef9SDaniel Boulby	 * returns the character printed on success or -1 on error.
174*7e2bbef9SDaniel Boulby	 * In: r0 - character to be printed
175*7e2bbef9SDaniel Boulby	 *     r1 - pointer to console_t structure
176*7e2bbef9SDaniel Boulby	 * Out : return -1 on error else return character.
177*7e2bbef9SDaniel Boulby	 * Clobber list: r2
178*7e2bbef9SDaniel Boulby	 * -------------------------------------------------------
179*7e2bbef9SDaniel Boulby	 */
180*7e2bbef9SDaniel Boulbyfunc console_pl011_putc
181*7e2bbef9SDaniel Boulby#if ENABLE_ASSERTIONS
182*7e2bbef9SDaniel Boulby	cmp	r1, #0
183*7e2bbef9SDaniel Boulby	ASM_ASSERT(ne)
184*7e2bbef9SDaniel Boulby#endif /* ENABLE_ASSERTIONS */
185*7e2bbef9SDaniel Boulby	ldr	r1, [r1, #CONSOLE_T_PL011_BASE]
186*7e2bbef9SDaniel Boulby	b	console_pl011_core_putc
187*7e2bbef9SDaniel Boulbyendfunc console_pl011_putc
18866be868eSSoby Mathew
18966be868eSSoby Mathew	/* ---------------------------------------------
19066be868eSSoby Mathew	 * int console_core_getc(uintptr_t base_addr)
19166be868eSSoby Mathew	 * Function to get a character from the console.
19266be868eSSoby Mathew	 * It returns the character grabbed on success
19366be868eSSoby Mathew	 * or -1 on error.
19466be868eSSoby Mathew	 * In : r0 - console base address
19566be868eSSoby Mathew	 * Clobber list : r0, r1
19666be868eSSoby Mathew	 * ---------------------------------------------
19766be868eSSoby Mathew	 */
198*7e2bbef9SDaniel Boulbyfunc console_pl011_core_getc
19966be868eSSoby Mathew	cmp	r0, #0
20066be868eSSoby Mathew	beq	getc_error
20166be868eSSoby Mathew1:
20266be868eSSoby Mathew	/* Check if the receive FIFO is empty */
20366be868eSSoby Mathew	ldr	r1, [r0, #UARTFR]
20469d59e0cSYatharth Kochar	tst	r1, #PL011_UARTFR_RXFE
20569d59e0cSYatharth Kochar	bne	1b
20666be868eSSoby Mathew	ldr	r1, [r0, #UARTDR]
20766be868eSSoby Mathew	mov	r0, r1
20866be868eSSoby Mathew	bx	lr
20966be868eSSoby Mathewgetc_error:
21066be868eSSoby Mathew	mov	r0, #-1
21166be868eSSoby Mathew	bx	lr
212*7e2bbef9SDaniel Boulbyendfunc console_pl011_core_getc
213*7e2bbef9SDaniel Boulby
214*7e2bbef9SDaniel Boulby	/* ------------------------------------------------
215*7e2bbef9SDaniel Boulby	 * int console_pl011_getc(console_pl011_t *console)
216*7e2bbef9SDaniel Boulby	 * Function to get a character from the console.
217*7e2bbef9SDaniel Boulby	 * It returns the character grabbed on success
218*7e2bbef9SDaniel Boulby	 * or -1 if no character is available.
219*7e2bbef9SDaniel Boulby	 * In : r0 - pointer to console_t structure
220*7e2bbef9SDaniel Boulby	 * Out: r0 - character if available, else -1
221*7e2bbef9SDaniel Boulby	 * Clobber list: r0, r1
222*7e2bbef9SDaniel Boulby	 * ------------------------------------------------
223*7e2bbef9SDaniel Boulby	 */
224*7e2bbef9SDaniel Boulbyfunc console_pl011_getc
225*7e2bbef9SDaniel Boulby#if ENABLE_ASSERTIONS
226*7e2bbef9SDaniel Boulby	cmp	r0, #0
227*7e2bbef9SDaniel Boulby	ASM_ASSERT(ne)
228*7e2bbef9SDaniel Boulby#endif /* ENABLE_ASSERTIONS */
229*7e2bbef9SDaniel Boulby	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
230*7e2bbef9SDaniel Boulby	b	console_pl011_core_getc
231*7e2bbef9SDaniel Boulbyendfunc console_pl011_getc
23273e05284SAntonio Nino Diaz
23373e05284SAntonio Nino Diaz	/* ---------------------------------------------
23473e05284SAntonio Nino Diaz	 * int console_core_flush(uintptr_t base_addr)
23573e05284SAntonio Nino Diaz	 * Function to force a write of all buffered
23673e05284SAntonio Nino Diaz	 * data that hasn't been output.
23773e05284SAntonio Nino Diaz	 * In : r0 - console base address
23873e05284SAntonio Nino Diaz	 * Out : return -1 on error else return 0.
23973e05284SAntonio Nino Diaz	 * Clobber list : r0, r1
24073e05284SAntonio Nino Diaz	 * ---------------------------------------------
24173e05284SAntonio Nino Diaz	 */
242*7e2bbef9SDaniel Boulbyfunc console_pl011_core_flush
24373e05284SAntonio Nino Diaz	cmp	r0, #0
24473e05284SAntonio Nino Diaz	beq	flush_error
24573e05284SAntonio Nino Diaz
24673e05284SAntonio Nino Diaz1:
24773e05284SAntonio Nino Diaz	/* Loop while the transmit FIFO is busy */
24873e05284SAntonio Nino Diaz	ldr	r1, [r0, #UARTFR]
24973e05284SAntonio Nino Diaz	tst	r1, #PL011_UARTFR_BUSY
25073e05284SAntonio Nino Diaz	bne	1b
25173e05284SAntonio Nino Diaz
25273e05284SAntonio Nino Diaz	mov	r0, #0
25373e05284SAntonio Nino Diaz	bx	lr
25473e05284SAntonio Nino Diazflush_error:
25573e05284SAntonio Nino Diaz	mov	r0, #-1
25673e05284SAntonio Nino Diaz	bx	lr
257*7e2bbef9SDaniel Boulbyendfunc console_pl011_core_flush
258*7e2bbef9SDaniel Boulby
259*7e2bbef9SDaniel Boulby	/* ---------------------------------------------
260*7e2bbef9SDaniel Boulby	 * int console_pl011_flush(console_pl011_t *console)
261*7e2bbef9SDaniel Boulby	 * Function to force a write of all buffered
262*7e2bbef9SDaniel Boulby	 * data that hasn't been output.
263*7e2bbef9SDaniel Boulby	 * In : r0 - pointer to console_t structure
264*7e2bbef9SDaniel Boulby	 * Out : return -1 on error else return 0.
265*7e2bbef9SDaniel Boulby	 * Clobber list: r0, r1
266*7e2bbef9SDaniel Boulby	 * ---------------------------------------------
267*7e2bbef9SDaniel Boulby	 */
268*7e2bbef9SDaniel Boulbyfunc console_pl011_flush
269*7e2bbef9SDaniel Boulby#if ENABLE_ASSERTIONS
270*7e2bbef9SDaniel Boulby	cmp	r0, #0
271*7e2bbef9SDaniel Boulby	ASM_ASSERT(ne)
272*7e2bbef9SDaniel Boulby#endif /* ENABLE_ASSERTIONS */
273*7e2bbef9SDaniel Boulby	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
274*7e2bbef9SDaniel Boulby	b	console_pl011_core_flush
275*7e2bbef9SDaniel Boulbyendfunc console_pl011_flush
276