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: 720ee80f35SPali Rohár /* Reset UART via North Bridge Peripheral */ 730ee80f35SPali Rohár mov_imm x4, MVEBU_NB_RESET_REG 740ee80f35SPali Rohár ldr w3, [x4] 750ee80f35SPali Rohár bic w3, w3, #MVEBU_NB_RESET_UART_N 760ee80f35SPali Rohár str w3, [x4] 770ee80f35SPali Rohár orr w3, w3, #MVEBU_NB_RESET_UART_N 780ee80f35SPali Rohár str w3, [x4] 790ee80f35SPali Rohár 8019112b79SKonstantin Porotchkin /* Reset FIFO */ 8119112b79SKonstantin Porotchkin mov w3, #UART_CTRL_RXFIFO_RESET 8219112b79SKonstantin Porotchkin orr w3, w3, #UART_CTRL_TXFIFO_RESET 8319112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 8419112b79SKonstantin Porotchkin 8519112b79SKonstantin Porotchkin /* Delay */ 867c85a757SPali Rohár mov w3, #2000 8719112b79SKonstantin Porotchkin1: 887c85a757SPali Rohár sub w3, w3, #1 897c85a757SPali Rohár cmp w3, #0 9019112b79SKonstantin Porotchkin b.ne 1b 9119112b79SKonstantin Porotchkin 9215546dbfSPali Rohár /* Program the baudrate */ 9315546dbfSPali Rohár /* Divisor = Round(Uartclock / (16 * baudrate)) */ 9415546dbfSPali Rohár lsl w2, w2, #4 9515546dbfSPali Rohár add w1, w1, w2, lsr #1 9615546dbfSPali Rohár udiv w2, w1, w2 9715546dbfSPali Rohár and w2, w2, #0x3ff /* clear all other bits to use default clock */ 9815546dbfSPali Rohár 9915546dbfSPali Rohár str w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */ 10015546dbfSPali Rohár 10115546dbfSPali Rohár /* Set UART to default 16X scheme */ 10215546dbfSPali Rohár mov w3, #0 10315546dbfSPali Rohár str w3, [x0, #UART_POSSR_REG] 10415546dbfSPali Rohár 10519112b79SKonstantin Porotchkin /* No Parity, 1 Stop */ 10619112b79SKonstantin Porotchkin mov w3, #0 10719112b79SKonstantin Porotchkin str w3, [x0, #UART_CTRL_REG] 10819112b79SKonstantin Porotchkin 10919112b79SKonstantin Porotchkin mov w0, #1 11019112b79SKonstantin Porotchkin ret 11119112b79SKonstantin Porotchkininit_fail: 11219112b79SKonstantin Porotchkin mov w0, #0 11319112b79SKonstantin Porotchkin ret 114d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_init 115d7c4420cSKonstantin Porotchkin 116d7c4420cSKonstantin Porotchkin .globl console_a3700_register 117d7c4420cSKonstantin Porotchkin 118d7c4420cSKonstantin Porotchkin /* ----------------------------------------------- 1193968bc08SAndre Przywara * int console_a3700_register(console_t *console, 120d7c4420cSKonstantin Porotchkin uintptr_t base, uint32_t clk, uint32_t baud) 121d7c4420cSKonstantin Porotchkin * Function to initialize and register a new a3700 122d7c4420cSKonstantin Porotchkin * console. Storage passed in for the console struct 123d7c4420cSKonstantin Porotchkin * *must* be persistent (i.e. not from the stack). 124d7c4420cSKonstantin Porotchkin * In: x0 - UART register base address 125d7c4420cSKonstantin Porotchkin * w1 - UART clock in Hz 126d7c4420cSKonstantin Porotchkin * w2 - Baud rate 1273968bc08SAndre Przywara * x3 - pointer to empty console_t struct 128d7c4420cSKonstantin Porotchkin * Out: return 1 on success, 0 on error 1297c85a757SPali Rohár * Clobber list : x0, x1, x2, x3, x4, x6, x7, x14 130d7c4420cSKonstantin Porotchkin * ----------------------------------------------- 131d7c4420cSKonstantin Porotchkin */ 132d7c4420cSKonstantin Porotchkinfunc console_a3700_register 133d7c4420cSKonstantin Porotchkin mov x7, x30 134d7c4420cSKonstantin Porotchkin mov x6, x3 135d7c4420cSKonstantin Porotchkin cbz x6, register_fail 1363968bc08SAndre Przywara str x0, [x6, #CONSOLE_T_BASE] 137d7c4420cSKonstantin Porotchkin 138d7c4420cSKonstantin Porotchkin bl console_a3700_core_init 139d7c4420cSKonstantin Porotchkin cbz x0, register_fail 140d7c4420cSKonstantin Porotchkin 141d7c4420cSKonstantin Porotchkin mov x0, x6 142d7c4420cSKonstantin Porotchkin mov x30, x7 143*85bebe18SSandrine Bailleux finish_console_register a3700, putc=1, getc=ENABLE_CONSOLE_GETC, flush=1 144d7c4420cSKonstantin Porotchkin 145d7c4420cSKonstantin Porotchkinregister_fail: 146d7c4420cSKonstantin Porotchkin ret x7 147d7c4420cSKonstantin Porotchkinendfunc console_a3700_register 14819112b79SKonstantin Porotchkin 14919112b79SKonstantin Porotchkin /* -------------------------------------------------------- 150d7c4420cSKonstantin Porotchkin * int console_a3700_core_putc(int c, unsigned int base_addr) 15119112b79SKonstantin Porotchkin * Function to output a character over the console. It 15219112b79SKonstantin Porotchkin * returns the character printed on success or -1 on error. 15319112b79SKonstantin Porotchkin * In : w0 - character to be printed 15419112b79SKonstantin Porotchkin * x1 - console base address 15519112b79SKonstantin Porotchkin * Out : return -1 on error else return character. 15619112b79SKonstantin Porotchkin * Clobber list : x2 15719112b79SKonstantin Porotchkin * -------------------------------------------------------- 15819112b79SKonstantin Porotchkin */ 159d7c4420cSKonstantin Porotchkinfunc console_a3700_core_putc 16019112b79SKonstantin Porotchkin /* Check the input parameter */ 16119112b79SKonstantin Porotchkin cbz x1, putc_error 16219112b79SKonstantin Porotchkin 16319112b79SKonstantin Porotchkin /* Prepend '\r' to '\n' */ 16419112b79SKonstantin Porotchkin cmp w0, #0xA 16519112b79SKonstantin Porotchkin b.ne 2f 16619112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 16719112b79SKonstantin Porotchkin1: ldr w2, [x1, #UART_STATUS_REG] 16819112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 16919112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 17019112b79SKonstantin Porotchkin b.eq 1b 17119112b79SKonstantin Porotchkin mov w2, #0xD /* '\r' */ 17219112b79SKonstantin Porotchkin str w2, [x1, #UART_TX_REG] 17319112b79SKonstantin Porotchkin 17419112b79SKonstantin Porotchkin /* Check if the transmit FIFO is full */ 17519112b79SKonstantin Porotchkin2: ldr w2, [x1, #UART_STATUS_REG] 17619112b79SKonstantin Porotchkin and w2, w2, #UARTLSR_TXFIFOFULL 17719112b79SKonstantin Porotchkin cmp w2, #UARTLSR_TXFIFOFULL 17819112b79SKonstantin Porotchkin b.eq 2b 17919112b79SKonstantin Porotchkin str w0, [x1, #UART_TX_REG] 18019112b79SKonstantin Porotchkin ret 18119112b79SKonstantin Porotchkinputc_error: 18219112b79SKonstantin Porotchkin mov w0, #-1 18319112b79SKonstantin Porotchkin ret 184d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_putc 185d7c4420cSKonstantin Porotchkin 186d7c4420cSKonstantin Porotchkin /* -------------------------------------------------------- 1873968bc08SAndre Przywara * int console_a3700_putc(int c, console_t *console) 188d7c4420cSKonstantin Porotchkin * Function to output a character over the console. It 189d7c4420cSKonstantin Porotchkin * returns the character printed on success or -1 on error. 190d7c4420cSKonstantin Porotchkin * In : w0 - character to be printed 191d7c4420cSKonstantin Porotchkin * x1 - pointer to console_t structure 192d7c4420cSKonstantin Porotchkin * Out : return -1 on error else return character. 193d7c4420cSKonstantin Porotchkin * Clobber list : x2 194d7c4420cSKonstantin Porotchkin * -------------------------------------------------------- 195d7c4420cSKonstantin Porotchkin */ 196d7c4420cSKonstantin Porotchkinfunc console_a3700_putc 1973968bc08SAndre Przywara ldr x1, [x1, #CONSOLE_T_BASE] 198d7c4420cSKonstantin Porotchkin b console_a3700_core_putc 199d7c4420cSKonstantin Porotchkinendfunc console_a3700_putc 20019112b79SKonstantin Porotchkin 20119112b79SKonstantin Porotchkin /* --------------------------------------------- 202d7c4420cSKonstantin Porotchkin * int console_a3700_core_getc(void) 20319112b79SKonstantin Porotchkin * Function to get a character from the console. 20419112b79SKonstantin Porotchkin * It returns the character grabbed on success 20574867756SPali Rohár * or -1 if no character is available. 20619112b79SKonstantin Porotchkin * In : w0 - console base address 20774867756SPali Rohár * Out : w0 - character if available, else -1 20819112b79SKonstantin Porotchkin * Clobber list : x0, x1 20919112b79SKonstantin Porotchkin * --------------------------------------------- 21019112b79SKonstantin Porotchkin */ 211d7c4420cSKonstantin Porotchkinfunc console_a3700_core_getc 21274867756SPali Rohár /* Check if there is a pending character */ 21374867756SPali Rohár ldr w1, [x0, #UART_STATUS_REG] 21474867756SPali Rohár and w1, w1, #UARTLSR_RXRDY 21574867756SPali Rohár cmp w1, #UARTLSR_RXRDY 21674867756SPali Rohár b.ne getc_no_char 21774867756SPali Rohár ldr w0, [x0, #UART_RX_REG] 21874867756SPali Rohár and w0, w0, #0xff 21974867756SPali Rohár ret 22074867756SPali Rohárgetc_no_char: 22174867756SPali Rohár mov w0, #ERROR_NO_PENDING_CHAR 22219112b79SKonstantin Porotchkin ret 223d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_getc 22419112b79SKonstantin Porotchkin 22519112b79SKonstantin Porotchkin /* --------------------------------------------- 2263968bc08SAndre Przywara * int console_a3700_getc(console_t *console) 227d7c4420cSKonstantin Porotchkin * Function to get a character from the console. 228d7c4420cSKonstantin Porotchkin * It returns the character grabbed on success 229d7c4420cSKonstantin Porotchkin * or -1 on if no character is available. 230d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 231d7c4420cSKonstantin Porotchkin * Out : w0 - character if available, else -1 232d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 233d7c4420cSKonstantin Porotchkin * --------------------------------------------- 234d7c4420cSKonstantin Porotchkin */ 235d7c4420cSKonstantin Porotchkinfunc console_a3700_getc 2363968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 237d7c4420cSKonstantin Porotchkin b console_a3700_core_getc 238d7c4420cSKonstantin Porotchkinendfunc console_a3700_getc 239d7c4420cSKonstantin Porotchkin 240d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 241831b0e98SJimmy Brisson * void console_a3700_core_flush(uintptr_t base_addr) 24219112b79SKonstantin Porotchkin * Function to force a write of all buffered 24319112b79SKonstantin Porotchkin * data that hasn't been output. 24419112b79SKonstantin Porotchkin * In : x0 - console base address 245831b0e98SJimmy Brisson * Out : void. 24619112b79SKonstantin Porotchkin * Clobber list : x0, x1 24719112b79SKonstantin Porotchkin * --------------------------------------------- 24819112b79SKonstantin Porotchkin */ 249d7c4420cSKonstantin Porotchkinfunc console_a3700_core_flush 250b8e637f4SPali Rohár /* Wait for the TX (THR and TSR) to be empty */ 251e63e4140SPali Rohár1: ldr w1, [x0, #UART_STATUS_REG] 252b8e637f4SPali Rohár and w1, w1, #UARTLSR_TXEMPTY 253b8e637f4SPali Rohár cmp w1, #UARTLSR_TXEMPTY 254e63e4140SPali Rohár b.ne 1b 25519112b79SKonstantin Porotchkin ret 256d7c4420cSKonstantin Porotchkinendfunc console_a3700_core_flush 257d7c4420cSKonstantin Porotchkin 258d7c4420cSKonstantin Porotchkin /* --------------------------------------------- 259831b0e98SJimmy Brisson * void console_a3700_flush(console_t *console) 260d7c4420cSKonstantin Porotchkin * Function to force a write of all buffered 261d7c4420cSKonstantin Porotchkin * data that hasn't been output. 262d7c4420cSKonstantin Porotchkin * In : x0 - pointer to console_t structure 263831b0e98SJimmy Brisson * Out : void. 264d7c4420cSKonstantin Porotchkin * Clobber list : x0, x1 265d7c4420cSKonstantin Porotchkin * --------------------------------------------- 266d7c4420cSKonstantin Porotchkin */ 267d7c4420cSKonstantin Porotchkinfunc console_a3700_flush 2683968bc08SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 269d7c4420cSKonstantin Porotchkin b console_a3700_core_flush 270d7c4420cSKonstantin Porotchkinendfunc console_a3700_flush 271d7c4420cSKonstantin Porotchkin 272