1/* 2 * Copyright (c) 2013-2017, 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/aarch64/console.S" 19#endif 20 21 /* 22 * "core" functions are low-level implementations that don't require 23 * writable 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 * int console_pl011_core_init(uintptr_t base_addr, 36 * unsigned int uart_clk, unsigned int baud_rate) 37 * Function to initialize the console without a 38 * C Runtime to print debug information. This 39 * function will be accessed by console_init and 40 * crash reporting. 41 * In: x0 - console base address 42 * w1 - Uart clock in Hz 43 * w2 - Baud rate 44 * Out: return 1 on success else 0 on error 45 * Clobber list : x1, x2, x3, x4 46 * ----------------------------------------------- 47 */ 48func console_pl011_core_init 49 /* Check the input base address */ 50 cbz x0, core_init_fail 51#if !PL011_GENERIC_UART 52 /* Check baud rate and uart clock for sanity */ 53 cbz w1, core_init_fail 54 cbz w2, core_init_fail 55 /* Disable uart before programming */ 56 ldr w3, [x0, #UARTCR] 57 mov w4, #PL011_UARTCR_UARTEN 58 bic w3, w3, w4 59 str w3, [x0, #UARTCR] 60 /* Program the baudrate */ 61 /* Divisor = (Uart clock * 4) / baudrate */ 62 lsl w1, w1, #2 63 udiv w2, w1, w2 64 /* IBRD = Divisor >> 6 */ 65 lsr w1, w2, #6 66 /* Write the IBRD */ 67 str w1, [x0, #UARTIBRD] 68 /* FBRD = Divisor & 0x3F */ 69 and w1, w2, #0x3f 70 /* Write the FBRD */ 71 str w1, [x0, #UARTFBRD] 72 mov w1, #PL011_LINE_CONTROL 73 str w1, [x0, #UARTLCR_H] 74 /* Clear any pending errors */ 75 str wzr, [x0, #UARTECR] 76 /* Enable tx, rx, and uart overall */ 77 mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) 78 str w1, [x0, #UARTCR] 79#endif 80 mov w0, #1 81 ret 82core_init_fail: 83 mov w0, wzr 84 ret 85endfunc console_pl011_core_init 86 87#if MULTI_CONSOLE_API 88 .globl console_pl011_register 89 90 /* ----------------------------------------------- 91 * int console_pl011_register(uintptr_t baseaddr, 92 * uint32_t clock, uint32_t baud, 93 * console_pl011_t *console); 94 * Function to initialize and register a new PL011 95 * console. Storage passed in for the console struct 96 * *must* be persistent (i.e. not from the stack). 97 * In: x0 - UART register base address 98 * w1 - UART clock in Hz 99 * w2 - Baud rate 100 * x3 - pointer to empty console_pl011_t struct 101 * Out: return 1 on success, 0 on error 102 * Clobber list : x0, x1, x2, x6, x7, x14 103 * ----------------------------------------------- 104 */ 105func console_pl011_register 106 mov x7, x30 107 mov x6, x3 108 cbz x6, register_fail 109 str x0, [x6, #CONSOLE_T_PL011_BASE] 110 111 bl console_pl011_core_init 112 cbz x0, register_fail 113 114 mov x0, x6 115 mov x30, x7 116 finish_console_register pl011 putc=1, getc=1, flush=1 117 118register_fail: 119 ret x7 120endfunc console_pl011_register 121#else 122 .globl console_core_init 123 .globl console_core_putc 124 .globl console_core_getc 125 .globl console_core_flush 126 .equ console_core_init,console_pl011_core_init 127 .equ console_core_putc,console_pl011_core_putc 128 .equ console_core_getc,console_pl011_core_getc 129 .equ console_core_flush,console_pl011_core_flush 130#endif 131 132 /* -------------------------------------------------------- 133 * int console_pl011_core_putc(int c, uintptr_t base_addr) 134 * Function to output a character over the console. It 135 * returns the character printed on success or -1 on error. 136 * In : w0 - character to be printed 137 * x1 - console base address 138 * Out : return -1 on error else return character. 139 * Clobber list : x2 140 * -------------------------------------------------------- 141 */ 142func console_pl011_core_putc 143#if ENABLE_ASSERTIONS 144 cmp x1, #0 145 ASM_ASSERT(ne) 146#endif /* ENABLE_ASSERTIONS */ 147 148 /* Prepend '\r' to '\n' */ 149 cmp w0, #0xA 150 b.ne 2f 1511: 152 /* Check if the transmit FIFO is full */ 153 ldr w2, [x1, #UARTFR] 154 tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b 155 mov w2, #0xD 156 str w2, [x1, #UARTDR] 1572: 158 /* Check if the transmit FIFO is full */ 159 ldr w2, [x1, #UARTFR] 160 tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b 161 str w0, [x1, #UARTDR] 162 ret 163endfunc console_pl011_core_putc 164 165 /* -------------------------------------------------------- 166 * int console_pl011_putc(int c, console_pl011_t *console) 167 * Function to output a character over the console. It 168 * returns the character printed on success or -1 on error. 169 * In : w0 - character to be printed 170 * x1 - pointer to console_t structure 171 * Out : return -1 on error else return character. 172 * Clobber list : x2 173 * -------------------------------------------------------- 174 */ 175func console_pl011_putc 176#if ENABLE_ASSERTIONS 177 cmp x1, #0 178 ASM_ASSERT(ne) 179#endif /* ENABLE_ASSERTIONS */ 180 ldr x1, [x1, #CONSOLE_T_PL011_BASE] 181 b console_pl011_core_putc 182endfunc console_pl011_putc 183 184 /* --------------------------------------------- 185 * int console_pl011_core_getc(uintptr_t base_addr) 186 * Function to get a character from the console. 187 * It returns the character grabbed on success 188 * or -1 if no character is available. 189 * In : x0 - console base address 190 * Out: w0 - character if available, else -1 191 * Clobber list : x0, x1 192 * --------------------------------------------- 193 */ 194func console_pl011_core_getc 195#if ENABLE_ASSERTIONS 196 cmp x0, #0 197 ASM_ASSERT(ne) 198#endif /* ENABLE_ASSERTIONS */ 199 200 /* Check if the receive FIFO is empty */ 201 ldr w1, [x0, #UARTFR] 202 tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char 203 ldr w1, [x0, #UARTDR] 204 mov w0, w1 205 ret 206no_char: 207 mov w0, #ERROR_NO_PENDING_CHAR 208 ret 209endfunc console_pl011_core_getc 210 211 /* --------------------------------------------- 212 * int console_pl011_getc(console_pl011_t *console) 213 * Function to get a character from the console. 214 * It returns the character grabbed on success 215 * or -1 if no character is available. 216 * In : x0 - pointer to console_t structure 217 * Out: w0 - character if available, else -1 218 * Clobber list : x0, x1 219 * --------------------------------------------- 220 */ 221func console_pl011_getc 222#if ENABLE_ASSERTIONS 223 cmp x0, #0 224 ASM_ASSERT(ne) 225#endif /* ENABLE_ASSERTIONS */ 226 ldr x0, [x0, #CONSOLE_T_PL011_BASE] 227 b console_pl011_core_getc 228endfunc console_pl011_getc 229 230 /* --------------------------------------------- 231 * int console_pl011_core_flush(uintptr_t base_addr) 232 * Function to force a write of all buffered 233 * data that hasn't been output. 234 * In : x0 - console base address 235 * Out : return -1 on error else return 0. 236 * Clobber list : x0, x1 237 * --------------------------------------------- 238 */ 239func console_pl011_core_flush 240#if ENABLE_ASSERTIONS 241 cmp x0, #0 242 ASM_ASSERT(ne) 243#endif /* ENABLE_ASSERTIONS */ 2441: 245 /* Loop until the transmit FIFO is empty */ 246 ldr w1, [x0, #UARTFR] 247 tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b 248 249 mov w0, #0 250 ret 251endfunc console_pl011_core_flush 252 253 /* --------------------------------------------- 254 * int console_pl011_flush(console_pl011_t *console) 255 * Function to force a write of all buffered 256 * data that hasn't been output. 257 * In : x0 - pointer to console_t structure 258 * Out : return -1 on error else return 0. 259 * Clobber list : x0, x1 260 * --------------------------------------------- 261 */ 262func console_pl011_flush 263#if ENABLE_ASSERTIONS 264 cmp x0, #0 265 ASM_ASSERT(ne) 266#endif /* ENABLE_ASSERTIONS */ 267 ldr x0, [x0, #CONSOLE_T_PL011_BASE] 268 b console_pl011_core_flush 269endfunc console_pl011_flush 270