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