1e5936205SVenkatesh Yadav Abbarapu /* 2e5936205SVenkatesh Yadav Abbarapu * Copyright (c) 2015-2021, Xilinx Inc. 3e5936205SVenkatesh Yadav Abbarapu * Written by Michal Simek. 4e5936205SVenkatesh Yadav Abbarapu * 5e5936205SVenkatesh Yadav Abbarapu * SPDX-License-Identifier: BSD-3-Clause 6e5936205SVenkatesh Yadav Abbarapu * 7e5936205SVenkatesh Yadav Abbarapu * Redistribution and use in source and binary forms, with or without 8e5936205SVenkatesh Yadav Abbarapu * modification, are permitted provided that the following conditions are met: 9e5936205SVenkatesh Yadav Abbarapu * 10e5936205SVenkatesh Yadav Abbarapu * Redistributions of source code must retain the above copyright notice, this 11e5936205SVenkatesh Yadav Abbarapu * list of conditions and the following disclaimer. 12e5936205SVenkatesh Yadav Abbarapu * 13e5936205SVenkatesh Yadav Abbarapu * Redistributions in binary form must reproduce the above copyright notice, 14e5936205SVenkatesh Yadav Abbarapu * this list of conditions and the following disclaimer in the documentation 15e5936205SVenkatesh Yadav Abbarapu * and/or other materials provided with the distribution. 16e5936205SVenkatesh Yadav Abbarapu * 17e5936205SVenkatesh Yadav Abbarapu * Neither the name of ARM nor the names of its contributors may be used 18e5936205SVenkatesh Yadav Abbarapu * to endorse or promote products derived from this software without specific 19e5936205SVenkatesh Yadav Abbarapu * prior written permission. 20e5936205SVenkatesh Yadav Abbarapu * 21e5936205SVenkatesh Yadav Abbarapu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22e5936205SVenkatesh Yadav Abbarapu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23e5936205SVenkatesh Yadav Abbarapu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24e5936205SVenkatesh Yadav Abbarapu * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25e5936205SVenkatesh Yadav Abbarapu * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26e5936205SVenkatesh Yadav Abbarapu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27e5936205SVenkatesh Yadav Abbarapu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28e5936205SVenkatesh Yadav Abbarapu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29e5936205SVenkatesh Yadav Abbarapu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30e5936205SVenkatesh Yadav Abbarapu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31e5936205SVenkatesh Yadav Abbarapu * POSSIBILITY OF SUCH DAMAGE. 32e5936205SVenkatesh Yadav Abbarapu */ 33e5936205SVenkatesh Yadav Abbarapu 34e5936205SVenkatesh Yadav Abbarapu #include <errno.h> 35e5936205SVenkatesh Yadav Abbarapu #include <stddef.h> 36e5936205SVenkatesh Yadav Abbarapu #include <arch_helpers.h> 37e5936205SVenkatesh Yadav Abbarapu #include <drivers/arm/dcc.h> 38e5936205SVenkatesh Yadav Abbarapu #include <drivers/console.h> 39e5936205SVenkatesh Yadav Abbarapu #include <drivers/delay_timer.h> 40e5936205SVenkatesh Yadav Abbarapu #include <lib/mmio.h> 41e5936205SVenkatesh Yadav Abbarapu 42e5936205SVenkatesh Yadav Abbarapu /* DCC Status Bits */ 43e5936205SVenkatesh Yadav Abbarapu #define DCC_STATUS_RX BIT(30) 44e5936205SVenkatesh Yadav Abbarapu #define DCC_STATUS_TX BIT(29) 45e5936205SVenkatesh Yadav Abbarapu #define TIMEOUT_COUNT_US U(0x10624) 46e5936205SVenkatesh Yadav Abbarapu 47e5936205SVenkatesh Yadav Abbarapu struct dcc_console { 48e5936205SVenkatesh Yadav Abbarapu struct console console; 49e5936205SVenkatesh Yadav Abbarapu }; 50e5936205SVenkatesh Yadav Abbarapu 51e5936205SVenkatesh Yadav Abbarapu static inline uint32_t __dcc_getstatus(void) 52e5936205SVenkatesh Yadav Abbarapu { 53e5936205SVenkatesh Yadav Abbarapu return read_mdccsr_el0(); 54e5936205SVenkatesh Yadav Abbarapu } 55e5936205SVenkatesh Yadav Abbarapu 56e5936205SVenkatesh Yadav Abbarapu static inline char __dcc_getchar(void) 57e5936205SVenkatesh Yadav Abbarapu { 58e5936205SVenkatesh Yadav Abbarapu char c; 59e5936205SVenkatesh Yadav Abbarapu 60e5936205SVenkatesh Yadav Abbarapu c = read_dbgdtrrx_el0(); 61e5936205SVenkatesh Yadav Abbarapu 62e5936205SVenkatesh Yadav Abbarapu return c; 63e5936205SVenkatesh Yadav Abbarapu } 64e5936205SVenkatesh Yadav Abbarapu 65e5936205SVenkatesh Yadav Abbarapu static inline void __dcc_putchar(char c) 66e5936205SVenkatesh Yadav Abbarapu { 67e5936205SVenkatesh Yadav Abbarapu /* 68e5936205SVenkatesh Yadav Abbarapu * The typecast is to make absolutely certain that 'c' is 69e5936205SVenkatesh Yadav Abbarapu * zero-extended. 70e5936205SVenkatesh Yadav Abbarapu */ 71e5936205SVenkatesh Yadav Abbarapu write_dbgdtrtx_el0((unsigned char)c); 72e5936205SVenkatesh Yadav Abbarapu } 73e5936205SVenkatesh Yadav Abbarapu 74e5936205SVenkatesh Yadav Abbarapu static int32_t dcc_status_timeout(uint32_t mask) 75e5936205SVenkatesh Yadav Abbarapu { 76e5936205SVenkatesh Yadav Abbarapu const unsigned int timeout_count = TIMEOUT_COUNT_US; 77e5936205SVenkatesh Yadav Abbarapu uint64_t timeout; 78e5936205SVenkatesh Yadav Abbarapu unsigned int status; 79e5936205SVenkatesh Yadav Abbarapu 80e5936205SVenkatesh Yadav Abbarapu timeout = timeout_init_us(timeout_count); 81e5936205SVenkatesh Yadav Abbarapu 82e5936205SVenkatesh Yadav Abbarapu do { 83e5936205SVenkatesh Yadav Abbarapu status = (__dcc_getstatus() & mask); 84e5936205SVenkatesh Yadav Abbarapu if (timeout_elapsed(timeout)) { 85e5936205SVenkatesh Yadav Abbarapu return -ETIMEDOUT; 86e5936205SVenkatesh Yadav Abbarapu } 87e5936205SVenkatesh Yadav Abbarapu } while ((status != 0U)); 88e5936205SVenkatesh Yadav Abbarapu 89e5936205SVenkatesh Yadav Abbarapu return 0; 90e5936205SVenkatesh Yadav Abbarapu } 91e5936205SVenkatesh Yadav Abbarapu 92e5936205SVenkatesh Yadav Abbarapu static int32_t dcc_console_putc(int32_t ch, struct console *console) 93e5936205SVenkatesh Yadav Abbarapu { 94e5936205SVenkatesh Yadav Abbarapu unsigned int status; 95e5936205SVenkatesh Yadav Abbarapu 96e5936205SVenkatesh Yadav Abbarapu status = dcc_status_timeout(DCC_STATUS_TX); 97e5936205SVenkatesh Yadav Abbarapu if (status != 0U) { 98e5936205SVenkatesh Yadav Abbarapu return status; 99e5936205SVenkatesh Yadav Abbarapu } 100e5936205SVenkatesh Yadav Abbarapu __dcc_putchar(ch); 101e5936205SVenkatesh Yadav Abbarapu 102e5936205SVenkatesh Yadav Abbarapu return ch; 103e5936205SVenkatesh Yadav Abbarapu } 104e5936205SVenkatesh Yadav Abbarapu 105e5936205SVenkatesh Yadav Abbarapu static int32_t dcc_console_getc(struct console *console) 106e5936205SVenkatesh Yadav Abbarapu { 107e5936205SVenkatesh Yadav Abbarapu unsigned int status; 108e5936205SVenkatesh Yadav Abbarapu 109e5936205SVenkatesh Yadav Abbarapu status = dcc_status_timeout(DCC_STATUS_RX); 110e5936205SVenkatesh Yadav Abbarapu if (status != 0U) { 111e5936205SVenkatesh Yadav Abbarapu return status; 112e5936205SVenkatesh Yadav Abbarapu } 113e5936205SVenkatesh Yadav Abbarapu 114e5936205SVenkatesh Yadav Abbarapu return __dcc_getchar(); 115e5936205SVenkatesh Yadav Abbarapu } 116e5936205SVenkatesh Yadav Abbarapu 117e5936205SVenkatesh Yadav Abbarapu int32_t dcc_console_init(unsigned long base_addr, uint32_t uart_clk, 118e5936205SVenkatesh Yadav Abbarapu uint32_t baud_rate) 119e5936205SVenkatesh Yadav Abbarapu { 120e5936205SVenkatesh Yadav Abbarapu return 0; /* No init needed */ 121e5936205SVenkatesh Yadav Abbarapu } 122e5936205SVenkatesh Yadav Abbarapu 123e5936205SVenkatesh Yadav Abbarapu /** 124e5936205SVenkatesh Yadav Abbarapu * dcc_console_flush() - Function to force a write of all buffered data 125e5936205SVenkatesh Yadav Abbarapu * that hasn't been output. 126e5936205SVenkatesh Yadav Abbarapu * @console Console struct 127e5936205SVenkatesh Yadav Abbarapu * 128e5936205SVenkatesh Yadav Abbarapu */ 129e5936205SVenkatesh Yadav Abbarapu static void dcc_console_flush(struct console *console) 130e5936205SVenkatesh Yadav Abbarapu { 131e5936205SVenkatesh Yadav Abbarapu unsigned int status; 132e5936205SVenkatesh Yadav Abbarapu 133e5936205SVenkatesh Yadav Abbarapu status = dcc_status_timeout(DCC_STATUS_TX); 134e5936205SVenkatesh Yadav Abbarapu if (status != 0U) { 135e5936205SVenkatesh Yadav Abbarapu return; 136e5936205SVenkatesh Yadav Abbarapu } 137e5936205SVenkatesh Yadav Abbarapu } 138e5936205SVenkatesh Yadav Abbarapu 139e5936205SVenkatesh Yadav Abbarapu static struct dcc_console dcc_console = { 140e5936205SVenkatesh Yadav Abbarapu .console = { 141e5936205SVenkatesh Yadav Abbarapu .flags = CONSOLE_FLAG_BOOT | 142*c6d9186fSMichal Simek CONSOLE_FLAG_RUNTIME | 143*c6d9186fSMichal Simek CONSOLE_FLAG_CRASH, 144e5936205SVenkatesh Yadav Abbarapu .putc = dcc_console_putc, 145e5936205SVenkatesh Yadav Abbarapu .getc = dcc_console_getc, 146e5936205SVenkatesh Yadav Abbarapu .flush = dcc_console_flush, 147e5936205SVenkatesh Yadav Abbarapu }, 148e5936205SVenkatesh Yadav Abbarapu }; 149e5936205SVenkatesh Yadav Abbarapu 150e5936205SVenkatesh Yadav Abbarapu int console_dcc_register(void) 151e5936205SVenkatesh Yadav Abbarapu { 152e5936205SVenkatesh Yadav Abbarapu return console_register(&dcc_console.console); 153e5936205SVenkatesh Yadav Abbarapu } 154