diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-09-19 17:44:59 (GMT) |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-09-20 06:09:54 (GMT) |
commit | daea1175a9f0f70eab5b33e2827d57ba8c686816 (patch) | |
tree | aac48bd8bdfb9c7ee8e3e5058aea07e04e105da3 /arch | |
parent | 6e35d5dac0c83ebb616ff3b9c2d6155c9a9ccb86 (diff) | |
download | linux-daea1175a9f0f70eab5b33e2827d57ba8c686816.tar.xz |
powerpc/powernv: Support for OPAL console
This adds a udbg and an hvc console backend for supporting a console
using the OPAL console interfaces.
On OPAL v1 we have hvc0 mapped to whatever console the system was
configured for (network or hvsi serial port) via the service
processor.
On OPAL v2 we have hvcN mapped to the Nth console provided by OPAL
which generally corresponds to:
hvc0 : network console (raw protocol)
hvc1 : serial port S1 (hvsi)
hvc2 : serial port S2 (hvsi)
Note: At this point, early debug console only works with OPAL v1
and shouldn't be enabled in a normal kernel.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/Kconfig.debug | 31 | ||||
-rw-r--r-- | arch/powerpc/include/asm/opal.h | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/udbg.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 14 | ||||
-rw-r--r-- | arch/powerpc/kernel/udbg.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 31 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/setup.c | 14 |
7 files changed, 81 insertions, 20 deletions
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 06eb62b..1b8a9c9 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -265,8 +265,27 @@ config PPC_EARLY_DEBUG_PS3GELIC Select this to enable early debugging for the PlayStation3 via UDP broadcasts sent out through the Ethernet port. +config PPC_EARLY_DEBUG_OPAL_RAW + bool "OPAL raw console" + depends on HVC_OPAL + help + Select this to enable early debugging for the PowerNV platform + using a "raw" console + +config PPC_EARLY_DEBUG_OPAL_HVSI + bool "OPAL hvsi console" + depends on HVC_OPAL + help + Select this to enable early debugging for the PowerNV platform + using an "hvsi" console + endchoice +config PPC_EARLY_DEBUG_OPAL + def_bool y + depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI + + config PPC_EARLY_DEBUG_HVSI_VTERMNO hex "vterm number to use with early debug HVSI" depends on PPC_EARLY_DEBUG_LPAR_HVSI @@ -275,6 +294,18 @@ config PPC_EARLY_DEBUG_HVSI_VTERMNO You probably want 0x30000000 for your first serial port and 0x30000001 for your second one +config PPC_EARLY_DEBUG_OPAL_VTERMNO + hex "vterm number to use with OPAL early debug" + depends on PPC_EARLY_DEBUG_OPAL + default "0" + help + This correspond to which /dev/hvcN you want to use for early + debug. + + On OPAL v1 (takeover) this should always be 0 + On OPAL v2, this will be 0 for network console and 1 or 2 for + the machine built-in serial ports. + config PPC_EARLY_DEBUG_44x_PHYSLOW hex "Low 32 bits of early debug UART physical address" depends on PPC_EARLY_DEBUG_44x diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index c7a3202..749de00 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -425,6 +425,11 @@ extern void hvc_opal_init_early(void); extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); +extern int opal_get_chars(uint32_t vtermno, char *buf, int count); +extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len); + +extern void hvc_opal_init_early(void); + #endif /* __ASSEMBLY__ */ #endif /* __OPAL_H */ diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h index 7cf796f..6587ec7 100644 --- a/arch/powerpc/include/asm/udbg.h +++ b/arch/powerpc/include/asm/udbg.h @@ -55,6 +55,8 @@ extern void __init udbg_init_cpm(void); extern void __init udbg_init_usbgecko(void); extern void __init udbg_init_wsp(void); extern void __init udbg_init_ps3gelic(void); +extern void __init udbg_init_debug_opal_raw(void); +extern void __init udbg_init_debug_opal_hvsi(void); #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_UDBG_H */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index dea8191..06c7251 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -53,7 +53,8 @@ * 2. The kernel is entered at __start * -or- For OPAL entry: * 1. The MMU is off, processor in HV mode, primary CPU enters at 0 - * with device-tree in gpr3 + * with device-tree in gpr3. We also get OPAL base in r8 and + * entry in r9 for debugging purposes * 2. Secondary processors enter at 0x60 with PIR in gpr3 * * For iSeries: @@ -335,6 +336,11 @@ _GLOBAL(__start_initialization_multiplatform) /* Save parameters */ mr r31,r3 mr r30,r4 +#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL + /* Save OPAL entry */ + mr r28,r8 + mr r29,r9 +#endif #ifdef CONFIG_PPC_BOOK3E bl .start_initialization_book3e @@ -711,6 +717,12 @@ _INIT_STATIC(start_here_multiplatform) bdnz 3b 4: +#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL + /* Setup OPAL entry */ + std r28,0(r11); + std r29,8(r11); +#endif + #ifndef CONFIG_PPC_BOOK3E mfmsr r6 ori r6,r6,MSR_RI diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 5b3e98e..35f9482 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -69,6 +69,10 @@ void __init udbg_early_init(void) udbg_init_wsp(); #elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC) udbg_init_ps3gelic(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_RAW) + udbg_init_debug_opal_raw(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI) + udbg_init_debug_opal_hvsi(); #endif #ifdef CONFIG_PPC_EARLY_DEBUG diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 8d55107..7887733 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -67,7 +67,7 @@ int opal_get_chars(uint32_t vtermno, char *buf, int count) u64 evt; if (!opal.entry) - return 0; + return -ENODEV; opal_poll_events(&evt); if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0) return 0; @@ -81,31 +81,38 @@ int opal_get_chars(uint32_t vtermno, char *buf, int count) int opal_put_chars(uint32_t vtermno, const char *data, int total_len) { int written = 0; - s64 len, rc = OPAL_BUSY; + s64 len, rc; unsigned long flags; u64 evt; if (!opal.entry) - return 0; + return -ENODEV; /* We want put_chars to be atomic to avoid mangling of hvsi * packets. To do that, we first test for room and return - * -EAGAIN if there isn't enough + * -EAGAIN if there isn't enough. + * + * Unfortunately, opal_console_write_buffer_space() doesn't + * appear to work on opal v1, so we just assume there is + * enough room and be done with it */ spin_lock_irqsave(&opal_write_lock, flags); - rc = opal_console_write_buffer_space(vtermno, &len); - if (rc || len < total_len) { - spin_unlock_irqrestore(&opal_write_lock, flags); - /* Closed -> drop characters */ - if (rc) - return total_len; - opal_poll_events(&evt); - return -EAGAIN; + if (firmware_has_feature(FW_FEATURE_OPALv2)) { + rc = opal_console_write_buffer_space(vtermno, &len); + if (rc || len < total_len) { + spin_unlock_irqrestore(&opal_write_lock, flags); + /* Closed -> drop characters */ + if (rc) + return total_len; + opal_poll_events(&evt); + return -EAGAIN; + } } /* We still try to handle partial completions, though they * should no longer happen. */ + rc = OPAL_BUSY; while(total_len > 0 && (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { len = total_len; diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index b6e5ff8..07ba1ec 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -29,17 +29,12 @@ #include <asm/machdep.h> #include <asm/firmware.h> #include <asm/xics.h> +#include <asm/opal.h> #include "powernv.h" static void __init pnv_setup_arch(void) { - /* Force console to hvc for now until we have sorted out the - * real console situation for the platform. This will make - * hvc_udbg work at least. - */ - add_preferred_console("hvc", 0, NULL); - /* Initialize SMP */ pnv_smp_init(); @@ -55,7 +50,12 @@ static void __init pnv_setup_arch(void) static void __init pnv_init_early(void) { - /* XXX IOMMU */ +#ifdef CONFIG_HVC_OPAL + if (firmware_has_feature(FW_FEATURE_OPAL)) + hvc_opal_init_early(); + else +#endif + add_preferred_console("hvc", 0, NULL); } static void __init pnv_init_IRQ(void) |