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 108c7fefcb9SSimon Glass #ifdef CONFIG_DEBUG_UART_ANNOUNCE 109c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE printascii("<debug_uart> "); 110c7fefcb9SSimon Glass #else 111c7fefcb9SSimon Glass #define _DEBUG_UART_ANNOUNCE 112c7fefcb9SSimon Glass #endif 113c7fefcb9SSimon Glass 1142f964aa7SSimon Glass /* 1152f964aa7SSimon Glass * Now define some functions - this should be inserted into the serial driver 1162f964aa7SSimon Glass */ 1172f964aa7SSimon Glass #define DEBUG_UART_FUNCS \ 118d0d73614SSimon Glass void printch(int ch) \ 1192f964aa7SSimon Glass { \ 120*b391d743SMasahiro Yamada if (ch == '\n') \ 121*b391d743SMasahiro Yamada _debug_uart_putc('\r'); \ 1222f964aa7SSimon Glass _debug_uart_putc(ch); \ 1232f964aa7SSimon Glass } \ 1242f964aa7SSimon Glass \ 125d0d73614SSimon Glass void printascii(const char *str) \ 1262f964aa7SSimon Glass { \ 1272f964aa7SSimon Glass while (*str) \ 128*b391d743SMasahiro Yamada printch(*str++); \ 1292f964aa7SSimon Glass } \ 1302f964aa7SSimon Glass \ 1312f964aa7SSimon Glass static inline void printhex1(uint digit) \ 1322f964aa7SSimon Glass { \ 1332f964aa7SSimon Glass digit &= 0xf; \ 1342f964aa7SSimon Glass _debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \ 1352f964aa7SSimon Glass } \ 1362f964aa7SSimon Glass \ 1372f964aa7SSimon Glass static inline void printhex(uint value, int digits) \ 1382f964aa7SSimon Glass { \ 1392f964aa7SSimon Glass while (digits-- > 0) \ 1402f964aa7SSimon Glass printhex1(value >> (4 * digits)); \ 1412f964aa7SSimon Glass } \ 1422f964aa7SSimon Glass \ 143d0d73614SSimon Glass void printhex2(uint value) \ 1442f964aa7SSimon Glass { \ 1452f964aa7SSimon Glass printhex(value, 2); \ 1462f964aa7SSimon Glass } \ 1472f964aa7SSimon Glass \ 148d0d73614SSimon Glass void printhex4(uint value) \ 1492f964aa7SSimon Glass { \ 1502f964aa7SSimon Glass printhex(value, 4); \ 1512f964aa7SSimon Glass } \ 1522f964aa7SSimon Glass \ 153d0d73614SSimon Glass void printhex8(uint value) \ 1542f964aa7SSimon Glass { \ 1552f964aa7SSimon Glass printhex(value, 8); \ 15697b05973SSimon Glass } \ 15797b05973SSimon Glass \ 15897b05973SSimon Glass void debug_uart_init(void) \ 15997b05973SSimon Glass { \ 1600e977bc1SSimon Glass board_debug_uart_init(); \ 16197b05973SSimon Glass _debug_uart_init(); \ 162c7fefcb9SSimon Glass _DEBUG_UART_ANNOUNCE \ 16397b05973SSimon Glass } \ 1642f964aa7SSimon Glass 1652f964aa7SSimon Glass #endif 166