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