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