
This series adds debug UART infrastructure which can in principle be used on any architecture. It works best with those that don't need a stack to call functions (e.g. ARM, PowerPC).
This came up in a discussion on the mailing list here:
https://patchwork.ozlabs.org/patch/384613/
My concerns at the time were: - it doesn't need to be written in assembler - it doesn't need to be ARM-specific - it only supports one serial driver
This potentially creates a problem where to support n architectures and m serial drivers we need n * m lots of assembler-coded functions. For example, in Linux for ARM we have:
../plat-spear/include/plat/debug-macro.S ../mach-s5pc100/include/mach/debug-macro.S ../mach-shark/include/mach/debug-macro.S ../mach-spear3xx/include/mach/debug-macro.S ../mach-sa1100/include/mach/debug-macro.S ../mach-l7200/include/mach/debug-macro.S ../mach-mv78xx0/include/mach/debug-macro.S ../mach-realview/include/mach/debug-macro.S ../mach-mmp/include/mach/debug-macro.S ../mach-s3c64xx/include/mach/debug-macro.S ../mach-s5pv210/include/mach/debug-macro.S ../mach-clps711x/include/mach/debug-macro.S ../mach-versatile/include/mach/debug-macro.S ../mach-iop32x/include/mach/debug-macro.S ../mach-ebsa110/include/mach/debug-macro.S ../mach-ux500/include/mach/debug-macro.S ../mach-orion5x/include/mach/debug-macro.S ../mach-lpc32xx/include/mach/debug-macro.S ../mach-vt8500/include/mach/debug-macro.S ../mach-rpc/include/mach/debug-macro.S ../mach-kirkwood/include/mach/debug-macro.S ../mach-spear6xx/include/mach/debug-macro.S ../mach-footbridge/include/mach/debug-macro.S ../mach-davinci/include/mach/debug-macro.S ../plat-samsung/include/plat/debug-macro.S ../mach-spear13xx/include/mach/debug-macro.S ../mach-exynos/include/mach/debug-macro.S ../mach-exynos/include/mach/regs-debug.h ../mach-dove/include/mach/debug-macro.S ../mach-omap1/include/mach/debug-macro.S ../mach-u300/include/mach/debug-macro.S ../mach-bcm2835/include/mach/debug-macro.S ../mach-h720x/include/mach/debug-macro.S ../mach-ep93xx/include/mach/debug-macro.S ../mach-gemini/include/mach/debug-macro.S ../mach-s3c24xx/include/mach/debug-macro.S ../mach-at91/include/mach/debug-macro.S ../mach-ixp4xx/include/mach/debug-macro.S ../mach-nomadik/include/mach/debug-macro.S ../mach-cns3xxx/include/mach/debug-macro.S ../mach-mxs/include/mach/debug-macro.S ../mach-iop33x/include/mach/debug-macro.S ../mach-ks8695/include/mach/debug-macro.S ../mach-netx/include/mach/debug-macro.S ../mach-iop13xx/include/mach/debug-macro.S ../mach-integrator/include/mach/debug-macro.S ../mach-msm/include/mach/debug-macro.S ../mach-pxa/include/mach/debug-macro.S ../mach-s5p64x0/include/mach/debug-macro.S ../mach-prima2/include/mach/debug-macro.S ../mach-omap2/include/mach/debug-macro.S
This series provides a possible alternative. It works by allowing any serial driver to export one init function and provide a putc() function. These can be used to output debug data before the real serial driver is available. Only one debug UART can be used at a time, and its address and serial clock must be provided statically in Kconfig.
This implementation does not depend on driver model being set up, and it is possible for it to operate without a stack on some architectures (e.g. PowerPC, ARM). It provides the same features as the ARM-specific debug.S but with more UART and architecture support.
As an example, here is the code generated for printch() by gcc 4.8 on ARM using the ns16550 driver (Tegra Seaboard):
0013b3b0 <printch>: 13b3b0: e59f201c ldr r2, [pc, #28] ; 13b3d4 <printch+0x24> 13b3b4: e5d23305 ldrb r3, [r2, #773] ; 0x305 13b3b8: e6ef3073 uxtb r3, r3 13b3bc: e3130020 tst r3, #32 13b3c0: 0afffffb beq 13b3b4 <printch+0x4> 13b3c4: e6ef0070 uxtb r0, r0 13b3c8: e59f3004 ldr r3, [pc, #4] ; 13b3d4 <printch+0x24> 13b3cc: e5c30300 strb r0, [r3, #768] ; 0x300 13b3d0: e12fff1e bx lr 13b3d4: 70006000 .word 0x70006000
The PowerPC 4xx code (ELDK-5.3) for printhex8() is this:
0102db44 <printhex8>: 102db44: 3c c0 ef 60 lis r6,-4256 102db48: 3c e0 ef 60 lis r7,-4256 102db4c: 39 20 00 1c li r9,28 102db50: 60 c6 03 05 ori r6,r6,773 102db54: 60 e7 03 00 ori r7,r7,768 102db58: 7c 6a 4c 30 srw r10,r3,r9 102db5c: 55 4a 07 3e clrlwi r10,r10,28 102db60: 2b 8a 00 09 cmplwi cr7,r10,9 102db64: 39 0a 00 30 addi r8,r10,48 102db68: 40 9d 00 08 ble- cr7,102db70 <printhex8+0x2c> 102db6c: 39 0a 00 57 addi r8,r10,87 102db70: 7c 00 04 ac sync 102db74: 89 46 00 00 lbz r10,0(r6) 102db78: 0c 0a 00 00 twi 0,r10,0 102db7c: 4c 00 01 2c isync 102db80: 55 4a 06 b4 rlwinm r10,r10,0,26,26 102db84: 71 45 00 ff andi. r5,r10,255 102db88: 41 82 ff e8 beq+ 102db70 <printhex8+0x2c> 102db8c: 55 08 06 3e clrlwi r8,r8,24 102db90: 7c 00 04 ac sync 102db94: 99 07 00 00 stb r8,0(r7) 102db98: 2f 89 00 00 cmpwi cr7,r9,0 102db9c: 39 29 ff fc addi r9,r9,-4 102dba0: 40 9e ff b8 bne+ cr7,102db58 <printhex8+0x14> 102dba4: 4e 80 00 20 blr
However this is somewhat toolchain-dependent. For example, some toolchains may spill over the available registers and use the stack. It would be nice to have a way to tell gcc not to do that.
This is not offered as a catch-all solution, but I believe it has value for many use cases.
Changes in v2: - Add asmlinkage to exported functions - Split series out on its own - Add x86 support (asmlinkage, so it still needs a stack at present) - Add better cover letter
Simon Glass (3): serial: Support an early UART for debugging serial: ns16550: Add access functions that don't need platdata serial: ns16550: Support debug UART
drivers/serial/Kconfig | 59 ++++++++++++++++++++ drivers/serial/ns16550.c | 98 ++++++++++++++++++++++++++------- include/debug_uart.h | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+), 20 deletions(-) create mode 100644 include/debug_uart.h