119112b79SKonstantin Porotchkin/* 219112b79SKonstantin Porotchkin * Copyright (C) 2016 Marvell International Ltd. 319112b79SKonstantin Porotchkin * 419112b79SKonstantin Porotchkin * SPDX-License-Identifier: BSD-3-Clause 519112b79SKonstantin Porotchkin * https://spdx.org/licenses 619112b79SKonstantin Porotchkin */ 719112b79SKonstantin Porotchkin 8d7c4420cSKonstantin Porotchkin#include <arch.h> 919112b79SKonstantin Porotchkin#include <asm_macros.S> 10d7c4420cSKonstantin Porotchkin#include <console_macros.S> 1109d40e0eSAntonio Nino Diaz#include <drivers/marvell/uart/a3700_console.h> 1219112b79SKonstantin Porotchkin 13d7c4420cSKonstantin Porotchkin /* 14d7c4420cSKonstantin Porotchkin * "core" functions are low-level implementations that don't require 15d7c4420cSKonstantin Porotchkin * writable memory and are thus safe to call in BL1 crash context. 16d7c4420cSKonstantin Porotchkin */ 17d7c4420cSKonstantin Porotchkin .globl console_a3700_core_putc 18d7c4420cSKonstantin Porotchkin .globl console_a3700_core_init 19d7c4420cSKonstantin Porotchkin .globl console_a3700_core_getc 20d7c4420cSKonstantin Porotchkin .globl console_a3700_core_flush 21d7c4420cSKonstantin Porotchkin 22d7c4420cSKonstantin Porotchkin .globl console_a3700_putc 23d7c4420cSKonstantin Porotchkin .globl console_a3700_getc 24d7c4420cSKonstantin Porotchkin .globl console_a3700_flush 2519112b79SKonstantin Porotchkin 2619112b79SKonstantin Porotchkin /* ----------------------------------------------- 27d7c4420cSKonstantin Porotchkin * int console_a3700_core_init(unsigned long base_addr, 2819112b79SKonstantin Porotchkin * unsigned int uart_clk, unsigned int baud_rate) 2919112b79SKonstantin Porotchkin * Function to initialize the console without a 3019112b79SKonstantin Porotchkin * C Runtime to print debug information. This 3119112b79SKonstantin Porotchkin * function will be accessed by console_init and 3219112b79SKonstantin Porotchkin * crash reporting. 3319112b79SKonstantin Porotchkin * In: x0 - console base address 3419112b79SKonstantin Porotchkin * w1 - Uart clock in Hz 3519112b79SKonstantin Porotchkin * w2 - Baud rate 3619112b79SKonstantin Porotchkin * Out: return 1 on success 377c85a757SPali Rohár * Clobber list : x1, x2, x3, x4 3819112b79SKonstantin Porotchkin * ----------------------------------------------- 3919112b79SKonstantin Porotchkin */ 40d7c4420cSKonstantin Porotchkinfunc console_a3700_core_init 4119112b79SKonstantin Porotchkin /* Check the input base address */ 4219112b79SKonstantin Porotchkin cbz x0, init_fail 4319112b79SKonstantin Porotchkin /* Check baud rate and uart clock for sanity */ 4419112b79SKonstantin Porotchkin cbz w1, init_fail 4519112b79SKonstantin Porotchkin cbz w2, init_fail 4619112b79SKonstantin Porotchkin 4719112b79SKonstantin Porotchkin /* 480d06b058SPali Rohár * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is 4919112b79SKonstantin Porotchkin * still not empty, TX FIFO will reset by all means. 5019112b79SKonstantin Porotchkin */ 517c85a757SPali Rohár mov w4, #30 /* max time out 30 * 100 us */ 5219112b79SKonstantin Porotchkin2: 53b8e637f4SPali Rohár /* Check whether TX (THR and TSR) is empty */ 5419112b79SKonstantin Porotchkin ldr w3, [x0, #UART_STATUS_REG] 55b8e637f4SPali Rohár and w3, w3, #UARTLSR_TXEMPTY 5619112b79SKonstantin Porotchkin cmp w3, #0 5719112b79SKonstantin Porotchkin b.ne 4f 5819112b79SKonstantin Porotchkin 5919112b79SKonstantin Porotchkin /* Delay */ 607c85a757SPali Rohár mov w3, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */ 6119112b79SKonstantin Porotchkin3: 627c85a757SPali Rohár sub w3, w3, #1 637c85a757SPali Rohár cmp w3, #0 6419112b79SKonstantin Porotchkin b.ne 3b 6519112b79SKonstantin Porotchkin 66ab1fe188SPali Rohár /* Check whether wait timeout expired */ 677c85a757SPali Rohár sub w4, w4, #1 687c85a757SPali Rohár cmp w4, #0 6919112b79SKonstantin Porotchkin b.ne 2b 7019112b79SKonstantin Porotchkin 7119112b79SKonstantin Porotchkin4: 7219112b79SKonstantin Porotchkin /* Reset FIFO */ 7319112b79SKonstantin Porotchkin mov w3, #UART_CTRL_RXFIFO_RESET 7419112b79SKonstantin Porotchkin orr w3, w3, #UART_CTRL_TXFIFO_RESET 7519112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 7619112b79SKonstantin Porotchkin 7719112b79SKonstantin Porotchkin /* Delay */ 787c85a757SPali Rohár mov w3, #2000 7919112b79SKonstantin Porotchkin1: 807c85a757SPali Rohár sub w3, w3, #1 817c85a757SPali Rohár cmp w3, #0 8219112b79SKonstantin Porotchkin b.ne 1b 8319112b79SKonstantin Porotchkin 84*15546dbfSPali Rohár /* Program the baudrate */ 85*15546dbfSPali Rohár /* Divisor = Round(Uartclock / (16 * baudrate)) */ 86*15546dbfSPali Rohár lsl w2, w2, #4 87*15546dbfSPali Rohár add w1, w1, w2, lsr #1 88*15546dbfSPali Rohár udiv w2, w1, w2 89*15546dbfSPali Rohár and w2, w2, #0x3ff /* clear all other bits to use default clock */ 90*15546dbfSPali Rohár 91*15546dbfSPali Rohár str w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */ 92*15546dbfSPali Rohár 93*15546dbfSPali Rohár /* Set UART to default 16X scheme */ 94*15546dbfSPali Rohár mov w3, #0 95*15546dbfSPali Rohár str w3, [x0, #UART_POSSR_REG] 96*15546dbfSPali Rohár 9719112b79SKonstantin Porotchkin /* No Parity, 1 Stop */ 9819112b79SKonstantin Porotchkin mov w3, #0 9919112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 10019112b79SKonstantin Porotchkin 10119112b79SKonstantin Porotchkin mov w0, #1 10219112b79SKonstantin Porotchkin ret 10319112b79SKonstantin Porotchkininit_fail: 10419112b79SKonstantin Porotchkin mov w0, #0 10519112b79SKonstantin Porotchkin ret 106d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_init 107d7c4420cSKonstantin Porotchkin 108d7c4420cSKonstantin Porotchkin .globl console_a3700_register 109d7c4420cSKonstantin Porotchkin 110d7c4420cSKonstantin Porotchkin /* ----------------------------------------------- 1113968bc08SAndre Przywara * int console_a3700_register(console_t *console, 112d7c4420cSKonstantin Porotchkin uintptr_t base, uint32_t clk, uint32_t baud) 113d7c4420cSKonstantin Porotchkin * Function to initialize and register a new a3700 114d7c4420cSKonstantin Porotchkin * console. Storage passed in for the console struct 115d7c4420cSKonstantin Porotchkin * *must* be persistent (i.e. not from the stack). 116d7c4420cSKonstantin Porotchkin * In: x0 - UART register base address 117d7c4420cSKonstantin Porotchkin * w1 - UART clock in Hz 118d7c4420cSKonstantin Porotchkin * w2 - Baud rate 1193968bc08SAndre Przywara * x3 - pointer to empty console_t struct 120d7c4420cSKonstantin Porotchkin * Out: return 1 on success, 0 on error 1217c85a757SPali Rohár * Clobber list : x0, x1, x2, x3, x4, x6, x7, x14 122d7c4420cSKonstantin Porotchkin * ----------------------------------------------- 123d7c4420cSKonstantin Porotchkin */ 124d7c4420cSKonstantin Porotchkinfunc console_a3700_register 125d7c4420cSKonstantin Porotchkin mov x7, x30 126d7c4420cSKonstantin Porotchkin mov x6, x3 127d7c4420cSKonstantin Porotchkin cbz x6, register_fail 1283968bc08SAndre Przywara str x0, [x6, #CONSOLE_T_BASE] 129d7c4420cSKonstantin Porotchkin 130d7c4420cSKonstantin Porotchkin bl console_a3700_core_init 131d7c4420cSKonstantin Porotchkin cbz x0, register_fail 132d7c4420cSKonstantin Porotchkin 133d7c4420cSKonstantin Porotchkin mov x0, x6 134d7c4420cSKonstantin Porotchkin mov x30, x7 135d7c4420cSKonstantin Porotchkin finish_console_register a3700, putc=1, getc=1, flush=1 136d7c4420cSKonstantin Porotchkin 137d7c4420cSKonstantin Porotchkinregister_fail: 138d7c4420cSKonstantin Porotchkin ret x7 139d7c4420cSKonstantin Porotchkinendfunc console_a3700_register 14019112b79SKonstantin Porotchkin 14119112b79SKonstantin Porotchkin /* -------------------------------------------------------- 142d7c4420cSKonstantin Porotchkin * int console_a3700_core_putc(int c, unsigned int base_addr) 14319112b79SKonstantin Porotchkin * Function to output a character over the console. It 14419112b79SKonstantin Porotchkin * returns the character printed on success or -1 on error. 14519112b79SKonstantin Porotchkin * In : w0 - character to be printed 14619112b79SKonstantin Porotchkin * x1 - console base address 14719112b79SKonstantin Porotchkin * Out : return -1 on error else return character. 14819112b79SKonstantin Porotchkin * Clobber list : x2 14919112b79SKonstantin Porotchkin * -------------------------------------------------------- 15019112b79SKonstantin Porotchkin */ 151d7c4420cSKonstantin Porotchkinfunc console_a3700_core_putc 15219112b79SKonstantin Porotchkin /* Check the input parameter */ 15319112b79SKonstantin Porotchkin cbz x1, putc_error 15419112b79SKonstantin Porotchkin 15519112b79SKonstantin Porotchkin /* Prepend '\r' to '\n' */ 15619112b79SKonstantin Porotchkin cmp w0, #0xA 15719112b79SKonstantin Porotchkin b.ne 2f 15819112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 15919112b79SKonstantin Porotchkin1: ldr w2, [x1, #UART_STATUS_REG] 16019112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 16119112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 16219112b79SKonstantin Porotchkin b.eq 1b 16319112b79SKonstantin Porotchkin mov w2, #0xD /* '\r' */ 16419112b79SKonstantin Porotchkin str w2, [x1, #UART_TX_REG] 16519112b79SKonstantin Porotchkin 16619112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 16719112b79SKonstantin Porotchkin2: ldr w2, [x1, #UART_STATUS_REG] 16819112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 16919112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 17019112b79SKonstantin Porotchkin b.eq 2b 17119112b79SKonstantin Porotchkin str w0, [x1, #UART_TX_REG] 17219112b79SKonstantin Porotchkin ret 17319112b79SKonstantin Porotchkinputc_error: 17419112b79SKonstantin Porotchkin mov w0, #-1 17519112b79SKonstantin Porotchkin ret 176d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_putc 177d7c4420cSKonstantin Porotchkin 178d7c4420cSKonstantin Porotchkin /* -------------------------------------------------------- 1793968bc08SAndre Przywara * int console_a3700_putc(int c, console_t *console) 180d7c4420cSKonstantin Porotchkin * Function to output a character over the console. It 181d7c4420cSKonstantin Porotchkin * returns the character printed on success or -1 on error. 182d7c4420cSKonstantin Porotchkin * In : w0 - character to be printed 183d7c4420cSKonstantin Porotchkin * x1 - pointer to console_t structure 184d7c4420cSKonstantin Porotchkin * Out : return -1 on error else return character. 185d7c4420cSKonstantin Porotchkin * Clobber list : x2 186d7c4420cSKonstantin Porotchkin * -------------------------------------------------------- 187d7c4420cSKonstantin Porotchkin */ 188d7c4420cSKonstantin Porotchkinfunc console_a3700_putc 1893968bc08SAndre Przywara ldr x1, [x1, #CONSOLE_T_BASE] 190d7c4420cSKonstantin Porotchkin b console_a3700_core_putc 191d7c4420cSKonstantin Porotchkinendfunc console_a3700_putc 19219112b79SKonstantin Porotchkin 19319112b79SKonstantin Porotchkin /* --------------------------------------------- 194d7c4420cSKonstantin Porotchkin * int console_a3700_core_getc(void) 19519112b79SKonstantin Porotchkin * Function to get a character from the console. 19619112b79SKonstantin Porotchkin * It returns the character grabbed on success 19774867756SPali Rohár * or -1 if no character is available. 19819112b79SKonstantin Porotchkin * In : w0 - console base address 19974867756SPali Rohár * Out : w0 - character if available, else -1 20019112b79SKonstantin Porotchkin * Clobber list : x0, x1 20119112b79SKonstantin Porotchkin * --------------------------------------------- 20219112b79SKonstantin Porotchkin */ 203d7c4420cSKonstantin Porotchkinfunc console_a3700_core_getc 20474867756SPali Rohár /* Check if there is a pending character */ 20574867756SPali Rohár ldr w1, [x0, #UART_STATUS_REG] 20674867756SPali Rohár and w1, w1, #UARTLSR_RXRDY 20774867756SPali Rohár cmp w1, #UARTLSR_RXRDY 20874867756SPali Rohár b.ne getc_no_char 20974867756SPali Rohár ldr w0, [x0, #UART_RX_REG] 21074867756SPali Rohár and w0, w0, #0xff 21174867756SPali Rohár ret 21274867756SPali Rohárgetc_no_char: 21374867756SPali Rohár mov w0, #ERROR_NO_PENDING_CHAR 21419112b79SKonstantin Porotchkin ret 215d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_getc 21619112b79SKonstantin Porotchkin 21719112b79SKonstantin Porotchkin /* --------------------------------------------- 2183968bc08SAndre Przywara * int console_a3700_getc(console_t *console) 219d7c4420cSKonstantin Porotchkin * Function to get a character from the console. 220d7c4420cSKonstantin Porotchkin * It returns the character grabbed on success 221d7c4420cSKonstantin Porotchkin * or -1 on if no character is available. 222d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 223d7c4420cSKonstantin Porotchkin * Out : w0 - character if available, else -1 224d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 225d7c4420cSKonstantin Porotchkin * --------------------------------------------- 226d7c4420cSKonstantin Porotchkin */ 227d7c4420cSKonstantin Porotchkinfunc console_a3700_getc 2283968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 229d7c4420cSKonstantin Porotchkin b console_a3700_core_getc 230d7c4420cSKonstantin Porotchkinendfunc console_a3700_getc 231d7c4420cSKonstantin Porotchkin 232d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 233831b0e98SJimmy Brisson * void console_a3700_core_flush(uintptr_t base_addr) 23419112b79SKonstantin Porotchkin * Function to force a write of all buffered 23519112b79SKonstantin Porotchkin * data that hasn't been output. 23619112b79SKonstantin Porotchkin * In : x0 - console base address 237831b0e98SJimmy Brisson * Out : void. 23819112b79SKonstantin Porotchkin * Clobber list : x0, x1 23919112b79SKonstantin Porotchkin * --------------------------------------------- 24019112b79SKonstantin Porotchkin */ 241d7c4420cSKonstantin Porotchkinfunc console_a3700_core_flush 242b8e637f4SPali Rohár /* Wait for the TX (THR and TSR) to be empty */ 243e63e4140SPali Rohár1: ldr w1, [x0, #UART_STATUS_REG] 244b8e637f4SPali Rohár and w1, w1, #UARTLSR_TXEMPTY 245b8e637f4SPali Rohár cmp w1, #UARTLSR_TXEMPTY 246e63e4140SPali Rohár b.ne 1b 24719112b79SKonstantin Porotchkin ret 248d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_flush 249d7c4420cSKonstantin Porotchkin 250d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 251831b0e98SJimmy Brisson * void console_a3700_flush(console_t *console) 252d7c4420cSKonstantin Porotchkin * Function to force a write of all buffered 253d7c4420cSKonstantin Porotchkin * data that hasn't been output. 254d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 255831b0e98SJimmy Brisson * Out : void. 256d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 257d7c4420cSKonstantin Porotchkin * --------------------------------------------- 258d7c4420cSKonstantin Porotchkin */ 259d7c4420cSKonstantin Porotchkinfunc console_a3700_flush 2603968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 261d7c4420cSKonstantin Porotchkin b console_a3700_core_flush 262d7c4420cSKonstantin Porotchkinendfunc console_a3700_flush 263d7c4420cSKonstantin Porotchkin 264