1/* 2 * Copyright (c) 2016-2018, 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/aarch32/console.S" 17 18 /* 19 * "core" functions are low-level implementations that don't require 20 * writeable 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 /* ----------------------------------------------- 33 * int console_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: r0 - console base address 40 * r1 - Uart clock in Hz 41 * r2 - Baud rate 42 * Out: return 1 on success else 0 on error 43 * Clobber list : r1, r2, r3 44 * ----------------------------------------------- 45 */ 46func console_pl011_core_init 47 /* Check the input base address */ 48 cmp r0, #0 49 beq core_init_fail 50#if !PL011_GENERIC_UART 51 /* Check baud rate and uart clock for sanity */ 52 cmp r1, #0 53 beq core_init_fail 54 cmp r2, #0 55 beq core_init_fail 56 /* Disable the UART before initialization */ 57 ldr r3, [r0, #UARTCR] 58 bic r3, r3, #PL011_UARTCR_UARTEN 59 str r3, [r0, #UARTCR] 60 /* Program the baudrate */ 61 /* Divisor = (Uart clock * 4) / baudrate */ 62 lsl r1, r1, #2 63 udiv r2, r1, r2 64 /* IBRD = Divisor >> 6 */ 65 lsr r1, r2, #6 66 /* Write the IBRD */ 67 str r1, [r0, #UARTIBRD] 68 /* FBRD = Divisor & 0x3F */ 69 and r1, r2, #0x3f 70 /* Write the FBRD */ 71 str r1, [r0, #UARTFBRD] 72 mov r1, #PL011_LINE_CONTROL 73 str r1, [r0, #UARTLCR_H] 74 /* Clear any pending errors */ 75 mov r1, #0 76 str r1, [r0, #UARTECR] 77 /* Enable tx, rx, and uart overall */ 78 ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) 79 str r1, [r0, #UARTCR] 80#endif 81 mov r0, #1 82 bx lr 83core_init_fail: 84 mov r0, #0 85 bx lr 86endfunc console_pl011_core_init 87 88#if MULTI_CONSOLE_API 89 .globl console_pl011_register 90 91 /* ------------------------------------------------------- 92 * int console_pl011_register(uintptr_t baseaddr, 93 * uint32_t clock, uint32_t baud, 94 * console_pl011_t *console); 95 * Function to initialize and register a new PL011 96 * console. Storage passed in for the console struct 97 * *must* be persistent (i.e. not from the stack). 98 * In: r0 - UART register base address 99 * r1 - UART clock in Hz 100 * r2 - Baud rate 101 * r3 - pointer to empty console_pl011_t struct 102 * Out: return 1 on success, 0 on error 103 * Clobber list : r0, r1, r2 104 * ------------------------------------------------------- 105 */ 106func console_pl011_register 107 push {r4, lr} 108 mov r4, r3 109 cmp r4, #0 110 beq register_fail 111 str r0, [r4, #CONSOLE_T_PL011_BASE] 112 113 bl console_pl011_core_init 114 cmp r0, #0 115 beq register_fail 116 117 mov r0, r4 118 pop {r4, lr} 119 finish_console_register pl011 120 121register_fail: 122 pop {r4, pc} 123endfunc console_pl011_register 124#else 125 .globl console_core_init 126 .globl console_core_putc 127 .globl console_core_getc 128 .globl console_core_flush 129 .equ console_core_init, console_pl011_core_init 130 .equ console_core_putc, console_pl011_core_putc 131 .equ console_core_getc, console_pl011_core_getc 132 .equ console_core_flush, console_pl011_core_flush 133#endif 134 135 /* -------------------------------------------------------- 136 * int console_core_putc(int c, uintptr_t base_addr) 137 * Function to output a character over the console. It 138 * returns the character printed on success or -1 on error. 139 * In : r0 - character to be printed 140 * r1 - console base address 141 * Out : return -1 on error else return character. 142 * Clobber list : r2 143 * -------------------------------------------------------- 144 */ 145func console_pl011_core_putc 146 /* Check the input parameter */ 147 cmp r1, #0 148 beq putc_error 149 /* Prepend '\r' to '\n' */ 150 cmp r0, #0xA 151 bne 2f 1521: 153 /* Check if the transmit FIFO is full */ 154 ldr r2, [r1, #UARTFR] 155 tst r2, #PL011_UARTFR_TXFF 156 bne 1b 157 mov r2, #0xD 158 str r2, [r1, #UARTDR] 1592: 160 /* Check if the transmit FIFO is full */ 161 ldr r2, [r1, #UARTFR] 162 tst r2, #PL011_UARTFR_TXFF 163 bne 2b 164 str r0, [r1, #UARTDR] 165 bx lr 166putc_error: 167 mov r0, #-1 168 bx lr 169endfunc console_pl011_core_putc 170 171 /* -------------------------------------------------------- 172 * int console_pl011_putc(int c, console_pl011_t *console) 173 * Function to output a character over the console. It 174 * returns the character printed on success or -1 on error. 175 * In: r0 - character to be printed 176 * r1 - pointer to console_t structure 177 * Out : return -1 on error else return character. 178 * Clobber list: r2 179 * ------------------------------------------------------- 180 */ 181func console_pl011_putc 182#if ENABLE_ASSERTIONS 183 cmp r1, #0 184 ASM_ASSERT(ne) 185#endif /* ENABLE_ASSERTIONS */ 186 ldr r1, [r1, #CONSOLE_T_PL011_BASE] 187 b console_pl011_core_putc 188endfunc console_pl011_putc 189 190 /* --------------------------------------------- 191 * int console_core_getc(uintptr_t base_addr) 192 * Function to get a character from the console. 193 * It returns the character grabbed on success 194 * or -1 on error. 195 * In : r0 - console base address 196 * Clobber list : r0, r1 197 * --------------------------------------------- 198 */ 199func console_pl011_core_getc 200 cmp r0, #0 201 beq getc_error 2021: 203 /* Check if the receive FIFO is empty */ 204 ldr r1, [r0, #UARTFR] 205 tst r1, #PL011_UARTFR_RXFE 206 bne 1b 207 ldr r1, [r0, #UARTDR] 208 mov r0, r1 209 bx lr 210getc_error: 211 mov r0, #-1 212 bx lr 213endfunc console_pl011_core_getc 214 215 /* ------------------------------------------------ 216 * int console_pl011_getc(console_pl011_t *console) 217 * Function to get a character from the console. 218 * It returns the character grabbed on success 219 * or -1 if no character is available. 220 * In : r0 - pointer to console_t structure 221 * Out: r0 - character if available, else -1 222 * Clobber list: r0, r1 223 * ------------------------------------------------ 224 */ 225func console_pl011_getc 226#if ENABLE_ASSERTIONS 227 cmp r0, #0 228 ASM_ASSERT(ne) 229#endif /* ENABLE_ASSERTIONS */ 230 ldr r0, [r0, #CONSOLE_T_PL011_BASE] 231 b console_pl011_core_getc 232endfunc console_pl011_getc 233 234 /* --------------------------------------------- 235 * int console_core_flush(uintptr_t base_addr) 236 * Function to force a write of all buffered 237 * data that hasn't been output. 238 * In : r0 - console base address 239 * Out : return -1 on error else return 0. 240 * Clobber list : r0, r1 241 * --------------------------------------------- 242 */ 243func console_pl011_core_flush 244 cmp r0, #0 245 beq flush_error 246 2471: 248 /* Loop while the transmit FIFO is busy */ 249 ldr r1, [r0, #UARTFR] 250 tst r1, #PL011_UARTFR_BUSY 251 bne 1b 252 253 mov r0, #0 254 bx lr 255flush_error: 256 mov r0, #-1 257 bx lr 258endfunc console_pl011_core_flush 259 260 /* --------------------------------------------- 261 * int console_pl011_flush(console_pl011_t *console) 262 * Function to force a write of all buffered 263 * data that hasn't been output. 264 * In : r0 - pointer to console_t structure 265 * Out : return -1 on error else return 0. 266 * Clobber list: r0, r1 267 * --------------------------------------------- 268 */ 269func console_pl011_flush 270#if ENABLE_ASSERTIONS 271 cmp r0, #0 272 ASM_ASSERT(ne) 273#endif /* ENABLE_ASSERTIONS */ 274 ldr r0, [r0, #CONSOLE_T_PL011_BASE] 275 b console_pl011_core_flush 276endfunc console_pl011_flush 277