summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/rtas.c
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2006-06-23 10:20:16 +0200
committerPaul Mackerras <paulus@samba.org>2006-06-28 03:59:48 +0200
commitcc46bb98c0d52695f26c239de701050660f5c79f (patch)
tree1b40e9db66de5c41c0b2fdf1db022f645a46a697 /arch/powerpc/kernel/rtas.c
parent[POWERPC] Setup RTAS values earlier, to enable rtas_call() earlier (diff)
downloadlinux-cc46bb98c0d52695f26c239de701050660f5c79f.tar.xz
linux-cc46bb98c0d52695f26c239de701050660f5c79f.zip
[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.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 061d8afd246e..4a4cb5598402 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;
}