1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu#include <asm_macros.S> 7*91f16700Schasinglulu#include <uart8250.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu .globl console_core_init 10*91f16700Schasinglulu .globl console_core_putc 11*91f16700Schasinglulu .globl console_core_getc 12*91f16700Schasinglulu .globl console_core_flush 13*91f16700Schasinglulu 14*91f16700Schasinglulu /* ----------------------------------------------- 15*91f16700Schasinglulu * int console_core_init(unsigned long base_addr, 16*91f16700Schasinglulu * unsigned int uart_clk, unsigned int baud_rate) 17*91f16700Schasinglulu * Function to initialize the console without a 18*91f16700Schasinglulu * C Runtime to print debug information. This 19*91f16700Schasinglulu * function will be accessed by console_init and 20*91f16700Schasinglulu * crash reporting. 21*91f16700Schasinglulu * In: x0 - console base address 22*91f16700Schasinglulu * w1 - Uart clock in Hz 23*91f16700Schasinglulu * w2 - Baud rate 24*91f16700Schasinglulu * Out: return 1 on success else 0 on error 25*91f16700Schasinglulu * Clobber list : x1, x2, x3 26*91f16700Schasinglulu * ----------------------------------------------- 27*91f16700Schasinglulu */ 28*91f16700Schasinglulufunc console_core_init 29*91f16700Schasinglulu /* Check the input base address */ 30*91f16700Schasinglulu cbz x0, core_init_fail 31*91f16700Schasinglulu /* Check baud rate and uart clock for sanity */ 32*91f16700Schasinglulu cbz w1, core_init_fail 33*91f16700Schasinglulu cbz w2, core_init_fail 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* Disable interrupt */ 36*91f16700Schasinglulu str wzr, [x0, #UART_IER] 37*91f16700Schasinglulu 38*91f16700Schasinglulu /* Force DTR and RTS to high */ 39*91f16700Schasinglulu mov w3, #(UART_MCR_DTR | UART_MCR_RTS) 40*91f16700Schasinglulu str w3, [x0, #UART_MCR] 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* Check high speed */ 43*91f16700Schasinglulu movz w3, #:abs_g1:115200 44*91f16700Schasinglulu movk w3, #:abs_g0_nc:115200 45*91f16700Schasinglulu cmp w2, w3 46*91f16700Schasinglulu b.hi 1f 47*91f16700Schasinglulu 48*91f16700Schasinglulu /* Non high speed */ 49*91f16700Schasinglulu lsl w2, w2, #4 50*91f16700Schasinglulu mov w3, wzr 51*91f16700Schasinglulu b 2f 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* High speed */ 54*91f16700Schasinglulu1: lsl w2, w2, #2 55*91f16700Schasinglulu mov w3, #2 56*91f16700Schasinglulu 57*91f16700Schasinglulu /* Set high speed UART register */ 58*91f16700Schasinglulu2: str w3, [x0, #UART_HIGHSPEED] 59*91f16700Schasinglulu 60*91f16700Schasinglulu /* Calculate divisor */ 61*91f16700Schasinglulu udiv w3, w1, w2 /* divisor = uartclk / (quot * baudrate) */ 62*91f16700Schasinglulu msub w1, w3, w2, w1 /* remainder = uartclk % (quot * baudrate) */ 63*91f16700Schasinglulu lsr w2, w2, #1 64*91f16700Schasinglulu cmp w1, w2 65*91f16700Schasinglulu cinc w3, w3, hs 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* Set line configuration, access divisor latches */ 68*91f16700Schasinglulu mov w1, #(UART_LCR_DLAB | UART_LCR_WLS_8) 69*91f16700Schasinglulu str w1, [x0, #UART_LCR] 70*91f16700Schasinglulu 71*91f16700Schasinglulu /* Set the divisor */ 72*91f16700Schasinglulu and w1, w3, #0xff 73*91f16700Schasinglulu str w1, [x0, #UART_DLL] 74*91f16700Schasinglulu lsr w1, w3, #8 75*91f16700Schasinglulu and w1, w1, #0xff 76*91f16700Schasinglulu str w1, [x0, #UART_DLH] 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* Hide the divisor latches */ 79*91f16700Schasinglulu mov w1, #UART_LCR_WLS_8 80*91f16700Schasinglulu str w1, [x0, #UART_LCR] 81*91f16700Schasinglulu 82*91f16700Schasinglulu /* Enable FIFOs, and clear receive and transmit */ 83*91f16700Schasinglulu mov w1, #(UART_FCR_FIFO_EN | UART_FCR_CLEAR_RCVR | \ 84*91f16700Schasinglulu UART_FCR_CLEAR_XMIT) 85*91f16700Schasinglulu str w1, [x0, #UART_FCR] 86*91f16700Schasinglulu 87*91f16700Schasinglulu mov w0, #1 88*91f16700Schasinglulu ret 89*91f16700Schasinglulucore_init_fail: 90*91f16700Schasinglulu mov w0, wzr 91*91f16700Schasinglulu ret 92*91f16700Schasingluluendfunc console_core_init 93*91f16700Schasinglulu 94*91f16700Schasinglulu /* -------------------------------------------------------- 95*91f16700Schasinglulu * int console_core_putc(int c, unsigned long base_addr) 96*91f16700Schasinglulu * Function to output a character over the console. It 97*91f16700Schasinglulu * returns the character printed on success or -1 on error. 98*91f16700Schasinglulu * In : w0 - character to be printed 99*91f16700Schasinglulu * x1 - console base address 100*91f16700Schasinglulu * Out : return -1 on error else return character. 101*91f16700Schasinglulu * Clobber list : x2 102*91f16700Schasinglulu * -------------------------------------------------------- 103*91f16700Schasinglulu */ 104*91f16700Schasinglulufunc console_core_putc 105*91f16700Schasinglulu /* Check the input parameter */ 106*91f16700Schasinglulu cbz x1, putc_error 107*91f16700Schasinglulu /* Prepend '\r' to '\n' */ 108*91f16700Schasinglulu cmp w0, #0xA 109*91f16700Schasinglulu b.ne 2f 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* Check if the transmit FIFO is full */ 112*91f16700Schasinglulu1: ldr w2, [x1, #UART_LSR] 113*91f16700Schasinglulu and w2, w2, #UART_LSR_THRE 114*91f16700Schasinglulu cbz w2, 1b 115*91f16700Schasinglulu mov w2, #0xD 116*91f16700Schasinglulu str w2, [x1, #UART_THR] 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* Check if the transmit FIFO is full */ 119*91f16700Schasinglulu2: ldr w2, [x1, #UART_LSR] 120*91f16700Schasinglulu and w2, w2, #UART_LSR_THRE 121*91f16700Schasinglulu cbz w2, 2b 122*91f16700Schasinglulu str w0, [x1, #UART_THR] 123*91f16700Schasinglulu ret 124*91f16700Schasingluluputc_error: 125*91f16700Schasinglulu mov w0, #-1 126*91f16700Schasinglulu ret 127*91f16700Schasingluluendfunc console_core_putc 128*91f16700Schasinglulu 129*91f16700Schasinglulu /* --------------------------------------------- 130*91f16700Schasinglulu * int console_core_getc(unsigned long base_addr) 131*91f16700Schasinglulu * Function to get a character from the console. 132*91f16700Schasinglulu * It returns the character grabbed on success 133*91f16700Schasinglulu * or -1 on error. 134*91f16700Schasinglulu * In : x0 - console base address 135*91f16700Schasinglulu * Clobber list : x0, x1 136*91f16700Schasinglulu * --------------------------------------------- 137*91f16700Schasinglulu */ 138*91f16700Schasinglulufunc console_core_getc 139*91f16700Schasinglulu cbz x0, getc_error 140*91f16700Schasinglulu 141*91f16700Schasinglulu /* Check if the receive FIFO is empty */ 142*91f16700Schasinglulu1: ldr w1, [x0, #UART_LSR] 143*91f16700Schasinglulu tbz w1, #UART_LSR_DR, 1b 144*91f16700Schasinglulu ldr w0, [x0, #UART_RBR] 145*91f16700Schasinglulu ret 146*91f16700Schasinglulugetc_error: 147*91f16700Schasinglulu mov w0, #-1 148*91f16700Schasinglulu ret 149*91f16700Schasingluluendfunc console_core_getc 150*91f16700Schasinglulu 151*91f16700Schasinglulu /* --------------------------------------------- 152*91f16700Schasinglulu * void console_core_flush(uintptr_t base_addr) 153*91f16700Schasinglulu * Function to force a write of all buffered 154*91f16700Schasinglulu * data that hasn't been output. 155*91f16700Schasinglulu * In : x0 - console base address 156*91f16700Schasinglulu * Out : void. 157*91f16700Schasinglulu * Clobber list : x0, x1 158*91f16700Schasinglulu * --------------------------------------------- 159*91f16700Schasinglulu */ 160*91f16700Schasinglulufunc console_core_flush 161*91f16700Schasinglulu /* Placeholder */ 162*91f16700Schasinglulu ret 163*91f16700Schasingluluendfunc console_core_flush 164