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