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