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