12f964aa7SSimon Glass /*
22f964aa7SSimon Glass * Early debug UART support
32f964aa7SSimon Glass *
42f964aa7SSimon Glass * (C) Copyright 2014 Google, Inc
52f964aa7SSimon Glass * Writte by Simon Glass <sjg@chromium.org>
62f964aa7SSimon Glass *
72f964aa7SSimon Glass * SPDX-License-Identifier: GPL-2.0+
82f964aa7SSimon Glass */
92f964aa7SSimon Glass
102f964aa7SSimon Glass #ifndef _DEBUG_UART_H
112f964aa7SSimon Glass #define _DEBUG_UART_H
122f964aa7SSimon Glass
132f964aa7SSimon Glass /*
142f964aa7SSimon Glass * The debug UART is intended for use very early in U-Boot to debug problems
152f964aa7SSimon Glass * when an ICE or other debug mechanism is not available.
162f964aa7SSimon Glass *
172f964aa7SSimon Glass * To use it you should:
182f964aa7SSimon Glass * - Make sure your UART supports this interface
192f964aa7SSimon Glass * - Enable CONFIG_DEBUG_UART
202f964aa7SSimon Glass * - Enable the CONFIG for your UART to tell it to provide this interface
212f964aa7SSimon Glass * (e.g. CONFIG_DEBUG_UART_NS16550)
222f964aa7SSimon Glass * - Define the required settings as needed (see below)
232f964aa7SSimon Glass * - Call debug_uart_init() before use
242f964aa7SSimon Glass * - Call printch() to output a character
252f964aa7SSimon Glass *
262f964aa7SSimon Glass * Depending on your platform it may be possible to use this UART before a
272f964aa7SSimon Glass * stack is available.
282f964aa7SSimon Glass *
292f964aa7SSimon Glass * If your UART does not support this interface you can probably add support
302f964aa7SSimon Glass * quite easily. Remember that you cannot use driver model and it is preferred
312f964aa7SSimon Glass * to use no stack.
322f964aa7SSimon Glass *
332f964aa7SSimon Glass * You must not use this UART once driver model is working and the serial
342f964aa7SSimon Glass * drivers are up and running (done in serial_init()). Otherwise the drivers
352f964aa7SSimon Glass * may conflict and you will get strange output.
362f964aa7SSimon Glass *
372f964aa7SSimon Glass *
382f964aa7SSimon Glass * To enable the debug UART in your serial driver:
392f964aa7SSimon Glass *
402f964aa7SSimon Glass * - #include <debug_uart.h>
4197b05973SSimon Glass * - Define _debug_uart_init(), trying to avoid using the stack
422f964aa7SSimon Glass * - Define _debug_uart_putc() as static inline (avoiding stack usage)
432f964aa7SSimon Glass * - Immediately afterwards, add DEBUG_UART_FUNCS to define the rest of the
442f964aa7SSimon Glass * functionality (printch(), etc.)
450e977bc1SSimon Glass *
460e977bc1SSimon Glass * If your board needs additional init for the UART to work, enable
470e977bc1SSimon Glass * CONFIG_DEBUG_UART_BOARD_INIT and write a function called
480e977bc1SSimon Glass * board_debug_uart_init() to perform that init. When debug_uart_init() is
490e977bc1SSimon Glass * called, the init will happen automatically.
502f964aa7SSimon Glass */
512f964aa7SSimon Glass
522f964aa7SSimon Glass /**
532f964aa7SSimon Glass * debug_uart_init() - Set up the debug UART ready for use
542f964aa7SSimon Glass *
552f964aa7SSimon Glass * This sets up the UART with the correct baud rate, etc.
562f964aa7SSimon Glass *
572f964aa7SSimon Glass * Available CONFIG is:
582f964aa7SSimon Glass *
592f964aa7SSimon Glass * - CONFIG_DEBUG_UART_BASE: Base address of UART
602f964aa7SSimon Glass * - CONFIG_BAUDRATE: Requested baud rate
612f964aa7SSimon Glass * - CONFIG_DEBUG_UART_CLOCK: Input clock for UART
622f964aa7SSimon Glass */
632f964aa7SSimon Glass void debug_uart_init(void);
642f964aa7SSimon Glass
650e977bc1SSimon Glass #ifdef CONFIG_DEBUG_UART_BOARD_INIT
660e977bc1SSimon Glass void board_debug_uart_init(void);
670e977bc1SSimon Glass #else
board_debug_uart_init(void)680e977bc1SSimon Glass static inline void board_debug_uart_init(void)
690e977bc1SSimon Glass {
700e977bc1SSimon Glass }
710e977bc1SSimon Glass #endif
720e977bc1SSimon Glass
732f964aa7SSimon Glass /**
742f964aa7SSimon Glass * printch() - Output a character to the debug UART
752f964aa7SSimon Glass *
762f964aa7SSimon Glass * @ch: Character to output
772f964aa7SSimon Glass */
78d0d73614SSimon Glass void printch(int ch);
79034db995SJoseph Chen int debug_uart_getc(void);
80034db995SJoseph Chen int debug_uart_tstc(void);
81034db995SJoseph Chen int debug_uart_clrc(void);
82*a5d16e51SJoseph Chen int debug_uart_flushc(void);
83034db995SJoseph Chen int debug_uart_setbrg(void);
842f964aa7SSimon Glass
852f964aa7SSimon Glass /**
862f964aa7SSimon Glass * printascii() - Output an ASCII string to the debug UART
872f964aa7SSimon Glass *
882f964aa7SSimon Glass * @str: String to output
892f964aa7SSimon Glass */
90d0d73614SSimon Glass void printascii(const char *str);
912f964aa7SSimon Glass
922f964aa7SSimon Glass /**
932f964aa7SSimon Glass * printhex2() - Output a 2-digit hex value
942f964aa7SSimon Glass *
952f964aa7SSimon Glass * @value: Value to output
962f964aa7SSimon Glass */
97d0d73614SSimon Glass void printhex2(uint value);
982f964aa7SSimon Glass
992f964aa7SSimon Glass /**
1002f964aa7SSimon Glass * printhex4() - Output a 4-digit hex value
1012f964aa7SSimon Glass *
1022f964aa7SSimon Glass * @value: Value to output
1032f964aa7SSimon Glass */
104d0d73614SSimon Glass void printhex4(uint value);
1052f964aa7SSimon Glass
1062f964aa7SSimon Glass /**
1072f964aa7SSimon Glass * printhex8() - Output a 8-digit hex value
1082f964aa7SSimon Glass *
1092f964aa7SSimon Glass * @value: Value to output
1102f964aa7SSimon Glass */
111d0d73614SSimon Glass void printhex8(uint value);
1122f964aa7SSimon Glass
113ab83a6feSCanYang He /**
114ab83a6feSCanYang He * printdec() - Output a decimalism value
115ab83a6feSCanYang He *
116ab83a6feSCanYang He * @value: Value to output
117ab83a6feSCanYang He */
118ab83a6feSCanYang He void printdec(uint value);
119ab83a6feSCanYang He
120c7fefcb9SSimon Glass #ifdef CONFIG_DEBUG_UART_ANNOUNCE
121c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE printascii("<debug_uart> ");
122c7fefcb9SSimon Glass #else
123c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE
124c7fefcb9SSimon Glass #endif
125c7fefcb9SSimon Glass
126a52cf086SLokesh Vutla #define serial_dout(reg, value) \
127a52cf086SLokesh Vutla serial_out_shift((char *)com_port + \
128a52cf086SLokesh Vutla ((char *)reg - (char *)com_port) * \
129a52cf086SLokesh Vutla (1 << CONFIG_DEBUG_UART_SHIFT), \
130a52cf086SLokesh Vutla CONFIG_DEBUG_UART_SHIFT, value)
131a52cf086SLokesh Vutla #define serial_din(reg) \
132a52cf086SLokesh Vutla serial_in_shift((char *)com_port + \
133a52cf086SLokesh Vutla ((char *)reg - (char *)com_port) * \
134a52cf086SLokesh Vutla (1 << CONFIG_DEBUG_UART_SHIFT), \
135a52cf086SLokesh Vutla CONFIG_DEBUG_UART_SHIFT)
136a52cf086SLokesh Vutla
1372f964aa7SSimon Glass /*
1382f964aa7SSimon Glass * Now define some functions - this should be inserted into the serial driver
1392f964aa7SSimon Glass */
1402f964aa7SSimon Glass #define DEBUG_UART_FUNCS \
1416bacc736Stim.chick \
1426bacc736Stim.chick static inline void _printch(int ch) \
1432f964aa7SSimon Glass { \
144b391d743SMasahiro Yamada if (ch == '\n') \
145b391d743SMasahiro Yamada _debug_uart_putc('\r'); \
1462f964aa7SSimon Glass _debug_uart_putc(ch); \
1472f964aa7SSimon Glass } \
1482f964aa7SSimon Glass \
1496bacc736Stim.chick void printch(int ch) \
1506bacc736Stim.chick { \
1516bacc736Stim.chick _printch(ch); \
1526bacc736Stim.chick } \
1536bacc736Stim.chick \
154034db995SJoseph Chen int debug_uart_getc(void)\
155034db995SJoseph Chen { \
156034db995SJoseph Chen return _debug_uart_getc(); \
157034db995SJoseph Chen } \
158034db995SJoseph Chen \
159034db995SJoseph Chen int debug_uart_tstc(void)\
160034db995SJoseph Chen { \
161034db995SJoseph Chen return _debug_uart_tstc(true); \
162034db995SJoseph Chen } \
163034db995SJoseph Chen \
164034db995SJoseph Chen int debug_uart_clrc(void)\
165034db995SJoseph Chen { \
166034db995SJoseph Chen return _debug_uart_clrc(); \
167034db995SJoseph Chen } \
168034db995SJoseph Chen \
169*a5d16e51SJoseph Chen int debug_uart_flushc(void)\
170*a5d16e51SJoseph Chen { \
171*a5d16e51SJoseph Chen return _debug_uart_flushc(); \
172*a5d16e51SJoseph Chen } \
173*a5d16e51SJoseph Chen \
174034db995SJoseph Chen int debug_uart_setbrg(void)\
175034db995SJoseph Chen { \
176034db995SJoseph Chen return _debug_uart_setbrg(); \
177034db995SJoseph Chen } \
178034db995SJoseph Chen \
179d0d73614SSimon Glass void printascii(const char *str) \
1802f964aa7SSimon Glass { \
1812f964aa7SSimon Glass while (*str) \
1826bacc736Stim.chick _printch(*str++); \
1832f964aa7SSimon Glass } \
1842f964aa7SSimon Glass \
1852f964aa7SSimon Glass static inline void printhex1(uint digit) \
1862f964aa7SSimon Glass { \
1872f964aa7SSimon Glass digit &= 0xf; \
1882f964aa7SSimon Glass _debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \
1892f964aa7SSimon Glass } \
1902f964aa7SSimon Glass \
1912f964aa7SSimon Glass static inline void printhex(uint value, int digits) \
1922f964aa7SSimon Glass { \
1932f964aa7SSimon Glass while (digits-- > 0) \
1942f964aa7SSimon Glass printhex1(value >> (4 * digits)); \
1952f964aa7SSimon Glass } \
1962f964aa7SSimon Glass \
197d0d73614SSimon Glass void printhex2(uint value) \
1982f964aa7SSimon Glass { \
1992f964aa7SSimon Glass printhex(value, 2); \
2002f964aa7SSimon Glass } \
2012f964aa7SSimon Glass \
202d0d73614SSimon Glass void printhex4(uint value) \
2032f964aa7SSimon Glass { \
2042f964aa7SSimon Glass printhex(value, 4); \
2052f964aa7SSimon Glass } \
2062f964aa7SSimon Glass \
207d0d73614SSimon Glass void printhex8(uint value) \
2082f964aa7SSimon Glass { \
2092f964aa7SSimon Glass printhex(value, 8); \
21097b05973SSimon Glass } \
21197b05973SSimon Glass \
212ab83a6feSCanYang He void printdec(uint value) \
213ab83a6feSCanYang He { \
214ab83a6feSCanYang He if (value > 10) { \
215ab83a6feSCanYang He printdec(value / 10); \
216ab83a6feSCanYang He value %= 10; \
217ab83a6feSCanYang He } else if (value == 10) { \
218ab83a6feSCanYang He _debug_uart_putc('1'); \
219ab83a6feSCanYang He value = 0; \
220ab83a6feSCanYang He } \
221ab83a6feSCanYang He _debug_uart_putc('0' + value); \
222ab83a6feSCanYang He } \
223ab83a6feSCanYang He \
22497b05973SSimon Glass void debug_uart_init(void) \
22597b05973SSimon Glass { \
2260e977bc1SSimon Glass board_debug_uart_init(); \
22797b05973SSimon Glass _debug_uart_init(); \
228c7fefcb9SSimon Glass _DEBUG_UART_ANNOUNCE \
22997b05973SSimon Glass } \
2302f964aa7SSimon Glass
2312f964aa7SSimon Glass #endif
232