1*2f964aa7SSimon Glass /* 2*2f964aa7SSimon Glass * Early debug UART support 3*2f964aa7SSimon Glass * 4*2f964aa7SSimon Glass * (C) Copyright 2014 Google, Inc 5*2f964aa7SSimon Glass * Writte by Simon Glass <sjg@chromium.org> 6*2f964aa7SSimon Glass * 7*2f964aa7SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 8*2f964aa7SSimon Glass */ 9*2f964aa7SSimon Glass 10*2f964aa7SSimon Glass #ifndef _DEBUG_UART_H 11*2f964aa7SSimon Glass #define _DEBUG_UART_H 12*2f964aa7SSimon Glass 13*2f964aa7SSimon Glass #include <linux/linkage.h> 14*2f964aa7SSimon Glass 15*2f964aa7SSimon Glass /* 16*2f964aa7SSimon Glass * The debug UART is intended for use very early in U-Boot to debug problems 17*2f964aa7SSimon Glass * when an ICE or other debug mechanism is not available. 18*2f964aa7SSimon Glass * 19*2f964aa7SSimon Glass * To use it you should: 20*2f964aa7SSimon Glass * - Make sure your UART supports this interface 21*2f964aa7SSimon Glass * - Enable CONFIG_DEBUG_UART 22*2f964aa7SSimon Glass * - Enable the CONFIG for your UART to tell it to provide this interface 23*2f964aa7SSimon Glass * (e.g. CONFIG_DEBUG_UART_NS16550) 24*2f964aa7SSimon Glass * - Define the required settings as needed (see below) 25*2f964aa7SSimon Glass * - Call debug_uart_init() before use 26*2f964aa7SSimon Glass * - Call printch() to output a character 27*2f964aa7SSimon Glass * 28*2f964aa7SSimon Glass * Depending on your platform it may be possible to use this UART before a 29*2f964aa7SSimon Glass * stack is available. 30*2f964aa7SSimon Glass * 31*2f964aa7SSimon Glass * If your UART does not support this interface you can probably add support 32*2f964aa7SSimon Glass * quite easily. Remember that you cannot use driver model and it is preferred 33*2f964aa7SSimon Glass * to use no stack. 34*2f964aa7SSimon Glass * 35*2f964aa7SSimon Glass * You must not use this UART once driver model is working and the serial 36*2f964aa7SSimon Glass * drivers are up and running (done in serial_init()). Otherwise the drivers 37*2f964aa7SSimon Glass * may conflict and you will get strange output. 38*2f964aa7SSimon Glass * 39*2f964aa7SSimon Glass * 40*2f964aa7SSimon Glass * To enable the debug UART in your serial driver: 41*2f964aa7SSimon Glass * 42*2f964aa7SSimon Glass * - #include <debug_uart.h> 43*2f964aa7SSimon Glass * - Define debug_uart_init(), trying to avoid using the stack 44*2f964aa7SSimon Glass * - Define _debug_uart_putc() as static inline (avoiding stack usage) 45*2f964aa7SSimon Glass * - Immediately afterwards, add DEBUG_UART_FUNCS to define the rest of the 46*2f964aa7SSimon Glass * functionality (printch(), etc.) 47*2f964aa7SSimon Glass */ 48*2f964aa7SSimon Glass 49*2f964aa7SSimon Glass /** 50*2f964aa7SSimon Glass * debug_uart_init() - Set up the debug UART ready for use 51*2f964aa7SSimon Glass * 52*2f964aa7SSimon Glass * This sets up the UART with the correct baud rate, etc. 53*2f964aa7SSimon Glass * 54*2f964aa7SSimon Glass * Available CONFIG is: 55*2f964aa7SSimon Glass * 56*2f964aa7SSimon Glass * - CONFIG_DEBUG_UART_BASE: Base address of UART 57*2f964aa7SSimon Glass * - CONFIG_BAUDRATE: Requested baud rate 58*2f964aa7SSimon Glass * - CONFIG_DEBUG_UART_CLOCK: Input clock for UART 59*2f964aa7SSimon Glass */ 60*2f964aa7SSimon Glass void debug_uart_init(void); 61*2f964aa7SSimon Glass 62*2f964aa7SSimon Glass /** 63*2f964aa7SSimon Glass * printch() - Output a character to the debug UART 64*2f964aa7SSimon Glass * 65*2f964aa7SSimon Glass * @ch: Character to output 66*2f964aa7SSimon Glass */ 67*2f964aa7SSimon Glass asmlinkage void printch(int ch); 68*2f964aa7SSimon Glass 69*2f964aa7SSimon Glass /** 70*2f964aa7SSimon Glass * printascii() - Output an ASCII string to the debug UART 71*2f964aa7SSimon Glass * 72*2f964aa7SSimon Glass * @str: String to output 73*2f964aa7SSimon Glass */ 74*2f964aa7SSimon Glass asmlinkage void printascii(const char *str); 75*2f964aa7SSimon Glass 76*2f964aa7SSimon Glass /** 77*2f964aa7SSimon Glass * printhex2() - Output a 2-digit hex value 78*2f964aa7SSimon Glass * 79*2f964aa7SSimon Glass * @value: Value to output 80*2f964aa7SSimon Glass */ 81*2f964aa7SSimon Glass asmlinkage void printhex2(uint value); 82*2f964aa7SSimon Glass 83*2f964aa7SSimon Glass /** 84*2f964aa7SSimon Glass * printhex4() - Output a 4-digit hex value 85*2f964aa7SSimon Glass * 86*2f964aa7SSimon Glass * @value: Value to output 87*2f964aa7SSimon Glass */ 88*2f964aa7SSimon Glass asmlinkage void printhex4(uint value); 89*2f964aa7SSimon Glass 90*2f964aa7SSimon Glass /** 91*2f964aa7SSimon Glass * printhex8() - Output a 8-digit hex value 92*2f964aa7SSimon Glass * 93*2f964aa7SSimon Glass * @value: Value to output 94*2f964aa7SSimon Glass */ 95*2f964aa7SSimon Glass asmlinkage void printhex8(uint value); 96*2f964aa7SSimon Glass 97*2f964aa7SSimon Glass /* 98*2f964aa7SSimon Glass * Now define some functions - this should be inserted into the serial driver 99*2f964aa7SSimon Glass */ 100*2f964aa7SSimon Glass #define DEBUG_UART_FUNCS \ 101*2f964aa7SSimon Glass asmlinkage void printch(int ch) \ 102*2f964aa7SSimon Glass { \ 103*2f964aa7SSimon Glass _debug_uart_putc(ch); \ 104*2f964aa7SSimon Glass } \ 105*2f964aa7SSimon Glass \ 106*2f964aa7SSimon Glass asmlinkage void printascii(const char *str) \ 107*2f964aa7SSimon Glass { \ 108*2f964aa7SSimon Glass while (*str) \ 109*2f964aa7SSimon Glass _debug_uart_putc(*str++); \ 110*2f964aa7SSimon Glass } \ 111*2f964aa7SSimon Glass \ 112*2f964aa7SSimon Glass static inline void printhex1(uint digit) \ 113*2f964aa7SSimon Glass { \ 114*2f964aa7SSimon Glass digit &= 0xf; \ 115*2f964aa7SSimon Glass _debug_uart_putc(digit > 9 ? digit - 10 + 'a' : digit + '0'); \ 116*2f964aa7SSimon Glass } \ 117*2f964aa7SSimon Glass \ 118*2f964aa7SSimon Glass static inline void printhex(uint value, int digits) \ 119*2f964aa7SSimon Glass { \ 120*2f964aa7SSimon Glass while (digits-- > 0) \ 121*2f964aa7SSimon Glass printhex1(value >> (4 * digits)); \ 122*2f964aa7SSimon Glass } \ 123*2f964aa7SSimon Glass \ 124*2f964aa7SSimon Glass asmlinkage void printhex2(uint value) \ 125*2f964aa7SSimon Glass { \ 126*2f964aa7SSimon Glass printhex(value, 2); \ 127*2f964aa7SSimon Glass } \ 128*2f964aa7SSimon Glass \ 129*2f964aa7SSimon Glass asmlinkage void printhex4(uint value) \ 130*2f964aa7SSimon Glass { \ 131*2f964aa7SSimon Glass printhex(value, 4); \ 132*2f964aa7SSimon Glass } \ 133*2f964aa7SSimon Glass \ 134*2f964aa7SSimon Glass asmlinkage void printhex8(uint value) \ 135*2f964aa7SSimon Glass { \ 136*2f964aa7SSimon Glass printhex(value, 8); \ 137*2f964aa7SSimon Glass } 138*2f964aa7SSimon Glass 139*2f964aa7SSimon Glass #endif 140