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