1/* 2 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <arch.h> 8#include <asm_macros.S> 9#include <assert_macros.S> 10#include <console_macros.S> 11#include <uart_16550.h> 12 13 /* 14 * "core" functions are low-level implementations that don't require 15 * writable memory and are thus safe to call in BL1 crash context. 16 */ 17 .globl console_16550_core_init 18 .globl console_16550_core_putc 19 .globl console_16550_core_getc 20 21 .globl console_16550_putc 22 .globl console_16550_getc 23 24 25 /* ----------------------------------------------- 26 * int console_16550_core_init(uintptr_t base_addr, 27 * unsigned int uart_clk, unsigned int baud_rate) 28 * Function to initialize the console without a 29 * C Runtime to print debug information. This 30 * function will be accessed by console_init and 31 * crash reporting. 32 * In: x0 - console base address 33 * w1 - Uart clock in Hz 34 * w2 - Baud rate 35 * Out: return 1 on success, 0 on error 36 * Clobber list : x1, x2, x3 37 * ----------------------------------------------- 38 */ 39func console_16550_core_init 40 /* Check the input base address */ 41 cbz x0, init_fail 42 /* Check baud rate and uart clock for sanity */ 43 cbz w1, init_fail 44 cbz w2, init_fail 45 46 /* Program the baudrate */ 47 /* Divisor = Uart clock / (16 * baudrate) */ 48 lsl w2, w2, #4 49 udiv w2, w1, w2 50 and w1, w2, #0xff /* w1 = DLL */ 51 lsr w2, w2, #8 52 and w2, w2, #0xff /* w2 = DLLM */ 53 ldr w3, [x0, #UARTLCR] 54 orr w3, w3, #UARTLCR_DLAB 55 str w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */ 56 str w1, [x0, #UARTDLL] /* program DLL */ 57 str w2, [x0, #UARTDLLM] /* program DLLM */ 58 mov w2, #~UARTLCR_DLAB 59 and w3, w3, w2 60 str w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */ 61 62 /* 8n1 */ 63 mov w3, #3 64 str w3, [x0, #UARTLCR] 65 /* no interrupt */ 66 mov w3, #0 67 str w3, [x0, #UARTIER] 68 /* enable fifo, DMA */ 69 mov w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN) 70 str w3, [x0, #UARTFCR] 71 /* DTR + RTS */ 72 mov w3, #3 73 str w3, [x0, #UARTMCR] 74 mov w0, #1 75 ret 76init_fail: 77 mov w0, #0 78 ret 79endfunc console_16550_core_init 80 81#if MULTI_CONSOLE_API 82 .globl console_16550_register 83 84 /* ----------------------------------------------- 85 * int console_16550_register(console_16550_t *console, 86 uintptr_t base, uint32_t clk, uint32_t baud) 87 * Function to initialize and register a new 16550 88 * console. Storage passed in for the console struct 89 * *must* be persistent (i.e. not from the stack). 90 * In: x0 - UART register base address 91 * w1 - UART clock in Hz 92 * w2 - Baud rate 93 * x3 - pointer to empty console_16550_t struct 94 * Out: return 1 on success, 0 on error 95 * Clobber list : x0, x1, x2, x6, x7, x14 96 * ----------------------------------------------- 97 */ 98func console_16550_register 99 mov x7, x30 100 mov x6, x3 101 cbz x6, register_fail 102 str x0, [x6, #CONSOLE_T_16550_BASE] 103 104 bl console_16550_core_init 105 cbz x0, register_fail 106 107 mov x0, x6 108 mov x30, x7 109 finish_console_register 16550 110 111register_fail: 112 ret x7 113endfunc console_16550_register 114#else 115 .globl console_core_init 116 .globl console_core_putc 117 .globl console_core_getc 118 .globl console_core_flush 119 .equ console_core_init,console_16550_core_init 120 .equ console_core_putc,console_16550_core_putc 121 .equ console_core_getc,console_16550_core_getc 122#endif 123 124 /* -------------------------------------------------------- 125 * int console_16550_core_putc(int c, uintptr_t base_addr) 126 * Function to output a character over the console. It 127 * returns the character printed on success or -1 on error. 128 * In : w0 - character to be printed 129 * x1 - console base address 130 * Out : return -1 on error else return character. 131 * Clobber list : x2 132 * -------------------------------------------------------- 133 */ 134func console_16550_core_putc 135#if ENABLE_ASSERTIONS 136 cmp x1, #0 137 ASM_ASSERT(ne) 138#endif /* ENABLE_ASSERTIONS */ 139 140 /* Prepend '\r' to '\n' */ 141 cmp w0, #0xA 142 b.ne 2f 143 /* Check if the transmit FIFO is full */ 1441: ldr w2, [x1, #UARTLSR] 145 and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE) 146 cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) 147 b.ne 1b 148 mov w2, #0xD /* '\r' */ 149 str w2, [x1, #UARTTX] 150 151 /* Check if the transmit FIFO is full */ 1522: ldr w2, [x1, #UARTLSR] 153 and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE) 154 cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) 155 b.ne 2b 156 str w0, [x1, #UARTTX] 157 ret 158endfunc console_16550_core_putc 159 160 /* -------------------------------------------------------- 161 * int console_16550_putc(int c, console_16550_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_16550_putc 171#if ENABLE_ASSERTIONS 172 cmp x1, #0 173 ASM_ASSERT(ne) 174#endif /* ENABLE_ASSERTIONS */ 175 ldr x1, [x1, #CONSOLE_T_16550_BASE] 176 b console_16550_core_putc 177endfunc console_16550_putc 178 179 /* --------------------------------------------- 180 * int console_16550_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 on 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_16550_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 */ 1961: ldr w1, [x0, #UARTLSR] 197 tbz w1, #UARTLSR_RDR_BIT, no_char 198 ldr w0, [x0, #UARTRX] 199 ret 200no_char: 201 mov w0, #ERROR_NO_PENDING_CHAR 202 ret 203endfunc console_16550_core_getc 204 205 /* --------------------------------------------- 206 * int console_16550_getc(console_16550_t *console) 207 * Function to get a character from the console. 208 * It returns the character grabbed on success 209 * or -1 on if no character is available. 210 * In : x0 - pointer to console_t stucture 211 * Out : w0 - character if available, else -1 212 * Clobber list : x0, x1 213 * --------------------------------------------- 214 */ 215func console_16550_getc 216#if ENABLE_ASSERTIONS 217 cmp x1, #0 218 ASM_ASSERT(ne) 219#endif /* ENABLE_ASSERTIONS */ 220 ldr x0, [x0, #CONSOLE_T_16550_BASE] 221 b console_16550_core_getc 222endfunc console_16550_getc 223 224 /* --------------------------------------------- 225 * int console_core_flush(uintptr_t base_addr) 226 * DEPRECATED: Not used with MULTI_CONSOLE_API! 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_core_flush 235 /* Placeholder */ 236 mov w0, #0 237 ret 238endfunc console_core_flush 239