162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * polling mode stateless debugging stuff, originally for NS16550 Serial Ports 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * c 2001 PPC 64 Team, IBM Corp 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/stdarg.h> 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/sched.h> 1162306a36Sopenharmony_ci#include <linux/console.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <asm/processor.h> 1462306a36Sopenharmony_ci#include <asm/udbg.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_civoid (*udbg_putc)(char c); 1762306a36Sopenharmony_civoid (*udbg_flush)(void); 1862306a36Sopenharmony_ciint (*udbg_getc)(void); 1962306a36Sopenharmony_ciint (*udbg_getc_poll)(void); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Early debugging facilities. You can enable _one_ of these via .config, 2362306a36Sopenharmony_ci * if you do so your kernel _will not boot_ on anything else. Be careful. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_civoid __init udbg_early_init(void) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci#if defined(CONFIG_PPC_EARLY_DEBUG_LPAR) 2862306a36Sopenharmony_ci /* For LPAR machines that have an HVC console on vterm 0 */ 2962306a36Sopenharmony_ci udbg_init_debug_lpar(); 3062306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI) 3162306a36Sopenharmony_ci /* For LPAR machines that have an HVSI console on vterm 0 */ 3262306a36Sopenharmony_ci udbg_init_debug_lpar_hvsi(); 3362306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_G5) 3462306a36Sopenharmony_ci /* For use on Apple G5 machines */ 3562306a36Sopenharmony_ci udbg_init_pmac_realmode(); 3662306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL) 3762306a36Sopenharmony_ci /* RTAS panel debug */ 3862306a36Sopenharmony_ci udbg_init_rtas_panel(); 3962306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE) 4062306a36Sopenharmony_ci /* RTAS console debug */ 4162306a36Sopenharmony_ci udbg_init_rtas_console(); 4262306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE) 4362306a36Sopenharmony_ci /* Maple real mode debug */ 4462306a36Sopenharmony_ci udbg_init_maple_realmode(); 4562306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE) 4662306a36Sopenharmony_ci udbg_init_pas_realmode(); 4762306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_BOOTX) 4862306a36Sopenharmony_ci udbg_init_btext(); 4962306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_44x) 5062306a36Sopenharmony_ci /* PPC44x debug */ 5162306a36Sopenharmony_ci udbg_init_44x_as1(); 5262306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_40x) 5362306a36Sopenharmony_ci /* PPC40x debug */ 5462306a36Sopenharmony_ci udbg_init_40x_realmode(); 5562306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_CPM) 5662306a36Sopenharmony_ci udbg_init_cpm(); 5762306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO) 5862306a36Sopenharmony_ci udbg_init_usbgecko(); 5962306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_MEMCONS) 6062306a36Sopenharmony_ci /* In memory console */ 6162306a36Sopenharmony_ci udbg_init_memcons(); 6262306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) 6362306a36Sopenharmony_ci udbg_init_ehv_bc(); 6462306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC) 6562306a36Sopenharmony_ci udbg_init_ps3gelic(); 6662306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_RAW) 6762306a36Sopenharmony_ci udbg_init_debug_opal_raw(); 6862306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI) 6962306a36Sopenharmony_ci udbg_init_debug_opal_hvsi(); 7062306a36Sopenharmony_ci#elif defined(CONFIG_PPC_EARLY_DEBUG_16550) 7162306a36Sopenharmony_ci udbg_init_debug_16550(); 7262306a36Sopenharmony_ci#endif 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#ifdef CONFIG_PPC_EARLY_DEBUG 7562306a36Sopenharmony_ci console_loglevel = CONSOLE_LOGLEVEL_DEBUG; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci register_early_udbg_console(); 7862306a36Sopenharmony_ci#endif 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* udbg library, used by xmon et al */ 8262306a36Sopenharmony_civoid udbg_puts(const char *s) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci if (udbg_putc) { 8562306a36Sopenharmony_ci char c; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (s && *s != '\0') { 8862306a36Sopenharmony_ci while ((c = *s++) != '\0') 8962306a36Sopenharmony_ci udbg_putc(c); 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (udbg_flush) 9362306a36Sopenharmony_ci udbg_flush(); 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci#if 0 9662306a36Sopenharmony_ci else { 9762306a36Sopenharmony_ci printk("%s", s); 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci#endif 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciint udbg_write(const char *s, int n) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci int remain = n; 10562306a36Sopenharmony_ci char c; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (!udbg_putc) 10862306a36Sopenharmony_ci return 0; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (s && *s != '\0') { 11162306a36Sopenharmony_ci while (((c = *s++) != '\0') && (remain-- > 0)) { 11262306a36Sopenharmony_ci udbg_putc(c); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (udbg_flush) 11762306a36Sopenharmony_ci udbg_flush(); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return n - remain; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define UDBG_BUFSIZE 256 12362306a36Sopenharmony_civoid udbg_printf(const char *fmt, ...) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci if (udbg_putc) { 12662306a36Sopenharmony_ci char buf[UDBG_BUFSIZE]; 12762306a36Sopenharmony_ci va_list args; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci va_start(args, fmt); 13062306a36Sopenharmony_ci vsnprintf(buf, UDBG_BUFSIZE, fmt, args); 13162306a36Sopenharmony_ci udbg_puts(buf); 13262306a36Sopenharmony_ci va_end(args); 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_civoid __init udbg_progress(char *s, unsigned short hex) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci udbg_puts(s); 13962306a36Sopenharmony_ci udbg_puts("\n"); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/* 14362306a36Sopenharmony_ci * Early boot console based on udbg 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_cistatic void udbg_console_write(struct console *con, const char *s, 14662306a36Sopenharmony_ci unsigned int n) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci udbg_write(s, n); 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic struct console udbg_console = { 15262306a36Sopenharmony_ci .name = "udbg", 15362306a36Sopenharmony_ci .write = udbg_console_write, 15462306a36Sopenharmony_ci .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME, 15562306a36Sopenharmony_ci .index = 0, 15662306a36Sopenharmony_ci}; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* 15962306a36Sopenharmony_ci * Called by setup_system after ppc_md->probe and ppc_md->early_init. 16062306a36Sopenharmony_ci * Call it again after setting udbg_putc in ppc_md->setup_arch. 16162306a36Sopenharmony_ci */ 16262306a36Sopenharmony_civoid __init register_early_udbg_console(void) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci if (early_console) 16562306a36Sopenharmony_ci return; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (!udbg_putc) 16862306a36Sopenharmony_ci return; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (strstr(boot_command_line, "udbg-immortal")) { 17162306a36Sopenharmony_ci printk(KERN_INFO "early console immortal !\n"); 17262306a36Sopenharmony_ci udbg_console.flags &= ~CON_BOOT; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci early_console = &udbg_console; 17562306a36Sopenharmony_ci register_console(&udbg_console); 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#if 0 /* if you want to use this as a regular output console */ 17962306a36Sopenharmony_ciconsole_initcall(register_udbg_console); 18062306a36Sopenharmony_ci#endif 181