]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2f964aa7 SG |
2 | /* |
3 | * Early debug UART support | |
4 | * | |
5 | * (C) Copyright 2014 Google, Inc | |
6 | * Writte by Simon Glass <[email protected]> | |
2f964aa7 SG |
7 | */ |
8 | ||
9 | #ifndef _DEBUG_UART_H | |
10 | #define _DEBUG_UART_H | |
11 | ||
2f964aa7 SG |
12 | /* |
13 | * The debug UART is intended for use very early in U-Boot to debug problems | |
14 | * when an ICE or other debug mechanism is not available. | |
15 | * | |
16 | * To use it you should: | |
17 | * - Make sure your UART supports this interface | |
18 | * - Enable CONFIG_DEBUG_UART | |
19 | * - Enable the CONFIG for your UART to tell it to provide this interface | |
20 | * (e.g. CONFIG_DEBUG_UART_NS16550) | |
21 | * - Define the required settings as needed (see below) | |
22 | * - Call debug_uart_init() before use | |
23 | * - Call printch() to output a character | |
24 | * | |
25 | * Depending on your platform it may be possible to use this UART before a | |
26 | * stack is available. | |
27 | * | |
28 | * If your UART does not support this interface you can probably add support | |
29 | * quite easily. Remember that you cannot use driver model and it is preferred | |
30 | * to use no stack. | |
31 | * | |
32 | * You must not use this UART once driver model is working and the serial | |
33 | * drivers are up and running (done in serial_init()). Otherwise the drivers | |
34 | * may conflict and you will get strange output. | |
35 | * | |
36 | * | |
37 | * To enable the debug UART in your serial driver: | |
38 | * | |
39 | * - #include <debug_uart.h> | |
97b05973 | 40 | * - Define _debug_uart_init(), trying to avoid using the stack |
2f964aa7 SG |
41 | * - Define _debug_uart_putc() as static inline (avoiding stack usage) |
42 | * - Immediately afterwards, add DEBUG_UART_FUNCS to define the rest of the | |
43 | * functionality (printch(), etc.) | |
0e977bc1 SG |
44 | * |
45 | * If your board needs additional init for the UART to work, enable | |
46 | * CONFIG_DEBUG_UART_BOARD_INIT and write a function called | |
47 | * board_debug_uart_init() to perform that init. When debug_uart_init() is | |
48 | * called, the init will happen automatically. | |
2f964aa7 SG |
49 | */ |
50 | ||
51 | /** | |
52 | * debug_uart_init() - Set up the debug UART ready for use | |
53 | * | |
54 | * This sets up the UART with the correct baud rate, etc. | |
55 | * | |
56 | * Available CONFIG is: | |
57 | * | |
58 | * - CONFIG_DEBUG_UART_BASE: Base address of UART | |
59 | * - CONFIG_BAUDRATE: Requested baud rate | |
60 | * - CONFIG_DEBUG_UART_CLOCK: Input clock for UART | |
61 | */ | |
62 | void debug_uart_init(void); | |
63 | ||
0e977bc1 SG |
64 | #ifdef CONFIG_DEBUG_UART_BOARD_INIT |
65 | void board_debug_uart_init(void); | |
66 | #else | |
67 | static inline void board_debug_uart_init(void) | |
68 | { | |
69 | } | |
70 | #endif | |
71 | ||
2f964aa7 SG |
72 | /** |
73 | * printch() - Output a character to the debug UART | |
74 | * | |
75 | * @ch: Character to output | |
76 | */ | |
d0d73614 | 77 | void printch(int ch); |
2f964aa7 SG |
78 | |
79 | /** | |
80 | * printascii() - Output an ASCII string to the debug UART | |
81 | * | |
82 | * @str: String to output | |
83 | */ | |
d0d73614 | 84 | void printascii(const char *str); |
2f964aa7 SG |
85 | |
86 | /** | |
87 | * printhex2() - Output a 2-digit hex value | |
88 | * | |
89 | * @value: Value to output | |
90 | */ | |
77c4ba54 | 91 | void printhex2(unsigned int value); |
2f964aa7 SG |
92 | |
93 | /** | |
94 | * printhex4() - Output a 4-digit hex value | |
95 | * | |
96 | * @value: Value to output | |
97 | */ | |
77c4ba54 | 98 | void printhex4(unsigned int value); |
2f964aa7 SG |
99 | |
100 | /** | |
101 | * printhex8() - Output a 8-digit hex value | |
102 | * | |
103 | * @value: Value to output | |
104 | */ | |
77c4ba54 | 105 | void printhex8(unsigned int value); |
2f964aa7 | 106 | |
3940ab65 JT |
107 | /** |
108 | * printdec() - Output a decimalism value | |
109 | * | |
110 | * @value: Value to output | |
111 | */ | |
77c4ba54 | 112 | void printdec(unsigned int value); |
3940ab65 | 113 | |
c7fefcb9 SG |
114 | #ifdef CONFIG_DEBUG_UART_ANNOUNCE |
115 | #define _DEBUG_UART_ANNOUNCE printascii("<debug_uart> "); | |
116 | #else | |
117 | #define _DEBUG_UART_ANNOUNCE | |
118 | #endif | |
119 | ||
a52cf086 LV |
120 | #define serial_dout(reg, value) \ |
121 | serial_out_shift((char *)com_port + \ | |
122 | ((char *)reg - (char *)com_port) * \ | |
123 | (1 << CONFIG_DEBUG_UART_SHIFT), \ | |
124 | CONFIG_DEBUG_UART_SHIFT, value) | |
125 | #define serial_din(reg) \ | |
126 | serial_in_shift((char *)com_port + \ | |
127 | ((char *)reg - (char *)com_port) * \ | |
128 | (1 << CONFIG_DEBUG_UART_SHIFT), \ | |
129 | CONFIG_DEBUG_UART_SHIFT) | |
130 | ||
2f964aa7 SG |
131 | /* |
132 | * Now define some functions - this should be inserted into the serial driver | |
133 | */ | |
134 | #define DEBUG_UART_FUNCS \ | |
6bacc736 | 135 | \ |
136 | static inline void _printch(int ch) \ | |
2f964aa7 | 137 | { \ |
b391d743 MY |
138 | if (ch == '\n') \ |
139 | _debug_uart_putc('\r'); \ | |
2f964aa7 SG |
140 | _debug_uart_putc(ch); \ |
141 | } \ | |
6bacc736 | 142 | \ |
143 | void printch(int ch) \ | |
144 | { \ | |
145 | _printch(ch); \ | |
146 | } \ | |
2f964aa7 | 147 | \ |
d0d73614 | 148 | void printascii(const char *str) \ |
2f964aa7 SG |
149 | { \ |
150 | while (*str) \ | |
6bacc736 | 151 | _printch(*str++); \ |
2f964aa7 SG |
152 | } \ |
153 | \ | |
77c4ba54 | 154 | static inline void printhex1(unsigned int digit) \ |
2f964aa7 SG |
155 | { \ |
156 | digit &= 0xf; \ | |
157 | _debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \ | |
158 | } \ | |
159 | \ | |
77c4ba54 | 160 | static inline void printhex(unsigned int value, int digits) \ |
2f964aa7 SG |
161 | { \ |
162 | while (digits-- > 0) \ | |
163 | printhex1(value >> (4 * digits)); \ | |
164 | } \ | |
165 | \ | |
77c4ba54 | 166 | void printhex2(unsigned int value) \ |
2f964aa7 SG |
167 | { \ |
168 | printhex(value, 2); \ | |
169 | } \ | |
170 | \ | |
77c4ba54 | 171 | void printhex4(unsigned int value) \ |
2f964aa7 SG |
172 | { \ |
173 | printhex(value, 4); \ | |
174 | } \ | |
175 | \ | |
77c4ba54 | 176 | void printhex8(unsigned int value) \ |
2f964aa7 SG |
177 | { \ |
178 | printhex(value, 8); \ | |
97b05973 | 179 | } \ |
3940ab65 | 180 | \ |
77c4ba54 | 181 | void printdec(unsigned int value) \ |
3940ab65 JT |
182 | { \ |
183 | if (value > 10) { \ | |
184 | printdec(value / 10); \ | |
185 | value %= 10; \ | |
186 | } else if (value == 10) { \ | |
187 | _debug_uart_putc('1'); \ | |
188 | value = 0; \ | |
189 | } \ | |
190 | _debug_uart_putc('0' + value); \ | |
191 | } \ | |
97b05973 SG |
192 | \ |
193 | void debug_uart_init(void) \ | |
194 | { \ | |
0e977bc1 | 195 | board_debug_uart_init(); \ |
97b05973 | 196 | _debug_uart_init(); \ |
c7fefcb9 | 197 | _DEBUG_UART_ANNOUNCE \ |
97b05973 | 198 | } \ |
2f964aa7 SG |
199 | |
200 | #endif |