diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2006-06-23 18:20:16 +1000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-06-28 11:59:48 +1000 |
commit | cc46bb98c0d52695f26c239de701050660f5c79f (patch) | |
tree | 1b40e9db66de5c41c0b2fdf1db022f645a46a697 /arch/powerpc/kernel/rtas.c | |
parent | 458148c00b97864a27ecf528a1d45a8e5ebd9bbc (diff) | |
download | op-kernel-dev-cc46bb98c0d52695f26c239de701050660f5c79f.zip op-kernel-dev-cc46bb98c0d52695f26c239de701050660f5c79f.tar.gz |
[POWERPC] Add udbg support for RTAS console
Add udbg hooks for the RTAS console, based on the RTAS put-term-char
and get-term-char calls. Along with my previous patches, this should
enable debugging as soon as early_init_dt_scan_rtas() is called.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 061d8af..4a4cb55 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -109,11 +109,71 @@ static void call_rtas_display_status_delay(char c) } } -void __init udbg_init_rtas(void) +void __init udbg_init_rtas_panel(void) { udbg_putc = call_rtas_display_status_delay; } +#ifdef CONFIG_UDBG_RTAS_CONSOLE + +/* If you think you're dying before early_init_dt_scan_rtas() does its + * work, you can hard code the token values for your firmware here and + * hardcode rtas.base/entry etc. + */ +static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE; +static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE; + +static void udbg_rtascon_putc(char c) +{ + int tries; + + if (!rtas.base) + return; + + /* Add CRs before LFs */ + if (c == '\n') + udbg_rtascon_putc('\r'); + + /* if there is more than one character to be displayed, wait a bit */ + for (tries = 0; tries < 16; tries++) { + if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0) + break; + udelay(1000); + } +} + +static int udbg_rtascon_getc_poll(void) +{ + int c; + + if (!rtas.base) + return -1; + + if (rtas_call(rtas_getchar_token, 0, 2, &c)) + return -1; + + return c; +} + +static int udbg_rtascon_getc(void) +{ + int c; + + while ((c = udbg_rtascon_getc_poll()) == -1) + ; + + return c; +} + + +void __init udbg_init_rtas_console(void) +{ + udbg_putc = udbg_rtascon_putc; + udbg_getc = udbg_rtascon_getc; + udbg_getc_poll = udbg_rtascon_getc_poll; +} +#endif /* CONFIG_UDBG_RTAS_CONSOLE */ + void rtas_progress(char *s, unsigned short hex) { struct device_node *root; @@ -820,6 +880,16 @@ int __init early_init_dt_scan_rtas(unsigned long node, rtas.size = *sizep; } +#ifdef CONFIG_UDBG_RTAS_CONSOLE + basep = of_get_flat_dt_prop(node, "put-term-char", NULL); + if (basep) + rtas_putchar_token = *basep; + + basep = of_get_flat_dt_prop(node, "get-term-char", NULL); + if (basep) + rtas_getchar_token = *basep; +#endif + /* break now */ return 1; } |