166be868eSSoby Mathew/* 273e05284SAntonio Nino Diaz * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. 366be868eSSoby Mathew * 4*82cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 566be868eSSoby Mathew */ 666be868eSSoby Mathew#include <arch.h> 766be868eSSoby Mathew#include <asm_macros.S> 866be868eSSoby Mathew#include <pl011.h> 966be868eSSoby Mathew 1066be868eSSoby Mathew/* 1166be868eSSoby Mathew * Pull in generic functions to provide backwards compatibility for 1266be868eSSoby Mathew * platform makefiles 1366be868eSSoby Mathew */ 1466be868eSSoby Mathew#include "../../../console/aarch32/console.S" 1566be868eSSoby Mathew 1666be868eSSoby Mathew .globl console_core_init 1766be868eSSoby Mathew .globl console_core_putc 1866be868eSSoby Mathew .globl console_core_getc 1973e05284SAntonio Nino Diaz .globl console_core_flush 2066be868eSSoby Mathew 2166be868eSSoby Mathew 2266be868eSSoby Mathew /* ----------------------------------------------- 2366be868eSSoby Mathew * int console_core_init(uintptr_t base_addr, 2466be868eSSoby Mathew * unsigned int uart_clk, unsigned int baud_rate) 2566be868eSSoby Mathew * Function to initialize the console without a 2666be868eSSoby Mathew * C Runtime to print debug information. This 2766be868eSSoby Mathew * function will be accessed by console_init and 2866be868eSSoby Mathew * crash reporting. 2966be868eSSoby Mathew * In: r0 - console base address 3066be868eSSoby Mathew * r1 - Uart clock in Hz 3166be868eSSoby Mathew * r2 - Baud rate 3266be868eSSoby Mathew * Out: return 1 on success else 0 on error 3366be868eSSoby Mathew * Clobber list : r1, r2, r3 3466be868eSSoby Mathew * ----------------------------------------------- 3566be868eSSoby Mathew */ 3666be868eSSoby Mathewfunc console_core_init 3766be868eSSoby Mathew /* Check the input base address */ 3866be868eSSoby Mathew cmp r0, #0 3966be868eSSoby Mathew beq core_init_fail 4066be868eSSoby Mathew#if !PL011_GENERIC_UART 4166be868eSSoby Mathew /* Check baud rate and uart clock for sanity */ 4266be868eSSoby Mathew cmp r1, #0 4366be868eSSoby Mathew beq core_init_fail 4466be868eSSoby Mathew cmp r2, #0 4566be868eSSoby Mathew beq core_init_fail 4666be868eSSoby Mathew /* Disable the UART before initialization */ 4766be868eSSoby Mathew ldr r3, [r0, #UARTCR] 4866be868eSSoby Mathew bic r3, r3, #PL011_UARTCR_UARTEN 4966be868eSSoby Mathew str r3, [r0, #UARTCR] 5066be868eSSoby Mathew /* Program the baudrate */ 5166be868eSSoby Mathew /* Divisor = (Uart clock * 4) / baudrate */ 5266be868eSSoby Mathew lsl r1, r1, #2 5366be868eSSoby Mathew udiv r2, r1, r2 5466be868eSSoby Mathew /* IBRD = Divisor >> 6 */ 5566be868eSSoby Mathew lsr r1, r2, #6 5666be868eSSoby Mathew /* Write the IBRD */ 5766be868eSSoby Mathew str r1, [r0, #UARTIBRD] 5866be868eSSoby Mathew /* FBRD = Divisor & 0x3F */ 5966be868eSSoby Mathew and r1, r2, #0x3f 6066be868eSSoby Mathew /* Write the FBRD */ 6166be868eSSoby Mathew str r1, [r0, #UARTFBRD] 6266be868eSSoby Mathew mov r1, #PL011_LINE_CONTROL 6366be868eSSoby Mathew str r1, [r0, #UARTLCR_H] 6466be868eSSoby Mathew /* Clear any pending errors */ 6566be868eSSoby Mathew mov r1, #0 6666be868eSSoby Mathew str r1, [r0, #UARTECR] 6766be868eSSoby Mathew /* Enable tx, rx, and uart overall */ 6866be868eSSoby Mathew ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) 6966be868eSSoby Mathew str r1, [r0, #UARTCR] 7066be868eSSoby Mathew#endif 7166be868eSSoby Mathew mov r0, #1 7266be868eSSoby Mathew bx lr 7366be868eSSoby Mathewcore_init_fail: 7466be868eSSoby Mathew mov r0, #0 7566be868eSSoby Mathew bx lr 7666be868eSSoby Mathewendfunc console_core_init 7766be868eSSoby Mathew 7866be868eSSoby Mathew /* -------------------------------------------------------- 7966be868eSSoby Mathew * int console_core_putc(int c, uintptr_t base_addr) 8066be868eSSoby Mathew * Function to output a character over the console. It 8166be868eSSoby Mathew * returns the character printed on success or -1 on error. 8266be868eSSoby Mathew * In : r0 - character to be printed 8366be868eSSoby Mathew * r1 - console base address 8466be868eSSoby Mathew * Out : return -1 on error else return character. 8566be868eSSoby Mathew * Clobber list : r2 8666be868eSSoby Mathew * -------------------------------------------------------- 8766be868eSSoby Mathew */ 8866be868eSSoby Mathewfunc console_core_putc 8966be868eSSoby Mathew /* Check the input parameter */ 9066be868eSSoby Mathew cmp r1, #0 9166be868eSSoby Mathew beq putc_error 9266be868eSSoby Mathew /* Prepend '\r' to '\n' */ 9366be868eSSoby Mathew cmp r0, #0xA 9466be868eSSoby Mathew bne 2f 9566be868eSSoby Mathew1: 9666be868eSSoby Mathew /* Check if the transmit FIFO is full */ 9766be868eSSoby Mathew ldr r2, [r1, #UARTFR] 9869d59e0cSYatharth Kochar tst r2, #PL011_UARTFR_TXFF 9969d59e0cSYatharth Kochar bne 1b 10066be868eSSoby Mathew mov r2, #0xD 10166be868eSSoby Mathew str r2, [r1, #UARTDR] 10266be868eSSoby Mathew2: 10366be868eSSoby Mathew /* Check if the transmit FIFO is full */ 10466be868eSSoby Mathew ldr r2, [r1, #UARTFR] 10569d59e0cSYatharth Kochar tst r2, #PL011_UARTFR_TXFF 10669d59e0cSYatharth Kochar bne 2b 10766be868eSSoby Mathew str r0, [r1, #UARTDR] 10866be868eSSoby Mathew bx lr 10966be868eSSoby Mathewputc_error: 11066be868eSSoby Mathew mov r0, #-1 11166be868eSSoby Mathew bx lr 11266be868eSSoby Mathewendfunc console_core_putc 11366be868eSSoby Mathew 11466be868eSSoby Mathew /* --------------------------------------------- 11566be868eSSoby Mathew * int console_core_getc(uintptr_t base_addr) 11666be868eSSoby Mathew * Function to get a character from the console. 11766be868eSSoby Mathew * It returns the character grabbed on success 11866be868eSSoby Mathew * or -1 on error. 11966be868eSSoby Mathew * In : r0 - console base address 12066be868eSSoby Mathew * Clobber list : r0, r1 12166be868eSSoby Mathew * --------------------------------------------- 12266be868eSSoby Mathew */ 12366be868eSSoby Mathewfunc console_core_getc 12466be868eSSoby Mathew cmp r0, #0 12566be868eSSoby Mathew beq getc_error 12666be868eSSoby Mathew1: 12766be868eSSoby Mathew /* Check if the receive FIFO is empty */ 12866be868eSSoby Mathew ldr r1, [r0, #UARTFR] 12969d59e0cSYatharth Kochar tst r1, #PL011_UARTFR_RXFE 13069d59e0cSYatharth Kochar bne 1b 13166be868eSSoby Mathew ldr r1, [r0, #UARTDR] 13266be868eSSoby Mathew mov r0, r1 13366be868eSSoby Mathew bx lr 13466be868eSSoby Mathewgetc_error: 13566be868eSSoby Mathew mov r0, #-1 13666be868eSSoby Mathew bx lr 13766be868eSSoby Mathewendfunc console_core_getc 13873e05284SAntonio Nino Diaz 13973e05284SAntonio Nino Diaz /* --------------------------------------------- 14073e05284SAntonio Nino Diaz * int console_core_flush(uintptr_t base_addr) 14173e05284SAntonio Nino Diaz * Function to force a write of all buffered 14273e05284SAntonio Nino Diaz * data that hasn't been output. 14373e05284SAntonio Nino Diaz * In : r0 - console base address 14473e05284SAntonio Nino Diaz * Out : return -1 on error else return 0. 14573e05284SAntonio Nino Diaz * Clobber list : r0, r1 14673e05284SAntonio Nino Diaz * --------------------------------------------- 14773e05284SAntonio Nino Diaz */ 14873e05284SAntonio Nino Diazfunc console_core_flush 14973e05284SAntonio Nino Diaz cmp r0, #0 15073e05284SAntonio Nino Diaz beq flush_error 15173e05284SAntonio Nino Diaz 15273e05284SAntonio Nino Diaz1: 15373e05284SAntonio Nino Diaz /* Loop while the transmit FIFO is busy */ 15473e05284SAntonio Nino Diaz ldr r1, [r0, #UARTFR] 15573e05284SAntonio Nino Diaz tst r1, #PL011_UARTFR_BUSY 15673e05284SAntonio Nino Diaz bne 1b 15773e05284SAntonio Nino Diaz 15873e05284SAntonio Nino Diaz mov r0, #0 15973e05284SAntonio Nino Diaz bx lr 16073e05284SAntonio Nino Diazflush_error: 16173e05284SAntonio Nino Diaz mov r0, #-1 16273e05284SAntonio Nino Diaz bx lr 16373e05284SAntonio Nino Diazendfunc console_core_flush 164