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#define USE_FINISH_CONSOLE_REG_2 11d7c4420cSKonstantin Porotchkin#include <console_macros.S> 12*09d40e0eSAntonio Nino Diaz#include <drivers/marvell/uart/a3700_console.h> 1319112b79SKonstantin Porotchkin 14d7c4420cSKonstantin Porotchkin /* 15d7c4420cSKonstantin Porotchkin * "core" functions are low-level implementations that don't require 16d7c4420cSKonstantin Porotchkin * writable memory and are thus safe to call in BL1 crash context. 17d7c4420cSKonstantin Porotchkin */ 18d7c4420cSKonstantin Porotchkin .globl console_a3700_core_putc 19d7c4420cSKonstantin Porotchkin .globl console_a3700_core_init 20d7c4420cSKonstantin Porotchkin .globl console_a3700_core_getc 21d7c4420cSKonstantin Porotchkin .globl console_a3700_core_flush 22d7c4420cSKonstantin Porotchkin 23d7c4420cSKonstantin Porotchkin .globl console_a3700_putc 24d7c4420cSKonstantin Porotchkin .globl console_a3700_getc 25d7c4420cSKonstantin Porotchkin .globl console_a3700_flush 2619112b79SKonstantin Porotchkin 2719112b79SKonstantin Porotchkin /* ----------------------------------------------- 28d7c4420cSKonstantin Porotchkin * int console_a3700_core_init(unsigned long base_addr, 2919112b79SKonstantin Porotchkin * unsigned int uart_clk, unsigned int baud_rate) 3019112b79SKonstantin Porotchkin * Function to initialize the console without a 3119112b79SKonstantin Porotchkin * C Runtime to print debug information. This 3219112b79SKonstantin Porotchkin * function will be accessed by console_init and 3319112b79SKonstantin Porotchkin * crash reporting. 3419112b79SKonstantin Porotchkin * In: x0 - console base address 3519112b79SKonstantin Porotchkin * w1 - Uart clock in Hz 3619112b79SKonstantin Porotchkin * w2 - Baud rate 3719112b79SKonstantin Porotchkin * Out: return 1 on success 3819112b79SKonstantin Porotchkin * Clobber list : x1, x2, x3 3919112b79SKonstantin Porotchkin * ----------------------------------------------- 4019112b79SKonstantin Porotchkin */ 41d7c4420cSKonstantin Porotchkinfunc console_a3700_core_init 4219112b79SKonstantin Porotchkin /* Check the input base address */ 4319112b79SKonstantin Porotchkin cbz x0, init_fail 4419112b79SKonstantin Porotchkin /* Check baud rate and uart clock for sanity */ 4519112b79SKonstantin Porotchkin cbz w1, init_fail 4619112b79SKonstantin Porotchkin cbz w2, init_fail 4719112b79SKonstantin Porotchkin 4819112b79SKonstantin Porotchkin /* Program the baudrate */ 4919112b79SKonstantin Porotchkin /* Divisor = Uart clock / (16 * baudrate) */ 5019112b79SKonstantin Porotchkin lsl w2, w2, #4 5119112b79SKonstantin Porotchkin udiv w2, w1, w2 5219112b79SKonstantin Porotchkin and w2, w2, #0x3ff 5319112b79SKonstantin Porotchkin 5419112b79SKonstantin Porotchkin ldr w3, [x0, #UART_BAUD_REG] 5519112b79SKonstantin Porotchkin bic w3, w3, 0x3ff 5619112b79SKonstantin Porotchkin orr w3, w3, w2 5719112b79SKonstantin Porotchkin str w3, [x0, #UART_BAUD_REG]/* set baud rate divisor */ 5819112b79SKonstantin Porotchkin 5919112b79SKonstantin Porotchkin /* Set UART to default 16X scheme */ 6019112b79SKonstantin Porotchkin mov w3, #0 6119112b79SKonstantin Porotchkin str w3, [x0, #UART_POSSR_REG] 6219112b79SKonstantin Porotchkin 6319112b79SKonstantin Porotchkin /* 6419112b79SKonstantin Porotchkin * Wait for the TX FIFO to be empty. If wait for 20ms, the TX FIFO is 6519112b79SKonstantin Porotchkin * still not empty, TX FIFO will reset by all means. 6619112b79SKonstantin Porotchkin */ 6719112b79SKonstantin Porotchkin mov w1, #20 /* max time out 20ms */ 6819112b79SKonstantin Porotchkin2: 6919112b79SKonstantin Porotchkin /* Check whether TX FIFO is empty */ 7019112b79SKonstantin Porotchkin ldr w3, [x0, #UART_STATUS_REG] 7119112b79SKonstantin Porotchkin and w3, w3, #UARTLSR_TXFIFOEMPTY 7219112b79SKonstantin Porotchkin cmp w3, #0 7319112b79SKonstantin Porotchkin b.ne 4f 7419112b79SKonstantin Porotchkin 7519112b79SKonstantin Porotchkin /* Delay */ 7619112b79SKonstantin Porotchkin mov w2, #30000 7719112b79SKonstantin Porotchkin3: 7819112b79SKonstantin Porotchkin sub w2, w2, #1 7919112b79SKonstantin Porotchkin cmp w2, #0 8019112b79SKonstantin Porotchkin b.ne 3b 8119112b79SKonstantin Porotchkin 8219112b79SKonstantin Porotchkin /* Check whether 10ms is waited */ 8319112b79SKonstantin Porotchkin sub w1, w1, #1 8419112b79SKonstantin Porotchkin cmp w1, #0 8519112b79SKonstantin Porotchkin b.ne 2b 8619112b79SKonstantin Porotchkin 8719112b79SKonstantin Porotchkin4: 8819112b79SKonstantin Porotchkin /* Reset FIFO */ 8919112b79SKonstantin Porotchkin mov w3, #UART_CTRL_RXFIFO_RESET 9019112b79SKonstantin Porotchkin orr w3, w3, #UART_CTRL_TXFIFO_RESET 9119112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 9219112b79SKonstantin Porotchkin 9319112b79SKonstantin Porotchkin /* Delay */ 9419112b79SKonstantin Porotchkin mov w2, #2000 9519112b79SKonstantin Porotchkin1: 9619112b79SKonstantin Porotchkin sub w2, w2, #1 9719112b79SKonstantin Porotchkin cmp w2, #0 9819112b79SKonstantin Porotchkin b.ne 1b 9919112b79SKonstantin Porotchkin 10019112b79SKonstantin Porotchkin /* No Parity, 1 Stop */ 10119112b79SKonstantin Porotchkin mov w3, #0 10219112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 10319112b79SKonstantin Porotchkin 10419112b79SKonstantin Porotchkin mov w0, #1 10519112b79SKonstantin Porotchkin ret 10619112b79SKonstantin Porotchkininit_fail: 10719112b79SKonstantin Porotchkin mov w0, #0 10819112b79SKonstantin Porotchkin ret 109d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_init 110d7c4420cSKonstantin Porotchkin 111d7c4420cSKonstantin Porotchkin .globl console_a3700_register 112d7c4420cSKonstantin Porotchkin 113d7c4420cSKonstantin Porotchkin /* ----------------------------------------------- 114d7c4420cSKonstantin Porotchkin * int console_a3700_register(console_16550_t *console, 115d7c4420cSKonstantin Porotchkin uintptr_t base, uint32_t clk, uint32_t baud) 116d7c4420cSKonstantin Porotchkin * Function to initialize and register a new a3700 117d7c4420cSKonstantin Porotchkin * console. Storage passed in for the console struct 118d7c4420cSKonstantin Porotchkin * *must* be persistent (i.e. not from the stack). 119d7c4420cSKonstantin Porotchkin * In: x0 - UART register base address 120d7c4420cSKonstantin Porotchkin * w1 - UART clock in Hz 121d7c4420cSKonstantin Porotchkin * w2 - Baud rate 122d7c4420cSKonstantin Porotchkin * x3 - pointer to empty console_a3700_t struct 123d7c4420cSKonstantin Porotchkin * Out: return 1 on success, 0 on error 124d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1, x2, x6, x7, x14 125d7c4420cSKonstantin Porotchkin * ----------------------------------------------- 126d7c4420cSKonstantin Porotchkin */ 127d7c4420cSKonstantin Porotchkinfunc console_a3700_register 128d7c4420cSKonstantin Porotchkin mov x7, x30 129d7c4420cSKonstantin Porotchkin mov x6, x3 130d7c4420cSKonstantin Porotchkin cbz x6, register_fail 131d7c4420cSKonstantin Porotchkin str x0, [x6, #CONSOLE_T_A3700_BASE] 132d7c4420cSKonstantin Porotchkin 133d7c4420cSKonstantin Porotchkin bl console_a3700_core_init 134d7c4420cSKonstantin Porotchkin cbz x0, register_fail 135d7c4420cSKonstantin Porotchkin 136d7c4420cSKonstantin Porotchkin mov x0, x6 137d7c4420cSKonstantin Porotchkin mov x30, x7 138d7c4420cSKonstantin Porotchkin finish_console_register a3700, putc=1, getc=1, flush=1 139d7c4420cSKonstantin Porotchkin 140d7c4420cSKonstantin Porotchkinregister_fail: 141d7c4420cSKonstantin Porotchkin ret x7 142d7c4420cSKonstantin Porotchkinendfunc console_a3700_register 14319112b79SKonstantin Porotchkin 14419112b79SKonstantin Porotchkin /* -------------------------------------------------------- 145d7c4420cSKonstantin Porotchkin * int console_a3700_core_putc(int c, unsigned int base_addr) 14619112b79SKonstantin Porotchkin * Function to output a character over the console. It 14719112b79SKonstantin Porotchkin * returns the character printed on success or -1 on error. 14819112b79SKonstantin Porotchkin * In : w0 - character to be printed 14919112b79SKonstantin Porotchkin * x1 - console base address 15019112b79SKonstantin Porotchkin * Out : return -1 on error else return character. 15119112b79SKonstantin Porotchkin * Clobber list : x2 15219112b79SKonstantin Porotchkin * -------------------------------------------------------- 15319112b79SKonstantin Porotchkin */ 154d7c4420cSKonstantin Porotchkinfunc console_a3700_core_putc 15519112b79SKonstantin Porotchkin /* Check the input parameter */ 15619112b79SKonstantin Porotchkin cbz x1, putc_error 15719112b79SKonstantin Porotchkin 15819112b79SKonstantin Porotchkin /* Prepend '\r' to '\n' */ 15919112b79SKonstantin Porotchkin cmp w0, #0xA 16019112b79SKonstantin Porotchkin b.ne 2f 16119112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 16219112b79SKonstantin Porotchkin1: ldr w2, [x1, #UART_STATUS_REG] 16319112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 16419112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 16519112b79SKonstantin Porotchkin b.eq 1b 16619112b79SKonstantin Porotchkin mov w2, #0xD /* '\r' */ 16719112b79SKonstantin Porotchkin str w2, [x1, #UART_TX_REG] 16819112b79SKonstantin Porotchkin 16919112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 17019112b79SKonstantin Porotchkin2: ldr w2, [x1, #UART_STATUS_REG] 17119112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 17219112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 17319112b79SKonstantin Porotchkin b.eq 2b 17419112b79SKonstantin Porotchkin str w0, [x1, #UART_TX_REG] 17519112b79SKonstantin Porotchkin ret 17619112b79SKonstantin Porotchkinputc_error: 17719112b79SKonstantin Porotchkin mov w0, #-1 17819112b79SKonstantin Porotchkin ret 179d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_putc 180d7c4420cSKonstantin Porotchkin 181d7c4420cSKonstantin Porotchkin /* -------------------------------------------------------- 182d7c4420cSKonstantin Porotchkin * int console_a3700_putc(int c, console_a3700_t *console) 183d7c4420cSKonstantin Porotchkin * Function to output a character over the console. It 184d7c4420cSKonstantin Porotchkin * returns the character printed on success or -1 on error. 185d7c4420cSKonstantin Porotchkin * In : w0 - character to be printed 186d7c4420cSKonstantin Porotchkin * x1 - pointer to console_t structure 187d7c4420cSKonstantin Porotchkin * Out : return -1 on error else return character. 188d7c4420cSKonstantin Porotchkin * Clobber list : x2 189d7c4420cSKonstantin Porotchkin * -------------------------------------------------------- 190d7c4420cSKonstantin Porotchkin */ 191d7c4420cSKonstantin Porotchkinfunc console_a3700_putc 192d7c4420cSKonstantin Porotchkin ldr x1, [x1, #CONSOLE_T_A3700_BASE] 193d7c4420cSKonstantin Porotchkin b console_a3700_core_putc 194d7c4420cSKonstantin Porotchkinendfunc console_a3700_putc 19519112b79SKonstantin Porotchkin 19619112b79SKonstantin Porotchkin /* --------------------------------------------- 197d7c4420cSKonstantin Porotchkin * int console_a3700_core_getc(void) 19819112b79SKonstantin Porotchkin * Function to get a character from the console. 19919112b79SKonstantin Porotchkin * It returns the character grabbed on success 20019112b79SKonstantin Porotchkin * or -1 on error. 20119112b79SKonstantin Porotchkin * In : w0 - console base address 20219112b79SKonstantin Porotchkin * Out : return -1 on error else return character. 20319112b79SKonstantin Porotchkin * Clobber list : x0, x1 20419112b79SKonstantin Porotchkin * --------------------------------------------- 20519112b79SKonstantin Porotchkin */ 206d7c4420cSKonstantin Porotchkinfunc console_a3700_core_getc 20719112b79SKonstantin Porotchkin mov w0, #-1 20819112b79SKonstantin Porotchkin ret 209d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_getc 21019112b79SKonstantin Porotchkin 21119112b79SKonstantin Porotchkin /* --------------------------------------------- 212d7c4420cSKonstantin Porotchkin * int console_a3700_getc(console_a3700_t *console) 213d7c4420cSKonstantin Porotchkin * Function to get a character from the console. 214d7c4420cSKonstantin Porotchkin * It returns the character grabbed on success 215d7c4420cSKonstantin Porotchkin * or -1 on if no character is available. 216d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 217d7c4420cSKonstantin Porotchkin * Out : w0 - character if available, else -1 218d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 219d7c4420cSKonstantin Porotchkin * --------------------------------------------- 220d7c4420cSKonstantin Porotchkin */ 221d7c4420cSKonstantin Porotchkinfunc console_a3700_getc 222d7c4420cSKonstantin Porotchkin ldr x0, [x0, #CONSOLE_T_A3700_BASE] 223d7c4420cSKonstantin Porotchkin b console_a3700_core_getc 224d7c4420cSKonstantin Porotchkinendfunc console_a3700_getc 225d7c4420cSKonstantin Porotchkin 226d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 227d7c4420cSKonstantin Porotchkin * int console_a3700_core_flush(uintptr_t base_addr) 22819112b79SKonstantin Porotchkin * Function to force a write of all buffered 22919112b79SKonstantin Porotchkin * data that hasn't been output. 23019112b79SKonstantin Porotchkin * In : x0 - console base address 23119112b79SKonstantin Porotchkin * Out : return -1 on error else return 0. 23219112b79SKonstantin Porotchkin * Clobber list : x0, x1 23319112b79SKonstantin Porotchkin * --------------------------------------------- 23419112b79SKonstantin Porotchkin */ 235d7c4420cSKonstantin Porotchkinfunc console_a3700_core_flush 23619112b79SKonstantin Porotchkin mov w0, #0 23719112b79SKonstantin Porotchkin ret 238d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_flush 239d7c4420cSKonstantin Porotchkin 240d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 241d7c4420cSKonstantin Porotchkin * int console_a3700_flush(console_a3700_t *console) 242d7c4420cSKonstantin Porotchkin * Function to force a write of all buffered 243d7c4420cSKonstantin Porotchkin * data that hasn't been output. 244d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 245d7c4420cSKonstantin Porotchkin * Out : return -1 on error else return 0. 246d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 247d7c4420cSKonstantin Porotchkin * --------------------------------------------- 248d7c4420cSKonstantin Porotchkin */ 249d7c4420cSKonstantin Porotchkinfunc console_a3700_flush 250d7c4420cSKonstantin Porotchkin ldr x0, [x0, #CONSOLE_T_A3700_BASE] 251d7c4420cSKonstantin Porotchkin b console_a3700_core_flush 252d7c4420cSKonstantin Porotchkinendfunc console_a3700_flush 253d7c4420cSKonstantin Porotchkin 254