1/* 2 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6#include <arch.h> 7#include <asm_macros.S> 8#include <assert_macros.S> 9#define USE_FINISH_CONSOLE_REG_2 10#include <console_macros.S> 11#include <pl011.h> 12 13/* 14 * Pull in generic functions to provide backwards compatibility for 15 * platform makefiles 16 */ 17#include "../../../console/aarch32/console.S" 18 19 /* 20 * "core" functions are low-level implementations that don't require 21 * writeable memory and are thus safe to call in BL1 crash context. 22 */ 23 .globl console_pl011_core_init 24 .globl console_pl011_core_putc 25 .globl console_pl011_core_getc 26 .globl console_pl011_core_flush 27 28 .globl console_pl011_putc 29 .globl console_pl011_getc 30 .globl console_pl011_flush 31 32 33 /* ----------------------------------------------- 34 * int console_core_init(uintptr_t base_addr, 35 * unsigned int uart_clk, unsigned int baud_rate) 36 * Function to initialize the console without a 37 * C Runtime to print debug information. This 38 * function will be accessed by console_init and 39 * crash reporting. 40 * In: r0 - console base address 41 * r1 - Uart clock in Hz 42 * r2 - Baud rate 43 * Out: return 1 on success else 0 on error 44 * Clobber list : r1, r2, r3 45 * ----------------------------------------------- 46 */ 47func console_pl011_core_init 48 /* Check the input base address */ 49 cmp r0, #0 50 beq core_init_fail 51#if !PL011_GENERIC_UART 52 /* Check baud rate and uart clock for sanity */ 53 cmp r1, #0 54 beq core_init_fail 55 cmp r2, #0 56 beq core_init_fail 57 /* Disable the UART before initialization */ 58 ldr r3, [r0, #UARTCR] 59 bic r3, r3, #PL011_UARTCR_UARTEN 60 str r3, [r0, #UARTCR] 61 /* Program the baudrate */ 62 /* Divisor = (Uart clock * 4) / baudrate */ 63 lsl r1, r1, #2 64 udiv r2, r1, r2 65 /* IBRD = Divisor >> 6 */ 66 lsr r1, r2, #6 67 /* Write the IBRD */ 68 str r1, [r0, #UARTIBRD] 69 /* FBRD = Divisor & 0x3F */ 70 and r1, r2, #0x3f 71 /* Write the FBRD */ 72 str r1, [r0, #UARTFBRD] 73 mov r1, #PL011_LINE_CONTROL 74 str r1, [r0, #UARTLCR_H] 75 /* Clear any pending errors */ 76 mov r1, #0 77 str r1, [r0, #UARTECR] 78 /* Enable tx, rx, and uart overall */ 79 ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) 80 str r1, [r0, #UARTCR] 81#endif 82 mov r0, #1 83 bx lr 84core_init_fail: 85 mov r0, #0 86 bx lr 87endfunc console_pl011_core_init 88 89#if MULTI_CONSOLE_API 90 .globl console_pl011_register 91 92 /* ------------------------------------------------------- 93 * int console_pl011_register(uintptr_t baseaddr, 94 * uint32_t clock, uint32_t baud, 95 * console_pl011_t *console); 96 * Function to initialize and register a new PL011 97 * console. Storage passed in for the console struct 98 * *must* be persistent (i.e. not from the stack). 99 * In: r0 - UART register base address 100 * r1 - UART clock in Hz 101 * r2 - Baud rate 102 * r3 - pointer to empty console_pl011_t struct 103 * Out: return 1 on success, 0 on error 104 * Clobber list : r0, r1, r2 105 * ------------------------------------------------------- 106 */ 107func console_pl011_register 108 push {r4, lr} 109 mov r4, r3 110 cmp r4, #0 111 beq register_fail 112 str r0, [r4, #CONSOLE_T_PL011_BASE] 113 114 bl console_pl011_core_init 115 cmp r0, #0 116 beq register_fail 117 118 mov r0, r4 119 pop {r4, lr} 120 finish_console_register pl011 putc=1, getc=1, flush=1 121 122register_fail: 123 pop {r4, pc} 124endfunc console_pl011_register 125#else 126 .globl console_core_init 127 .globl console_core_putc 128 .globl console_core_getc 129 .globl console_core_flush 130 .equ console_core_init, console_pl011_core_init 131 .equ console_core_putc, console_pl011_core_putc 132 .equ console_core_getc, console_pl011_core_getc 133 .equ console_core_flush, console_pl011_core_flush 134#endif 135 136 /* -------------------------------------------------------- 137 * int console_core_putc(int c, uintptr_t base_addr) 138 * Function to output a character over the console. It 139 * returns the character printed on success or -1 on error. 140 * In : r0 - character to be printed 141 * r1 - console base address 142 * Out : return -1 on error else return character. 143 * Clobber list : r2 144 * -------------------------------------------------------- 145 */ 146func console_pl011_core_putc 147 /* Check the input parameter */ 148 cmp r1, #0 149 beq putc_error 150 /* Prepend '\r' to '\n' */ 151 cmp r0, #0xA 152 bne 2f 1531: 154 /* Check if the transmit FIFO is full */ 155 ldr r2, [r1, #UARTFR] 156 tst r2, #PL011_UARTFR_TXFF 157 bne 1b 158 mov r2, #0xD 159 str r2, [r1, #UARTDR] 1602: 161 /* Check if the transmit FIFO is full */ 162 ldr r2, [r1, #UARTFR] 163 tst r2, #PL011_UARTFR_TXFF 164 bne 2b 165 str r0, [r1, #UARTDR] 166 bx lr 167putc_error: 168 mov r0, #-1 169 bx lr 170endfunc console_pl011_core_putc 171 172 /* -------------------------------------------------------- 173 * int console_pl011_putc(int c, console_pl011_t *console) 174 * Function to output a character over the console. It 175 * returns the character printed on success or -1 on error. 176 * In: r0 - character to be printed 177 * r1 - pointer to console_t structure 178 * Out : return -1 on error else return character. 179 * Clobber list: r2 180 * ------------------------------------------------------- 181 */ 182func console_pl011_putc 183#if ENABLE_ASSERTIONS 184 cmp r1, #0 185 ASM_ASSERT(ne) 186#endif /* ENABLE_ASSERTIONS */ 187 ldr r1, [r1, #CONSOLE_T_PL011_BASE] 188 b console_pl011_core_putc 189endfunc console_pl011_putc 190 191 /* --------------------------------------------- 192 * int console_core_getc(uintptr_t base_addr) 193 * Function to get a character from the console. 194 * It returns the character grabbed on success 195 * or -1 on error. 196 * In : r0 - console base address 197 * Clobber list : r0, r1 198 * --------------------------------------------- 199 */ 200func console_pl011_core_getc 201 cmp r0, #0 202 beq getc_error 2031: 204 /* Check if the receive FIFO is empty */ 205 ldr r1, [r0, #UARTFR] 206 tst r1, #PL011_UARTFR_RXFE 207 bne 1b 208 ldr r1, [r0, #UARTDR] 209 mov r0, r1 210 bx lr 211getc_error: 212 mov r0, #-1 213 bx lr 214endfunc console_pl011_core_getc 215 216 /* ------------------------------------------------ 217 * int console_pl011_getc(console_pl011_t *console) 218 * Function to get a character from the console. 219 * It returns the character grabbed on success 220 * or -1 if no character is available. 221 * In : r0 - pointer to console_t structure 222 * Out: r0 - character if available, else -1 223 * Clobber list: r0, r1 224 * ------------------------------------------------ 225 */ 226func console_pl011_getc 227#if ENABLE_ASSERTIONS 228 cmp r0, #0 229 ASM_ASSERT(ne) 230#endif /* ENABLE_ASSERTIONS */ 231 ldr r0, [r0, #CONSOLE_T_PL011_BASE] 232 b console_pl011_core_getc 233endfunc console_pl011_getc 234 235 /* --------------------------------------------- 236 * int console_core_flush(uintptr_t base_addr) 237 * Function to force a write of all buffered 238 * data that hasn't been output. 239 * In : r0 - console base address 240 * Out : return -1 on error else return 0. 241 * Clobber list : r0, r1 242 * --------------------------------------------- 243 */ 244func console_pl011_core_flush 245 cmp r0, #0 246 beq flush_error 247 2481: 249 /* Loop while the transmit FIFO is busy */ 250 ldr r1, [r0, #UARTFR] 251 tst r1, #PL011_UARTFR_BUSY 252 bne 1b 253 254 mov r0, #0 255 bx lr 256flush_error: 257 mov r0, #-1 258 bx lr 259endfunc console_pl011_core_flush 260 261 /* --------------------------------------------- 262 * int console_pl011_flush(console_pl011_t *console) 263 * Function to force a write of all buffered 264 * data that hasn't been output. 265 * In : r0 - pointer to console_t structure 266 * Out : return -1 on error else return 0. 267 * Clobber list: r0, r1 268 * --------------------------------------------- 269 */ 270func console_pl011_flush 271#if ENABLE_ASSERTIONS 272 cmp r0, #0 273 ASM_ASSERT(ne) 274#endif /* ENABLE_ASSERTIONS */ 275 ldr r0, [r0, #CONSOLE_T_PL011_BASE] 276 b console_pl011_core_flush 277endfunc console_pl011_flush 278