14a079c75SCarlo Caione/* 2831b0e98SJimmy Brisson * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. 34a079c75SCarlo Caione * 44a079c75SCarlo Caione * SPDX-License-Identifier: BSD-3-Clause 54a079c75SCarlo Caione */ 64a079c75SCarlo Caione 74a079c75SCarlo Caione#include <asm_macros.S> 84a079c75SCarlo Caione#include <assert_macros.S> 94a079c75SCarlo Caione#include <console_macros.S> 104a079c75SCarlo Caione#include <drivers/amlogic/meson_console.h> 114a079c75SCarlo Caione 124a079c75SCarlo Caione .globl console_meson_register 134a079c75SCarlo Caione .globl console_meson_init 144a079c75SCarlo Caione .globl console_meson_putc 154a079c75SCarlo Caione .globl console_meson_getc 164a079c75SCarlo Caione .globl console_meson_flush 174a079c75SCarlo Caione .globl console_meson_core_putc 184a079c75SCarlo Caione .globl console_meson_core_getc 194a079c75SCarlo Caione .globl console_meson_core_flush 204a079c75SCarlo Caione 214a079c75SCarlo Caione /* ----------------------------------------------- 224a079c75SCarlo Caione * Hardware definitions 234a079c75SCarlo Caione * ----------------------------------------------- 244a079c75SCarlo Caione */ 254a079c75SCarlo Caione#define MESON_WFIFO_OFFSET 0x0 264a079c75SCarlo Caione#define MESON_RFIFO_OFFSET 0x4 274a079c75SCarlo Caione#define MESON_CONTROL_OFFSET 0x8 284a079c75SCarlo Caione#define MESON_STATUS_OFFSET 0xC 294a079c75SCarlo Caione#define MESON_MISC_OFFSET 0x10 304a079c75SCarlo Caione#define MESON_REG5_OFFSET 0x14 314a079c75SCarlo Caione 324a079c75SCarlo Caione#define MESON_CONTROL_CLR_ERROR_BIT 24 334a079c75SCarlo Caione#define MESON_CONTROL_RX_RESET_BIT 23 344a079c75SCarlo Caione#define MESON_CONTROL_TX_RESET_BIT 22 354a079c75SCarlo Caione#define MESON_CONTROL_RX_ENABLE_BIT 13 364a079c75SCarlo Caione#define MESON_CONTROL_TX_ENABLE_BIT 12 374a079c75SCarlo Caione 384a079c75SCarlo Caione#define MESON_STATUS_RX_EMPTY_BIT 20 394a079c75SCarlo Caione#define MESON_STATUS_TX_FULL_BIT 21 404a079c75SCarlo Caione#define MESON_STATUS_TX_EMPTY_BIT 22 414a079c75SCarlo Caione 424a079c75SCarlo Caione#define MESON_REG5_USE_XTAL_CLK_BIT 24 434a079c75SCarlo Caione#define MESON_REG5_USE_NEW_RATE_BIT 23 444a079c75SCarlo Caione#define MESON_REG5_NEW_BAUD_RATE_MASK 0x7FFFFF 454a079c75SCarlo Caione 464a079c75SCarlo Caione /* ----------------------------------------------- 474a079c75SCarlo Caione * int console_meson_register(uintptr_t base, 484a079c75SCarlo Caione * uint32_t clk, uint32_t baud, 49489e2987SAndre Przywara * console_t *console); 504a079c75SCarlo Caione * Function to initialize and register a new MESON 514a079c75SCarlo Caione * console. Storage passed in for the console struct 524a079c75SCarlo Caione * *must* be persistent (i.e. not from the stack). 534a079c75SCarlo Caione * In: x0 - UART register base address 544a079c75SCarlo Caione * w1 - UART clock in Hz 554a079c75SCarlo Caione * w2 - Baud rate 56489e2987SAndre Przywara * x3 - pointer to empty console_t struct 574a079c75SCarlo Caione * Out: return 1 on success, 0 on error 584a079c75SCarlo Caione * Clobber list : x0, x1, x2, x6, x7, x14 594a079c75SCarlo Caione * ----------------------------------------------- 604a079c75SCarlo Caione */ 614a079c75SCarlo Caionefunc console_meson_register 624a079c75SCarlo Caione mov x7, x30 634a079c75SCarlo Caione mov x6, x3 644a079c75SCarlo Caione cbz x6, register_fail 65489e2987SAndre Przywara str x0, [x6, #CONSOLE_T_BASE] 664a079c75SCarlo Caione 674a079c75SCarlo Caione bl console_meson_init 684a079c75SCarlo Caione cbz x0, register_fail 694a079c75SCarlo Caione 704a079c75SCarlo Caione mov x0, x6 714a079c75SCarlo Caione mov x30, x7 72*85bebe18SSandrine Bailleux finish_console_register meson putc=1, getc=ENABLE_CONSOLE_GETC, flush=1 734a079c75SCarlo Caione 744a079c75SCarlo Caioneregister_fail: 754a079c75SCarlo Caione ret x7 764a079c75SCarlo Caioneendfunc console_meson_register 774a079c75SCarlo Caione 784a079c75SCarlo Caione /* ----------------------------------------------- 794a079c75SCarlo Caione * int console_meson_init(uintptr_t base_addr, 804a079c75SCarlo Caione * unsigned int uart_clk, unsigned int baud_rate) 814a079c75SCarlo Caione * Function to initialize the console without a 824a079c75SCarlo Caione * C Runtime to print debug information. This 834a079c75SCarlo Caione * function will be accessed by console_init and 844a079c75SCarlo Caione * crash reporting. 854a079c75SCarlo Caione * In: x0 - console base address 864a079c75SCarlo Caione * w1 - Uart clock in Hz 874a079c75SCarlo Caione * w2 - Baud rate 884a079c75SCarlo Caione * Out: return 1 on success else 0 on error 894a079c75SCarlo Caione * Clobber list : x0-x3 904a079c75SCarlo Caione * ----------------------------------------------- 914a079c75SCarlo Caione */ 924a079c75SCarlo Caionefunc console_meson_init 934a079c75SCarlo Caione cmp w0, #0 944a079c75SCarlo Caione beq init_fail 954a079c75SCarlo Caione mov_imm w3, 24000000 /* TODO: This only works with a 24 MHz clock. */ 964a079c75SCarlo Caione cmp w1, w3 974a079c75SCarlo Caione bne init_fail 984a079c75SCarlo Caione cmp w2, #0 994a079c75SCarlo Caione beq init_fail 1004a079c75SCarlo Caione /* Set baud rate: value = ((clock / 3) / baudrate) - 1 */ 1014a079c75SCarlo Caione mov w3, #3 1024a079c75SCarlo Caione udiv w3, w1, w3 1034a079c75SCarlo Caione udiv w3, w3, w2 1044a079c75SCarlo Caione sub w3, w3, #1 1054a079c75SCarlo Caione orr w3, w3, #((1 << MESON_REG5_USE_XTAL_CLK_BIT) | \ 1064a079c75SCarlo Caione (1 << MESON_REG5_USE_NEW_RATE_BIT)) 1074a079c75SCarlo Caione str w3, [x0, #MESON_REG5_OFFSET] 1084a079c75SCarlo Caione /* Reset UART and clear error flag */ 1094a079c75SCarlo Caione ldr w3, [x0, #MESON_CONTROL_OFFSET] 1104a079c75SCarlo Caione orr w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ 1114a079c75SCarlo Caione (1 << MESON_CONTROL_RX_RESET_BIT) | \ 1124a079c75SCarlo Caione (1 << MESON_CONTROL_TX_RESET_BIT)) 1134a079c75SCarlo Caione str w3, [x0, #MESON_CONTROL_OFFSET] 1144a079c75SCarlo Caione bic w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ 1154a079c75SCarlo Caione (1 << MESON_CONTROL_RX_RESET_BIT) | \ 1164a079c75SCarlo Caione (1 << MESON_CONTROL_TX_RESET_BIT)) 1174a079c75SCarlo Caione str w3, [x0, #MESON_CONTROL_OFFSET] 1184a079c75SCarlo Caione /* Enable transfer and receive FIFO */ 1194a079c75SCarlo Caione orr w3, w3, #((1 << MESON_CONTROL_RX_ENABLE_BIT) | \ 1204a079c75SCarlo Caione (1 << MESON_CONTROL_TX_ENABLE_BIT)) 1214a079c75SCarlo Caione str w3, [x0, #MESON_CONTROL_OFFSET] 1224a079c75SCarlo Caione /* Success */ 1234a079c75SCarlo Caione mov w0, #1 1244a079c75SCarlo Caione ret 1254a079c75SCarlo Caioneinit_fail: 1264a079c75SCarlo Caione mov w0, wzr 1274a079c75SCarlo Caione ret 1284a079c75SCarlo Caioneendfunc console_meson_init 1294a079c75SCarlo Caione 1304a079c75SCarlo Caione /* -------------------------------------------------------- 131489e2987SAndre Przywara * int console_meson_putc(int c, console_t *console) 1324a079c75SCarlo Caione * Function to output a character over the console. It 1334a079c75SCarlo Caione * returns the character printed on success or -1 on error. 1344a079c75SCarlo Caione * In : w0 - character to be printed 1354a079c75SCarlo Caione * x1 - pointer to console_t structure 1364a079c75SCarlo Caione * Out : return -1 on error else return character. 1374a079c75SCarlo Caione * Clobber list : x2 1384a079c75SCarlo Caione * -------------------------------------------------------- 1394a079c75SCarlo Caione */ 1404a079c75SCarlo Caionefunc console_meson_putc 1414a079c75SCarlo Caione#if ENABLE_ASSERTIONS 1424a079c75SCarlo Caione cmp x1, #0 1434a079c75SCarlo Caione ASM_ASSERT(ne) 1444a079c75SCarlo Caione#endif /* ENABLE_ASSERTIONS */ 145489e2987SAndre Przywara ldr x1, [x1, #CONSOLE_T_BASE] 1464a079c75SCarlo Caione b console_meson_core_putc 1474a079c75SCarlo Caioneendfunc console_meson_putc 1484a079c75SCarlo Caione 1494a079c75SCarlo Caione /* -------------------------------------------------------- 1504a079c75SCarlo Caione * int console_meson_core_putc(int c, uintptr_t base_addr) 1514a079c75SCarlo Caione * Function to output a character over the console. It 1524a079c75SCarlo Caione * returns the character printed on success or -1 on error. 1534a079c75SCarlo Caione * In : w0 - character to be printed 1544a079c75SCarlo Caione * x1 - console base address 1554a079c75SCarlo Caione * Out : return -1 on error else return character. 1564a079c75SCarlo Caione * Clobber list : x2 1574a079c75SCarlo Caione * -------------------------------------------------------- 1584a079c75SCarlo Caione */ 1594a079c75SCarlo Caionefunc console_meson_core_putc 1604a079c75SCarlo Caione#if ENABLE_ASSERTIONS 1614a079c75SCarlo Caione cmp x1, #0 1624a079c75SCarlo Caione ASM_ASSERT(ne) 1634a079c75SCarlo Caione#endif 1644a079c75SCarlo Caione /* Prepend '\r' to '\n' */ 1654a079c75SCarlo Caione cmp w0, #0xA 1664a079c75SCarlo Caione b.ne 2f 1674a079c75SCarlo Caione /* Wait until the transmit FIFO isn't full */ 1684a079c75SCarlo Caione1: ldr w2, [x1, #MESON_STATUS_OFFSET] 1694a079c75SCarlo Caione tbnz w2, #MESON_STATUS_TX_FULL_BIT, 1b 1704a079c75SCarlo Caione /* Write '\r' if needed */ 1714a079c75SCarlo Caione mov w2, #0xD 1724a079c75SCarlo Caione str w2, [x1, #MESON_WFIFO_OFFSET] 1734a079c75SCarlo Caione /* Wait until the transmit FIFO isn't full */ 1744a079c75SCarlo Caione2: ldr w2, [x1, #MESON_STATUS_OFFSET] 1754a079c75SCarlo Caione tbnz w2, #MESON_STATUS_TX_FULL_BIT, 2b 1764a079c75SCarlo Caione /* Write input character */ 1774a079c75SCarlo Caione str w0, [x1, #MESON_WFIFO_OFFSET] 1784a079c75SCarlo Caione ret 1794a079c75SCarlo Caioneendfunc console_meson_core_putc 1804a079c75SCarlo Caione 1814a079c75SCarlo Caione /* --------------------------------------------- 182489e2987SAndre Przywara * int console_meson_getc(console_t *console) 1834a079c75SCarlo Caione * Function to get a character from the console. 1844a079c75SCarlo Caione * It returns the character grabbed on success 1854a079c75SCarlo Caione * or -1 if no character is available. 1864a079c75SCarlo Caione * In : x0 - pointer to console_t structure 1874a079c75SCarlo Caione * Out: w0 - character if available, else -1 1884a079c75SCarlo Caione * Clobber list : x0, x1 1894a079c75SCarlo Caione * --------------------------------------------- 1904a079c75SCarlo Caione */ 1914a079c75SCarlo Caionefunc console_meson_getc 1924a079c75SCarlo Caione#if ENABLE_ASSERTIONS 1934a079c75SCarlo Caione cmp x0, #0 1944a079c75SCarlo Caione ASM_ASSERT(ne) 1954a079c75SCarlo Caione#endif /* ENABLE_ASSERTIONS */ 196489e2987SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 1974a079c75SCarlo Caione b console_meson_core_getc 1984a079c75SCarlo Caioneendfunc console_meson_getc 1994a079c75SCarlo Caione 2004a079c75SCarlo Caione /* --------------------------------------------- 2014a079c75SCarlo Caione * int console_meson_core_getc(uintptr_t base_addr) 2024a079c75SCarlo Caione * Function to get a character from the console. 2034a079c75SCarlo Caione * It returns the character grabbed on success 2044a079c75SCarlo Caione * or -1 if no character is available. 2054a079c75SCarlo Caione * In : x0 - console base address 2064a079c75SCarlo Caione * Out: w0 - character if available, else -1 2074a079c75SCarlo Caione * Clobber list : x0, x1 2084a079c75SCarlo Caione * --------------------------------------------- 2094a079c75SCarlo Caione */ 2104a079c75SCarlo Caionefunc console_meson_core_getc 2114a079c75SCarlo Caione#if ENABLE_ASSERTIONS 2124a079c75SCarlo Caione cmp x0, #0 2134a079c75SCarlo Caione ASM_ASSERT(ne) 2144a079c75SCarlo Caione#endif 2154a079c75SCarlo Caione /* Is the receive FIFO empty? */ 2164a079c75SCarlo Caione ldr w1, [x0, #MESON_STATUS_OFFSET] 2174a079c75SCarlo Caione tbnz w1, #MESON_STATUS_RX_EMPTY_BIT, 1f 2184a079c75SCarlo Caione /* Read one character from the RX FIFO */ 2194a079c75SCarlo Caione ldr w0, [x0, #MESON_RFIFO_OFFSET] 2204a079c75SCarlo Caione ret 2214a079c75SCarlo Caione1: 2224a079c75SCarlo Caione mov w0, #ERROR_NO_PENDING_CHAR 2234a079c75SCarlo Caione ret 2244a079c75SCarlo Caioneendfunc console_meson_core_getc 2254a079c75SCarlo Caione 2264a079c75SCarlo Caione /* --------------------------------------------- 227831b0e98SJimmy Brisson * void console_meson_flush(console_t *console) 2284a079c75SCarlo Caione * Function to force a write of all buffered 2294a079c75SCarlo Caione * data that hasn't been output. 2304a079c75SCarlo Caione * In : x0 - pointer to console_t structure 231831b0e98SJimmy Brisson * Out : void. 2324a079c75SCarlo Caione * Clobber list : x0, x1 2334a079c75SCarlo Caione * --------------------------------------------- 2344a079c75SCarlo Caione */ 2354a079c75SCarlo Caionefunc console_meson_flush 2364a079c75SCarlo Caione#if ENABLE_ASSERTIONS 2374a079c75SCarlo Caione cmp x0, #0 2384a079c75SCarlo Caione ASM_ASSERT(ne) 2394a079c75SCarlo Caione#endif /* ENABLE_ASSERTIONS */ 240489e2987SAndre Przywara ldr x0, [x0, #CONSOLE_T_BASE] 2414a079c75SCarlo Caione b console_meson_core_flush 2424a079c75SCarlo Caioneendfunc console_meson_flush 2434a079c75SCarlo Caione 2444a079c75SCarlo Caione /* --------------------------------------------- 245831b0e98SJimmy Brisson * void console_meson_core_flush(uintptr_t base_addr) 2464a079c75SCarlo Caione * Function to force a write of all buffered 2474a079c75SCarlo Caione * data that hasn't been output. 2484a079c75SCarlo Caione * In : x0 - console base address 249831b0e98SJimmy Brisson * Out : void. 2504a079c75SCarlo Caione * Clobber list : x0, x1 2514a079c75SCarlo Caione * --------------------------------------------- 2524a079c75SCarlo Caione */ 2534a079c75SCarlo Caionefunc console_meson_core_flush 2544a079c75SCarlo Caione#if ENABLE_ASSERTIONS 2554a079c75SCarlo Caione cmp x0, #0 2564a079c75SCarlo Caione ASM_ASSERT(ne) 2574a079c75SCarlo Caione#endif 2584a079c75SCarlo Caione /* Wait until the transmit FIFO is empty */ 2594a079c75SCarlo Caione1: ldr w1, [x0, #MESON_STATUS_OFFSET] 2604a079c75SCarlo Caione tbz w1, #MESON_STATUS_TX_EMPTY_BIT, 1b 2614a079c75SCarlo Caione ret 2624a079c75SCarlo Caioneendfunc console_meson_core_flush 263