]>
Commit | Line | Data |
---|---|---|
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 | ||
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> | |
41 | * - Define _debug_uart_init(), trying to avoid using the stack | |
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.) | |
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. | |
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 | ||
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 | ||
73 | /** | |
74 | * printch() - Output a character to the debug UART | |
75 | * | |
76 | * @ch: Character to output | |
77 | */ | |
78 | void printch(int ch); | |
79 | ||
80 | /** | |
81 | * printascii() - Output an ASCII string to the debug UART | |
82 | * | |
83 | * @str: String to output | |
84 | */ | |
85 | void printascii(const char *str); | |
86 | ||
87 | /** | |
88 | * printhex2() - Output a 2-digit hex value | |
89 | * | |
90 | * @value: Value to output | |
91 | */ | |
92 | void printhex2(uint value); | |
93 | ||
94 | /** | |
95 | * printhex4() - Output a 4-digit hex value | |
96 | * | |
97 | * @value: Value to output | |
98 | */ | |
99 | void printhex4(uint value); | |
100 | ||
101 | /** | |
102 | * printhex8() - Output a 8-digit hex value | |
103 | * | |
104 | * @value: Value to output | |
105 | */ | |
106 | void printhex8(uint value); | |
107 | ||
108 | #ifdef CONFIG_DEBUG_UART_ANNOUNCE | |
109 | #define _DEBUG_UART_ANNOUNCE printascii("<debug_uart> "); | |
110 | #else | |
111 | #define _DEBUG_UART_ANNOUNCE | |
112 | #endif | |
113 | ||
114 | #define serial_dout(reg, value) \ | |
115 | serial_out_shift((char *)com_port + \ | |
116 | ((char *)reg - (char *)com_port) * \ | |
117 | (1 << CONFIG_DEBUG_UART_SHIFT), \ | |
118 | CONFIG_DEBUG_UART_SHIFT, value) | |
119 | #define serial_din(reg) \ | |
120 | serial_in_shift((char *)com_port + \ | |
121 | ((char *)reg - (char *)com_port) * \ | |
122 | (1 << CONFIG_DEBUG_UART_SHIFT), \ | |
123 | CONFIG_DEBUG_UART_SHIFT) | |
124 | ||
125 | /* | |
126 | * Now define some functions - this should be inserted into the serial driver | |
127 | */ | |
128 | #define DEBUG_UART_FUNCS \ | |
129 | \ | |
130 | static inline void _printch(int ch) \ | |
131 | { \ | |
132 | if (ch == '\n') \ | |
133 | _debug_uart_putc('\r'); \ | |
134 | _debug_uart_putc(ch); \ | |
135 | } \ | |
136 | \ | |
137 | void printch(int ch) \ | |
138 | { \ | |
139 | _printch(ch); \ | |
140 | } \ | |
141 | \ | |
142 | void printascii(const char *str) \ | |
143 | { \ | |
144 | while (*str) \ | |
145 | _printch(*str++); \ | |
146 | } \ | |
147 | \ | |
148 | static inline void printhex1(uint digit) \ | |
149 | { \ | |
150 | digit &= 0xf; \ | |
151 | _debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \ | |
152 | } \ | |
153 | \ | |
154 | static inline void printhex(uint value, int digits) \ | |
155 | { \ | |
156 | while (digits-- > 0) \ | |
157 | printhex1(value >> (4 * digits)); \ | |
158 | } \ | |
159 | \ | |
160 | void printhex2(uint value) \ | |
161 | { \ | |
162 | printhex(value, 2); \ | |
163 | } \ | |
164 | \ | |
165 | void printhex4(uint value) \ | |
166 | { \ | |
167 | printhex(value, 4); \ | |
168 | } \ | |
169 | \ | |
170 | void printhex8(uint value) \ | |
171 | { \ | |
172 | printhex(value, 8); \ | |
173 | } \ | |
174 | \ | |
175 | void debug_uart_init(void) \ | |
176 | { \ | |
177 | board_debug_uart_init(); \ | |
178 | _debug_uart_init(); \ | |
179 | _DEBUG_UART_ANNOUNCE \ | |
180 | } \ | |
181 | ||
182 | #endif |