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 */ 48*66a77528SPali Rohár /* Divisor = Round(Uartclock / (16 * baudrate)) */ 4919112b79SKonstantin Porotchkin lsl w2, w2, #4 50*66a77528SPali Rohár add w1, w1, w2, lsr #1 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 /* 640d06b058SPali Rohár * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is 6519112b79SKonstantin Porotchkin * still not empty, TX FIFO will reset by all means. 6619112b79SKonstantin Porotchkin */ 670d06b058SPali Rohár mov w1, #30 /* max time out 30 * 100 us */ 6819112b79SKonstantin Porotchkin2: 69b8e637f4SPali Rohár /* Check whether TX (THR and TSR) is empty */ 7019112b79SKonstantin Porotchkin ldr w3, [x0, #UART_STATUS_REG] 71b8e637f4SPali Rohár and w3, w3, #UARTLSR_TXEMPTY 7219112b79SKonstantin Porotchkin cmp w3, #0 7319112b79SKonstantin Porotchkin b.ne 4f 7419112b79SKonstantin Porotchkin 7519112b79SKonstantin Porotchkin /* Delay */ 7698641515SPali Rohár mov w2, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */ 7719112b79SKonstantin Porotchkin3: 7819112b79SKonstantin Porotchkin sub w2, w2, #1 7919112b79SKonstantin Porotchkin cmp w2, #0 8019112b79SKonstantin Porotchkin b.ne 3b 8119112b79SKonstantin Porotchkin 82ab1fe188SPali Rohár /* Check whether wait timeout expired */ 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 /* ----------------------------------------------- 1143968bc08SAndre Przywara * int console_a3700_register(console_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 1223968bc08SAndre Przywara * x3 - pointer to empty console_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 1313968bc08SAndre Przywara str x0, [x6, #CONSOLE_T_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 /* -------------------------------------------------------- 1823968bc08SAndre Przywara * int console_a3700_putc(int c, console_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 1923968bc08SAndre Przywara ldr x1, [x1, #CONSOLE_T_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 20074867756SPali Rohár * or -1 if no character is available. 20119112b79SKonstantin Porotchkin * In : w0 - console base address 20274867756SPali Rohár * Out : w0 - character if available, else -1 20319112b79SKonstantin Porotchkin * Clobber list : x0, x1 20419112b79SKonstantin Porotchkin * --------------------------------------------- 20519112b79SKonstantin Porotchkin */ 206d7c4420cSKonstantin Porotchkinfunc console_a3700_core_getc 20774867756SPali Rohár /* Check if there is a pending character */ 20874867756SPali Rohár ldr w1, [x0, #UART_STATUS_REG] 20974867756SPali Rohár and w1, w1, #UARTLSR_RXRDY 21074867756SPali Rohár cmp w1, #UARTLSR_RXRDY 21174867756SPali Rohár b.ne getc_no_char 21274867756SPali Rohár ldr w0, [x0, #UART_RX_REG] 21374867756SPali Rohár and w0, w0, #0xff 21474867756SPali Rohár ret 21574867756SPali Rohárgetc_no_char: 21674867756SPali Rohár mov w0, #ERROR_NO_PENDING_CHAR 21719112b79SKonstantin Porotchkin ret 218d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_getc 21919112b79SKonstantin Porotchkin 22019112b79SKonstantin Porotchkin /* --------------------------------------------- 2213968bc08SAndre Przywara * int console_a3700_getc(console_t *console) 222d7c4420cSKonstantin Porotchkin * Function to get a character from the console. 223d7c4420cSKonstantin Porotchkin * It returns the character grabbed on success 224d7c4420cSKonstantin Porotchkin * or -1 on if no character is available. 225d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 226d7c4420cSKonstantin Porotchkin * Out : w0 - character if available, else -1 227d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 228d7c4420cSKonstantin Porotchkin * --------------------------------------------- 229d7c4420cSKonstantin Porotchkin */ 230d7c4420cSKonstantin Porotchkinfunc console_a3700_getc 2313968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 232d7c4420cSKonstantin Porotchkin b console_a3700_core_getc 233d7c4420cSKonstantin Porotchkinendfunc console_a3700_getc 234d7c4420cSKonstantin Porotchkin 235d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 236831b0e98SJimmy Brisson * void console_a3700_core_flush(uintptr_t base_addr) 23719112b79SKonstantin Porotchkin * Function to force a write of all buffered 23819112b79SKonstantin Porotchkin * data that hasn't been output. 23919112b79SKonstantin Porotchkin * In : x0 - console base address 240831b0e98SJimmy Brisson * Out : void. 24119112b79SKonstantin Porotchkin * Clobber list : x0, x1 24219112b79SKonstantin Porotchkin * --------------------------------------------- 24319112b79SKonstantin Porotchkin */ 244d7c4420cSKonstantin Porotchkinfunc console_a3700_core_flush 245b8e637f4SPali Rohár /* Wait for the TX (THR and TSR) to be empty */ 246e63e4140SPali Rohár1: ldr w1, [x0, #UART_STATUS_REG] 247b8e637f4SPali Rohár and w1, w1, #UARTLSR_TXEMPTY 248b8e637f4SPali Rohár cmp w1, #UARTLSR_TXEMPTY 249e63e4140SPali Rohár b.ne 1b 25019112b79SKonstantin Porotchkin ret 251d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_flush 252d7c4420cSKonstantin Porotchkin 253d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 254831b0e98SJimmy Brisson * void console_a3700_flush(console_t *console) 255d7c4420cSKonstantin Porotchkin * Function to force a write of all buffered 256d7c4420cSKonstantin Porotchkin * data that hasn't been output. 257d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 258831b0e98SJimmy Brisson * Out : void. 259d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 260d7c4420cSKonstantin Porotchkin * --------------------------------------------- 261d7c4420cSKonstantin Porotchkin */ 262d7c4420cSKonstantin Porotchkinfunc console_a3700_flush 2633968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 264d7c4420cSKonstantin Porotchkin b console_a3700_core_flush 265d7c4420cSKonstantin Porotchkinendfunc console_a3700_flush 266d7c4420cSKonstantin Porotchkin 267