1*83d290c5STom Rini /* SPDX-License-Identifier: GPL-2.0+ */
22f964aa7SSimon Glass /*
32f964aa7SSimon Glass * Early debug UART support
42f964aa7SSimon Glass *
52f964aa7SSimon Glass * (C) Copyright 2014 Google, Inc
62f964aa7SSimon Glass * Writte by Simon Glass <sjg@chromium.org>
72f964aa7SSimon Glass */
82f964aa7SSimon Glass
92f964aa7SSimon Glass #ifndef _DEBUG_UART_H
102f964aa7SSimon Glass #define _DEBUG_UART_H
112f964aa7SSimon Glass
122f964aa7SSimon Glass /*
132f964aa7SSimon Glass * The debug UART is intended for use very early in U-Boot to debug problems
142f964aa7SSimon Glass * when an ICE or other debug mechanism is not available.
152f964aa7SSimon Glass *
162f964aa7SSimon Glass * To use it you should:
172f964aa7SSimon Glass * - Make sure your UART supports this interface
182f964aa7SSimon Glass * - Enable CONFIG_DEBUG_UART
192f964aa7SSimon Glass * - Enable the CONFIG for your UART to tell it to provide this interface
202f964aa7SSimon Glass * (e.g. CONFIG_DEBUG_UART_NS16550)
212f964aa7SSimon Glass * - Define the required settings as needed (see below)
222f964aa7SSimon Glass * - Call debug_uart_init() before use
232f964aa7SSimon Glass * - Call printch() to output a character
242f964aa7SSimon Glass *
252f964aa7SSimon Glass * Depending on your platform it may be possible to use this UART before a
262f964aa7SSimon Glass * stack is available.
272f964aa7SSimon Glass *
282f964aa7SSimon Glass * If your UART does not support this interface you can probably add support
292f964aa7SSimon Glass * quite easily. Remember that you cannot use driver model and it is preferred
302f964aa7SSimon Glass * to use no stack.
312f964aa7SSimon Glass *
322f964aa7SSimon Glass * You must not use this UART once driver model is working and the serial
332f964aa7SSimon Glass * drivers are up and running (done in serial_init()). Otherwise the drivers
342f964aa7SSimon Glass * may conflict and you will get strange output.
352f964aa7SSimon Glass *
362f964aa7SSimon Glass *
372f964aa7SSimon Glass * To enable the debug UART in your serial driver:
382f964aa7SSimon Glass *
392f964aa7SSimon Glass * - #include <debug_uart.h>
4097b05973SSimon Glass * - Define _debug_uart_init(), trying to avoid using the stack
412f964aa7SSimon Glass * - Define _debug_uart_putc() as static inline (avoiding stack usage)
422f964aa7SSimon Glass * - Immediately afterwards, add DEBUG_UART_FUNCS to define the rest of the
432f964aa7SSimon Glass * functionality (printch(), etc.)
440e977bc1SSimon Glass *
450e977bc1SSimon Glass * If your board needs additional init for the UART to work, enable
460e977bc1SSimon Glass * CONFIG_DEBUG_UART_BOARD_INIT and write a function called
470e977bc1SSimon Glass * board_debug_uart_init() to perform that init. When debug_uart_init() is
480e977bc1SSimon Glass * called, the init will happen automatically.
492f964aa7SSimon Glass */
502f964aa7SSimon Glass
512f964aa7SSimon Glass /**
522f964aa7SSimon Glass * debug_uart_init() - Set up the debug UART ready for use
532f964aa7SSimon Glass *
542f964aa7SSimon Glass * This sets up the UART with the correct baud rate, etc.
552f964aa7SSimon Glass *
562f964aa7SSimon Glass * Available CONFIG is:
572f964aa7SSimon Glass *
582f964aa7SSimon Glass * - CONFIG_DEBUG_UART_BASE: Base address of UART
592f964aa7SSimon Glass * - CONFIG_BAUDRATE: Requested baud rate
602f964aa7SSimon Glass * - CONFIG_DEBUG_UART_CLOCK: Input clock for UART
612f964aa7SSimon Glass */
622f964aa7SSimon Glass void debug_uart_init(void);
632f964aa7SSimon Glass
640e977bc1SSimon Glass #ifdef CONFIG_DEBUG_UART_BOARD_INIT
650e977bc1SSimon Glass void board_debug_uart_init(void);
660e977bc1SSimon Glass #else
board_debug_uart_init(void)670e977bc1SSimon Glass static inline void board_debug_uart_init(void)
680e977bc1SSimon Glass {
690e977bc1SSimon Glass }
700e977bc1SSimon Glass #endif
710e977bc1SSimon Glass
722f964aa7SSimon Glass /**
732f964aa7SSimon Glass * printch() - Output a character to the debug UART
742f964aa7SSimon Glass *
752f964aa7SSimon Glass * @ch: Character to output
762f964aa7SSimon Glass */
77d0d73614SSimon Glass void printch(int ch);
782f964aa7SSimon Glass
792f964aa7SSimon Glass /**
802f964aa7SSimon Glass * printascii() - Output an ASCII string to the debug UART
812f964aa7SSimon Glass *
822f964aa7SSimon Glass * @str: String to output
832f964aa7SSimon Glass */
84d0d73614SSimon Glass void printascii(const char *str);
852f964aa7SSimon Glass
862f964aa7SSimon Glass /**
872f964aa7SSimon Glass * printhex2() - Output a 2-digit hex value
882f964aa7SSimon Glass *
892f964aa7SSimon Glass * @value: Value to output
902f964aa7SSimon Glass */
91d0d73614SSimon Glass void printhex2(uint value);
922f964aa7SSimon Glass
932f964aa7SSimon Glass /**
942f964aa7SSimon Glass * printhex4() - Output a 4-digit hex value
952f964aa7SSimon Glass *
962f964aa7SSimon Glass * @value: Value to output
972f964aa7SSimon Glass */
98d0d73614SSimon Glass void printhex4(uint value);
992f964aa7SSimon Glass
1002f964aa7SSimon Glass /**
1012f964aa7SSimon Glass * printhex8() - Output a 8-digit hex value
1022f964aa7SSimon Glass *
1032f964aa7SSimon Glass * @value: Value to output
1042f964aa7SSimon Glass */
105d0d73614SSimon Glass void printhex8(uint value);
1062f964aa7SSimon Glass
107c7fefcb9SSimon Glass #ifdef CONFIG_DEBUG_UART_ANNOUNCE
108c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE printascii("<debug_uart> ");
109c7fefcb9SSimon Glass #else
110c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE
111c7fefcb9SSimon Glass #endif
112c7fefcb9SSimon Glass
113a52cf086SLokesh Vutla #define serial_dout(reg, value) \
114a52cf086SLokesh Vutla serial_out_shift((char *)com_port + \
115a52cf086SLokesh Vutla ((char *)reg - (char *)com_port) * \
116a52cf086SLokesh Vutla (1 << CONFIG_DEBUG_UART_SHIFT), \
117a52cf086SLokesh Vutla CONFIG_DEBUG_UART_SHIFT, value)
118a52cf086SLokesh Vutla #define serial_din(reg) \
119a52cf086SLokesh Vutla serial_in_shift((char *)com_port + \
120a52cf086SLokesh Vutla ((char *)reg - (char *)com_port) * \
121a52cf086SLokesh Vutla (1 << CONFIG_DEBUG_UART_SHIFT), \
122a52cf086SLokesh Vutla CONFIG_DEBUG_UART_SHIFT)
123a52cf086SLokesh Vutla
1242f964aa7SSimon Glass /*
1252f964aa7SSimon Glass * Now define some functions - this should be inserted into the serial driver
1262f964aa7SSimon Glass */
1272f964aa7SSimon Glass #define DEBUG_UART_FUNCS \
1286bacc736Stim.chick \
1296bacc736Stim.chick static inline void _printch(int ch) \
1302f964aa7SSimon Glass { \
131b391d743SMasahiro Yamada if (ch == '\n') \
132b391d743SMasahiro Yamada _debug_uart_putc('\r'); \
1332f964aa7SSimon Glass _debug_uart_putc(ch); \
1342f964aa7SSimon Glass } \
1352f964aa7SSimon Glass \
1366bacc736Stim.chick void printch(int ch) \
1376bacc736Stim.chick { \
1386bacc736Stim.chick _printch(ch); \
1396bacc736Stim.chick } \
1406bacc736Stim.chick \
141d0d73614SSimon Glass void printascii(const char *str) \
1422f964aa7SSimon Glass { \
1432f964aa7SSimon Glass while (*str) \
1446bacc736Stim.chick _printch(*str++); \
1452f964aa7SSimon Glass } \
1462f964aa7SSimon Glass \
1472f964aa7SSimon Glass static inline void printhex1(uint digit) \
1482f964aa7SSimon Glass { \
1492f964aa7SSimon Glass digit &= 0xf; \
1502f964aa7SSimon Glass _debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \
1512f964aa7SSimon Glass } \
1522f964aa7SSimon Glass \
1532f964aa7SSimon Glass static inline void printhex(uint value, int digits) \
1542f964aa7SSimon Glass { \
1552f964aa7SSimon Glass while (digits-- > 0) \
1562f964aa7SSimon Glass printhex1(value >> (4 * digits)); \
1572f964aa7SSimon Glass } \
1582f964aa7SSimon Glass \
159d0d73614SSimon Glass void printhex2(uint value) \
1602f964aa7SSimon Glass { \
1612f964aa7SSimon Glass printhex(value, 2); \
1622f964aa7SSimon Glass } \
1632f964aa7SSimon Glass \
164d0d73614SSimon Glass void printhex4(uint value) \
1652f964aa7SSimon Glass { \
1662f964aa7SSimon Glass printhex(value, 4); \
1672f964aa7SSimon Glass } \
1682f964aa7SSimon Glass \
169d0d73614SSimon Glass void printhex8(uint value) \
1702f964aa7SSimon Glass { \
1712f964aa7SSimon Glass printhex(value, 8); \
17297b05973SSimon Glass } \
17397b05973SSimon Glass \
17497b05973SSimon Glass void debug_uart_init(void) \
17597b05973SSimon Glass { \
1760e977bc1SSimon Glass board_debug_uart_init(); \
17797b05973SSimon Glass _debug_uart_init(); \
178c7fefcb9SSimon Glass _DEBUG_UART_ANNOUNCE \
17997b05973SSimon Glass } \
1802f964aa7SSimon Glass
1812f964aa7SSimon Glass #endif
182