xref: /rk3399_rockchip-uboot/include/debug_uart.h (revision ab83a6fe5812f67d3b3e398bb083b48c0b4c5fad)
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
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);
792f964aa7SSimon Glass 
802f964aa7SSimon Glass /**
812f964aa7SSimon Glass  * printascii() - Output an ASCII string to the debug UART
822f964aa7SSimon Glass  *
832f964aa7SSimon Glass  * @str:	String to output
842f964aa7SSimon Glass  */
85d0d73614SSimon Glass void printascii(const char *str);
862f964aa7SSimon Glass 
872f964aa7SSimon Glass /**
882f964aa7SSimon Glass  * printhex2() - Output a 2-digit hex value
892f964aa7SSimon Glass  *
902f964aa7SSimon Glass  * @value:	Value to output
912f964aa7SSimon Glass  */
92d0d73614SSimon Glass void printhex2(uint value);
932f964aa7SSimon Glass 
942f964aa7SSimon Glass /**
952f964aa7SSimon Glass  * printhex4() - Output a 4-digit hex value
962f964aa7SSimon Glass  *
972f964aa7SSimon Glass  * @value:	Value to output
982f964aa7SSimon Glass  */
99d0d73614SSimon Glass void printhex4(uint value);
1002f964aa7SSimon Glass 
1012f964aa7SSimon Glass /**
1022f964aa7SSimon Glass  * printhex8() - Output a 8-digit hex value
1032f964aa7SSimon Glass  *
1042f964aa7SSimon Glass  * @value:	Value to output
1052f964aa7SSimon Glass  */
106d0d73614SSimon Glass void printhex8(uint value);
1072f964aa7SSimon Glass 
108*ab83a6feSCanYang He /**
109*ab83a6feSCanYang He  * printdec() - Output a decimalism value
110*ab83a6feSCanYang He  *
111*ab83a6feSCanYang He  * @value:	Value to output
112*ab83a6feSCanYang He  */
113*ab83a6feSCanYang He void printdec(uint value);
114*ab83a6feSCanYang He 
115c7fefcb9SSimon Glass #ifdef CONFIG_DEBUG_UART_ANNOUNCE
116c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE	printascii("<debug_uart> ");
117c7fefcb9SSimon Glass #else
118c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE
119c7fefcb9SSimon Glass #endif
120c7fefcb9SSimon Glass 
121a52cf086SLokesh Vutla #define serial_dout(reg, value)	\
122a52cf086SLokesh Vutla 	serial_out_shift((char *)com_port + \
123a52cf086SLokesh Vutla 		((char *)reg - (char *)com_port) * \
124a52cf086SLokesh Vutla 			(1 << CONFIG_DEBUG_UART_SHIFT), \
125a52cf086SLokesh Vutla 		CONFIG_DEBUG_UART_SHIFT, value)
126a52cf086SLokesh Vutla #define serial_din(reg) \
127a52cf086SLokesh Vutla 	serial_in_shift((char *)com_port + \
128a52cf086SLokesh Vutla 		((char *)reg - (char *)com_port) * \
129a52cf086SLokesh Vutla 			(1 << CONFIG_DEBUG_UART_SHIFT), \
130a52cf086SLokesh Vutla 		CONFIG_DEBUG_UART_SHIFT)
131a52cf086SLokesh Vutla 
1322f964aa7SSimon Glass /*
1332f964aa7SSimon Glass  * Now define some functions - this should be inserted into the serial driver
1342f964aa7SSimon Glass  */
1352f964aa7SSimon Glass #define DEBUG_UART_FUNCS \
1366bacc736Stim.chick \
1376bacc736Stim.chick 	static inline void _printch(int ch) \
1382f964aa7SSimon Glass 	{ \
139b391d743SMasahiro Yamada 		if (ch == '\n') \
140b391d743SMasahiro Yamada 			_debug_uart_putc('\r'); \
1412f964aa7SSimon Glass 		_debug_uart_putc(ch); \
1422f964aa7SSimon Glass 	} \
1432f964aa7SSimon Glass \
1446bacc736Stim.chick 	void printch(int ch) \
1456bacc736Stim.chick 	{ \
1466bacc736Stim.chick 		_printch(ch); \
1476bacc736Stim.chick 	} \
1486bacc736Stim.chick \
149d0d73614SSimon Glass 	void printascii(const char *str) \
1502f964aa7SSimon Glass 	{ \
1512f964aa7SSimon Glass 		while (*str) \
1526bacc736Stim.chick 			_printch(*str++); \
1532f964aa7SSimon Glass 	} \
1542f964aa7SSimon Glass \
1552f964aa7SSimon Glass 	static inline void printhex1(uint digit) \
1562f964aa7SSimon Glass 	{ \
1572f964aa7SSimon Glass 		digit &= 0xf; \
1582f964aa7SSimon Glass 		_debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \
1592f964aa7SSimon Glass 	} \
1602f964aa7SSimon Glass \
1612f964aa7SSimon Glass 	static inline void printhex(uint value, int digits) \
1622f964aa7SSimon Glass 	{ \
1632f964aa7SSimon Glass 		while (digits-- > 0) \
1642f964aa7SSimon Glass 			printhex1(value >> (4 * digits)); \
1652f964aa7SSimon Glass 	} \
1662f964aa7SSimon Glass \
167d0d73614SSimon Glass 	void printhex2(uint value) \
1682f964aa7SSimon Glass 	{ \
1692f964aa7SSimon Glass 		printhex(value, 2); \
1702f964aa7SSimon Glass 	} \
1712f964aa7SSimon Glass \
172d0d73614SSimon Glass 	void printhex4(uint value) \
1732f964aa7SSimon Glass 	{ \
1742f964aa7SSimon Glass 		printhex(value, 4); \
1752f964aa7SSimon Glass 	} \
1762f964aa7SSimon Glass \
177d0d73614SSimon Glass 	void printhex8(uint value) \
1782f964aa7SSimon Glass 	{ \
1792f964aa7SSimon Glass 		printhex(value, 8); \
18097b05973SSimon Glass 	} \
18197b05973SSimon Glass \
182*ab83a6feSCanYang He 	void printdec(uint value) \
183*ab83a6feSCanYang He 	{ \
184*ab83a6feSCanYang He 		if (value > 10) { \
185*ab83a6feSCanYang He 			printdec(value / 10); \
186*ab83a6feSCanYang He 			value %= 10; \
187*ab83a6feSCanYang He 		} else if (value == 10) { \
188*ab83a6feSCanYang He 			_debug_uart_putc('1'); \
189*ab83a6feSCanYang He 			value = 0; \
190*ab83a6feSCanYang He 		} \
191*ab83a6feSCanYang He 		_debug_uart_putc('0' + value); \
192*ab83a6feSCanYang He 	} \
193*ab83a6feSCanYang He \
19497b05973SSimon Glass 	void debug_uart_init(void) \
19597b05973SSimon Glass 	{ \
1960e977bc1SSimon Glass 		board_debug_uart_init(); \
19797b05973SSimon Glass 		_debug_uart_init(); \
198c7fefcb9SSimon Glass 		_DEBUG_UART_ANNOUNCE \
19997b05973SSimon Glass 	} \
2002f964aa7SSimon Glass 
2012f964aa7SSimon Glass #endif
202