blob: 0b7e541f06fa952ca115ac66eed4262b792380ee [file] [log] [blame]
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -07001/*
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
47struct dcc_console {
48 struct console console;
49};
50
51static inline uint32_t __dcc_getstatus(void)
52{
53 return read_mdccsr_el0();
54}
55
56static inline char __dcc_getchar(void)
57{
58 char c;
59
60 c = read_dbgdtrrx_el0();
61
62 return c;
63}
64
65static 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
74static 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
92static 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
105static 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
117int32_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 */
129static 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
139static 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
149int console_dcc_register(void)
150{
151 return console_register(&dcc_console.console);
152}