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 3719112b79SKonstantin Porotchkin * Clobber list : x1, x2, x3 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 /* Program the baudrate */ 4819112b79SKonstantin Porotchkin /* Divisor = Uart clock / (16 * baudrate) */ 4919112b79SKonstantin Porotchkin lsl w2, w2, #4 5019112b79SKonstantin Porotchkin udiv w2, w1, w2 5119112b79SKonstantin Porotchkin and w2, w2, #0x3ff 5219112b79SKonstantin Porotchkin 5319112b79SKonstantin Porotchkin ldr w3, [x0, #UART_BAUD_REG] 5419112b79SKonstantin Porotchkin bic w3, w3, 0x3ff 5519112b79SKonstantin Porotchkin orr w3, w3, w2 5619112b79SKonstantin Porotchkin str w3, [x0, #UART_BAUD_REG]/* set baud rate divisor */ 5719112b79SKonstantin Porotchkin 5819112b79SKonstantin Porotchkin /* Set UART to default 16X scheme */ 5919112b79SKonstantin Porotchkin mov w3, #0 6019112b79SKonstantin Porotchkin str w3, [x0, #UART_POSSR_REG] 6119112b79SKonstantin Porotchkin 6219112b79SKonstantin Porotchkin /* 63*0d06b058SPali Rohár * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is 6419112b79SKonstantin Porotchkin * still not empty, TX FIFO will reset by all means. 6519112b79SKonstantin Porotchkin */ 66*0d06b058SPali Rohár mov w1, #30 /* max time out 30 * 100 us */ 6719112b79SKonstantin Porotchkin2: 68b8e637f4SPali Rohár /* Check whether TX (THR and TSR) is empty */ 6919112b79SKonstantin Porotchkin ldr w3, [x0, #UART_STATUS_REG] 70b8e637f4SPali Rohár and w3, w3, #UARTLSR_TXEMPTY 7119112b79SKonstantin Porotchkin cmp w3, #0 7219112b79SKonstantin Porotchkin b.ne 4f 7319112b79SKonstantin Porotchkin 7419112b79SKonstantin Porotchkin /* Delay */ 7598641515SPali Rohár mov w2, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */ 7619112b79SKonstantin Porotchkin3: 7719112b79SKonstantin Porotchkin sub w2, w2, #1 7819112b79SKonstantin Porotchkin cmp w2, #0 7919112b79SKonstantin Porotchkin b.ne 3b 8019112b79SKonstantin Porotchkin 81ab1fe188SPali Rohár /* Check whether wait timeout expired */ 8219112b79SKonstantin Porotchkin sub w1, w1, #1 8319112b79SKonstantin Porotchkin cmp w1, #0 8419112b79SKonstantin Porotchkin b.ne 2b 8519112b79SKonstantin Porotchkin 8619112b79SKonstantin Porotchkin4: 8719112b79SKonstantin Porotchkin /* Reset FIFO */ 8819112b79SKonstantin Porotchkin mov w3, #UART_CTRL_RXFIFO_RESET 8919112b79SKonstantin Porotchkin orr w3, w3, #UART_CTRL_TXFIFO_RESET 9019112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 9119112b79SKonstantin Porotchkin 9219112b79SKonstantin Porotchkin /* Delay */ 9319112b79SKonstantin Porotchkin mov w2, #2000 9419112b79SKonstantin Porotchkin1: 9519112b79SKonstantin Porotchkin sub w2, w2, #1 9619112b79SKonstantin Porotchkin cmp w2, #0 9719112b79SKonstantin Porotchkin b.ne 1b 9819112b79SKonstantin Porotchkin 9919112b79SKonstantin Porotchkin /* No Parity, 1 Stop */ 10019112b79SKonstantin Porotchkin mov w3, #0 10119112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 10219112b79SKonstantin Porotchkin 10319112b79SKonstantin Porotchkin mov w0, #1 10419112b79SKonstantin Porotchkin ret 10519112b79SKonstantin Porotchkininit_fail: 10619112b79SKonstantin Porotchkin mov w0, #0 10719112b79SKonstantin Porotchkin ret 108d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_init 109d7c4420cSKonstantin Porotchkin 110d7c4420cSKonstantin Porotchkin .globl console_a3700_register 111d7c4420cSKonstantin Porotchkin 112d7c4420cSKonstantin Porotchkin /* ----------------------------------------------- 1133968bc08SAndre Przywara * int console_a3700_register(console_t *console, 114d7c4420cSKonstantin Porotchkin uintptr_t base, uint32_t clk, uint32_t baud) 115d7c4420cSKonstantin Porotchkin * Function to initialize and register a new a3700 116d7c4420cSKonstantin Porotchkin * console. Storage passed in for the console struct 117d7c4420cSKonstantin Porotchkin * *must* be persistent (i.e. not from the stack). 118d7c4420cSKonstantin Porotchkin * In: x0 - UART register base address 119d7c4420cSKonstantin Porotchkin * w1 - UART clock in Hz 120d7c4420cSKonstantin Porotchkin * w2 - Baud rate 1213968bc08SAndre Przywara * x3 - pointer to empty console_t struct 122d7c4420cSKonstantin Porotchkin * Out: return 1 on success, 0 on error 123d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1, x2, x6, x7, x14 124d7c4420cSKonstantin Porotchkin * ----------------------------------------------- 125d7c4420cSKonstantin Porotchkin */ 126d7c4420cSKonstantin Porotchkinfunc console_a3700_register 127d7c4420cSKonstantin Porotchkin mov x7, x30 128d7c4420cSKonstantin Porotchkin mov x6, x3 129d7c4420cSKonstantin Porotchkin cbz x6, register_fail 1303968bc08SAndre Przywara str x0, [x6, #CONSOLE_T_BASE] 131d7c4420cSKonstantin Porotchkin 132d7c4420cSKonstantin Porotchkin bl console_a3700_core_init 133d7c4420cSKonstantin Porotchkin cbz x0, register_fail 134d7c4420cSKonstantin Porotchkin 135d7c4420cSKonstantin Porotchkin mov x0, x6 136d7c4420cSKonstantin Porotchkin mov x30, x7 137d7c4420cSKonstantin Porotchkin finish_console_register a3700, putc=1, getc=1, flush=1 138d7c4420cSKonstantin Porotchkin 139d7c4420cSKonstantin Porotchkinregister_fail: 140d7c4420cSKonstantin Porotchkin ret x7 141d7c4420cSKonstantin Porotchkinendfunc console_a3700_register 14219112b79SKonstantin Porotchkin 14319112b79SKonstantin Porotchkin /* -------------------------------------------------------- 144d7c4420cSKonstantin Porotchkin * int console_a3700_core_putc(int c, unsigned int base_addr) 14519112b79SKonstantin Porotchkin * Function to output a character over the console. It 14619112b79SKonstantin Porotchkin * returns the character printed on success or -1 on error. 14719112b79SKonstantin Porotchkin * In : w0 - character to be printed 14819112b79SKonstantin Porotchkin * x1 - console base address 14919112b79SKonstantin Porotchkin * Out : return -1 on error else return character. 15019112b79SKonstantin Porotchkin * Clobber list : x2 15119112b79SKonstantin Porotchkin * -------------------------------------------------------- 15219112b79SKonstantin Porotchkin */ 153d7c4420cSKonstantin Porotchkinfunc console_a3700_core_putc 15419112b79SKonstantin Porotchkin /* Check the input parameter */ 15519112b79SKonstantin Porotchkin cbz x1, putc_error 15619112b79SKonstantin Porotchkin 15719112b79SKonstantin Porotchkin /* Prepend '\r' to '\n' */ 15819112b79SKonstantin Porotchkin cmp w0, #0xA 15919112b79SKonstantin Porotchkin b.ne 2f 16019112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 16119112b79SKonstantin Porotchkin1: ldr w2, [x1, #UART_STATUS_REG] 16219112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 16319112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 16419112b79SKonstantin Porotchkin b.eq 1b 16519112b79SKonstantin Porotchkin mov w2, #0xD /* '\r' */ 16619112b79SKonstantin Porotchkin str w2, [x1, #UART_TX_REG] 16719112b79SKonstantin Porotchkin 16819112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 16919112b79SKonstantin Porotchkin2: ldr w2, [x1, #UART_STATUS_REG] 17019112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 17119112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 17219112b79SKonstantin Porotchkin b.eq 2b 17319112b79SKonstantin Porotchkin str w0, [x1, #UART_TX_REG] 17419112b79SKonstantin Porotchkin ret 17519112b79SKonstantin Porotchkinputc_error: 17619112b79SKonstantin Porotchkin mov w0, #-1 17719112b79SKonstantin Porotchkin ret 178d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_putc 179d7c4420cSKonstantin Porotchkin 180d7c4420cSKonstantin Porotchkin /* -------------------------------------------------------- 1813968bc08SAndre Przywara * int console_a3700_putc(int c, console_t *console) 182d7c4420cSKonstantin Porotchkin * Function to output a character over the console. It 183d7c4420cSKonstantin Porotchkin * returns the character printed on success or -1 on error. 184d7c4420cSKonstantin Porotchkin * In : w0 - character to be printed 185d7c4420cSKonstantin Porotchkin * x1 - pointer to console_t structure 186d7c4420cSKonstantin Porotchkin * Out : return -1 on error else return character. 187d7c4420cSKonstantin Porotchkin * Clobber list : x2 188d7c4420cSKonstantin Porotchkin * -------------------------------------------------------- 189d7c4420cSKonstantin Porotchkin */ 190d7c4420cSKonstantin Porotchkinfunc console_a3700_putc 1913968bc08SAndre Przywara ldr x1, [x1, #CONSOLE_T_BASE] 192d7c4420cSKonstantin Porotchkin b console_a3700_core_putc 193d7c4420cSKonstantin Porotchkinendfunc console_a3700_putc 19419112b79SKonstantin Porotchkin 19519112b79SKonstantin Porotchkin /* --------------------------------------------- 196d7c4420cSKonstantin Porotchkin * int console_a3700_core_getc(void) 19719112b79SKonstantin Porotchkin * Function to get a character from the console. 19819112b79SKonstantin Porotchkin * It returns the character grabbed on success 19974867756SPali Rohár * or -1 if no character is available. 20019112b79SKonstantin Porotchkin * In : w0 - console base address 20174867756SPali Rohár * Out : w0 - character if available, else -1 20219112b79SKonstantin Porotchkin * Clobber list : x0, x1 20319112b79SKonstantin Porotchkin * --------------------------------------------- 20419112b79SKonstantin Porotchkin */ 205d7c4420cSKonstantin Porotchkinfunc console_a3700_core_getc 20674867756SPali Rohár /* Check if there is a pending character */ 20774867756SPali Rohár ldr w1, [x0, #UART_STATUS_REG] 20874867756SPali Rohár and w1, w1, #UARTLSR_RXRDY 20974867756SPali Rohár cmp w1, #UARTLSR_RXRDY 21074867756SPali Rohár b.ne getc_no_char 21174867756SPali Rohár ldr w0, [x0, #UART_RX_REG] 21274867756SPali Rohár and w0, w0, #0xff 21374867756SPali Rohár ret 21474867756SPali Rohárgetc_no_char: 21574867756SPali Rohár mov w0, #ERROR_NO_PENDING_CHAR 21619112b79SKonstantin Porotchkin ret 217d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_getc 21819112b79SKonstantin Porotchkin 21919112b79SKonstantin Porotchkin /* --------------------------------------------- 2203968bc08SAndre Przywara * int console_a3700_getc(console_t *console) 221d7c4420cSKonstantin Porotchkin * Function to get a character from the console. 222d7c4420cSKonstantin Porotchkin * It returns the character grabbed on success 223d7c4420cSKonstantin Porotchkin * or -1 on if no character is available. 224d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 225d7c4420cSKonstantin Porotchkin * Out : w0 - character if available, else -1 226d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 227d7c4420cSKonstantin Porotchkin * --------------------------------------------- 228d7c4420cSKonstantin Porotchkin */ 229d7c4420cSKonstantin Porotchkinfunc console_a3700_getc 2303968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 231d7c4420cSKonstantin Porotchkin b console_a3700_core_getc 232d7c4420cSKonstantin Porotchkinendfunc console_a3700_getc 233d7c4420cSKonstantin Porotchkin 234d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 235831b0e98SJimmy Brisson * void console_a3700_core_flush(uintptr_t base_addr) 23619112b79SKonstantin Porotchkin * Function to force a write of all buffered 23719112b79SKonstantin Porotchkin * data that hasn't been output. 23819112b79SKonstantin Porotchkin * In : x0 - console base address 239831b0e98SJimmy Brisson * Out : void. 24019112b79SKonstantin Porotchkin * Clobber list : x0, x1 24119112b79SKonstantin Porotchkin * --------------------------------------------- 24219112b79SKonstantin Porotchkin */ 243d7c4420cSKonstantin Porotchkinfunc console_a3700_core_flush 244b8e637f4SPali Rohár /* Wait for the TX (THR and TSR) to be empty */ 245e63e4140SPali Rohár1: ldr w1, [x0, #UART_STATUS_REG] 246b8e637f4SPali Rohár and w1, w1, #UARTLSR_TXEMPTY 247b8e637f4SPali Rohár cmp w1, #UARTLSR_TXEMPTY 248e63e4140SPali Rohár b.ne 1b 24919112b79SKonstantin Porotchkin ret 250d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_flush 251d7c4420cSKonstantin Porotchkin 252d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 253831b0e98SJimmy Brisson * void console_a3700_flush(console_t *console) 254d7c4420cSKonstantin Porotchkin * Function to force a write of all buffered 255d7c4420cSKonstantin Porotchkin * data that hasn't been output. 256d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 257831b0e98SJimmy Brisson * Out : void. 258d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 259d7c4420cSKonstantin Porotchkin * --------------------------------------------- 260d7c4420cSKonstantin Porotchkin */ 261d7c4420cSKonstantin Porotchkinfunc console_a3700_flush 2623968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 263d7c4420cSKonstantin Porotchkin b console_a3700_core_flush 264d7c4420cSKonstantin Porotchkinendfunc console_a3700_flush 265d7c4420cSKonstantin Porotchkin 266