1/* 2 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7#include <asm_macros.S> 8#include <console_macros.S> 9 10#define CONSOLE_NUM_BYTES_SHIFT 24 11#define CONSOLE_FLUSH_DATA_TO_PORT (1 << 26) 12#define CONSOLE_RING_DOORBELL (1 << 31) 13#define CONSOLE_IS_BUSY (1 << 31) 14#define CONSOLE_TIMEOUT 0xC000 /* 50 ms */ 15 16 /* 17 * This file contains a driver implementation to make use of the 18 * real console implementation provided by the SPE firmware running 19 * SoCs after Tegra186. 20 * 21 * This console is shared by multiple components and the SPE firmware 22 * finally displays everything on the UART port. 23 */ 24 25 .globl console_spe_core_init 26 .globl console_spe_core_putc 27 .globl console_spe_core_getc 28 .globl console_spe_core_flush 29 .globl console_spe_putc 30 .globl console_spe_getc 31 .globl console_spe_flush 32 .globl console_spe_register 33 34.macro check_if_console_is_ready base, tmp1, tmp2, label 35 /* wait until spe is ready or timeout expires */ 36 mrs \tmp2, cntps_tval_el1 371: ldr \tmp1, [\base] 38 and \tmp1, \tmp1, #CONSOLE_IS_BUSY 39 cbz \tmp1, 2f 40 mrs \tmp1, cntps_tval_el1 41 sub \tmp1, \tmp2, \tmp1 42 cmp \tmp1, #CONSOLE_TIMEOUT 43 b.lt 1b 44 b \label 452: 46.endm 47 48 /* ------------------------------------------------- 49 * int console_spe_register(uintptr_t baseaddr, 50 * uint32_t clock, uint32_t baud, 51 * console_t *console); 52 * Function to initialize and register a new spe 53 * console. Storage passed in for the console struct 54 * *must* be persistent (i.e. not from the stack). 55 * In: x0 - UART register base address 56 * w1 - UART clock in Hz 57 * w2 - Baud rate 58 * x3 - pointer to empty console_t struct 59 * Out: return 1 on success, 0 on error 60 * Clobber list : x0, x1, x2, x6, x7, x14 61 * ------------------------------------------------- 62 */ 63func console_spe_register 64 /* Check the input base address */ 65 cbz x0, register_fail 66 67 /* Dont use clock or baud rate, so ok to overwrite them */ 68 check_if_console_is_ready x0, x1, x2, register_fail 69 70 cbz x3, register_fail 71 str x0, [x3, #CONSOLE_T_BASE] 72 mov x0, x3 73 finish_console_register spe putc=1, getc=1, flush=1 74 75register_fail: 76 mov w0, wzr 77 ret 78endfunc console_spe_register 79 80 /* -------------------------------------------------------- 81 * int console_spe_core_putc(int c, uintptr_t base_addr) 82 * Function to output a character over the console. It 83 * returns the character printed on success or -1 on error. 84 * In : w0 - character to be printed 85 * x1 - console base address 86 * Out : return -1 on error else return character. 87 * Clobber list : x2, x3 88 * -------------------------------------------------------- 89 */ 90func console_spe_core_putc 91 /* Check the input parameter */ 92 cbz x1, putc_error 93 94 /* Prepend '\r' to '\n' */ 95 cmp w0, #0xA 96 b.ne not_eol 97 98 check_if_console_is_ready x1, x2, x3, putc_error 99 100 /* spe is ready */ 101 mov w2, #0xD /* '\r' */ 102 and w2, w2, #0xFF 103 mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT)) 104 orr w2, w2, w3 105 str w2, [x1] 106 107not_eol: 108 check_if_console_is_ready x1, x2, x3, putc_error 109 110 /* spe is ready */ 111 mov w2, w0 112 and w2, w2, #0xFF 113 mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT)) 114 orr w2, w2, w3 115 str w2, [x1] 116 117 ret 118putc_error: 119 mov w0, #-1 120 ret 121endfunc console_spe_core_putc 122 123 /* -------------------------------------------------------- 124 * int console_spe_putc(int c, console_t *console) 125 * Function to output a character over the console. It 126 * returns the character printed on success or -1 on error. 127 * In : w0 - character to be printed 128 * x1 - pointer to console_t structure 129 * Out : return -1 on error else return character. 130 * Clobber list : x2 131 * -------------------------------------------------------- 132 */ 133func console_spe_putc 134 ldr x1, [x1, #CONSOLE_T_BASE] 135 b console_spe_core_putc 136endfunc console_spe_putc 137 138 /* --------------------------------------------- 139 * int console_spe_getc(console_t *console) 140 * Function to get a character from the console. 141 * It returns the character grabbed on success 142 * or -1 if no character is available. 143 * In : x0 - pointer to console_t structure 144 * Out: w0 - character if available, else -1 145 * Clobber list : x0, x1 146 * --------------------------------------------- 147 */ 148func console_spe_getc 149 mov w0, #-1 150 ret 151endfunc console_spe_getc 152 153 /* ------------------------------------------------- 154 * int console_spe_core_flush(uintptr_t base_addr) 155 * Function to force a write of all buffered 156 * data that hasn't been output. 157 * In : x0 - console base address 158 * Out : return -1 on error else return 0. 159 * Clobber list : x0, x1 160 * ------------------------------------------------- 161 */ 162func console_spe_core_flush 163 cbz x0, flush_error 164 165 /* flush console */ 166 mov w1, #(CONSOLE_RING_DOORBELL | CONSOLE_FLUSH_DATA_TO_PORT) 167 str w1, [x0] 168 mov w0, #0 169 ret 170flush_error: 171 mov w0, #-1 172 ret 173endfunc console_spe_core_flush 174 175 /* --------------------------------------------- 176 * int console_spe_flush(console_t *console) 177 * Function to force a write of all buffered 178 * data that hasn't been output. 179 * In : x0 - pointer to console_t structure 180 * Out : return -1 on error else return 0. 181 * Clobber list : x0, x1 182 * --------------------------------------------- 183 */ 184func console_spe_flush 185 ldr x0, [x0, #CONSOLE_T_BASE] 186 b console_spe_core_flush 187endfunc console_spe_flush 188