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