blob: 19c3450b39be79f67ec41fc4452f37c621d85e86 [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
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +020056#if ENABLE_CONSOLE_GETC
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -070057static inline char __dcc_getchar(void)
58{
59 char c;
60
61 c = read_dbgdtrrx_el0();
62
63 return c;
64}
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +020065#endif
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -070066
67static inline void __dcc_putchar(char c)
68{
69 /*
70 * The typecast is to make absolutely certain that 'c' is
71 * zero-extended.
72 */
73 write_dbgdtrtx_el0((unsigned char)c);
74}
75
76static int32_t dcc_status_timeout(uint32_t mask)
77{
78 const unsigned int timeout_count = TIMEOUT_COUNT_US;
79 uint64_t timeout;
80 unsigned int status;
81
82 timeout = timeout_init_us(timeout_count);
83
84 do {
85 status = (__dcc_getstatus() & mask);
86 if (timeout_elapsed(timeout)) {
87 return -ETIMEDOUT;
88 }
89 } while ((status != 0U));
90
91 return 0;
92}
93
94static int32_t dcc_console_putc(int32_t ch, struct console *console)
95{
96 unsigned int status;
97
98 status = dcc_status_timeout(DCC_STATUS_TX);
99 if (status != 0U) {
100 return status;
101 }
102 __dcc_putchar(ch);
103
104 return ch;
105}
106
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +0200107#if ENABLE_CONSOLE_GETC
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -0700108static int32_t dcc_console_getc(struct console *console)
109{
110 unsigned int status;
111
112 status = dcc_status_timeout(DCC_STATUS_RX);
113 if (status != 0U) {
114 return status;
115 }
116
117 return __dcc_getchar();
118}
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +0200119#endif
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -0700120
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -0700121/**
122 * dcc_console_flush() - Function to force a write of all buffered data
123 * that hasn't been output.
124 * @console Console struct
125 *
126 */
127static void dcc_console_flush(struct console *console)
128{
129 unsigned int status;
130
131 status = dcc_status_timeout(DCC_STATUS_TX);
132 if (status != 0U) {
133 return;
134 }
135}
136
137static struct dcc_console dcc_console = {
138 .console = {
139 .flags = CONSOLE_FLAG_BOOT |
Michal Simek78ba23d2023-09-18 10:16:25 +0200140 CONSOLE_FLAG_RUNTIME |
141 CONSOLE_FLAG_CRASH,
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -0700142 .putc = dcc_console_putc,
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +0200143#if ENABLE_CONSOLE_GETC
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -0700144 .getc = dcc_console_getc,
Sandrine Bailleuxf57e2032023-10-11 08:38:00 +0200145#endif
Venkatesh Yadav Abbarapuf80014d2020-11-27 02:58:24 -0700146 .flush = dcc_console_flush,
147 },
148};
149
150int console_dcc_register(void)
151{
152 return console_register(&dcc_console.console);
153}
Prasad Kummarif006e952023-09-19 22:35:08 +0530154
155void console_dcc_unregister(void)
156{
157 dcc_console_flush(&dcc_console.console);
158 (void)console_unregister(&dcc_console.console);
159}