aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/Kconfig.debug31
-rw-r--r--arch/powerpc/include/asm/opal.h5
-rw-r--r--arch/powerpc/include/asm/udbg.h2
-rw-r--r--arch/powerpc/kernel/head_64.S14
-rw-r--r--arch/powerpc/kernel/udbg.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal.c31
-rw-r--r--arch/powerpc/platforms/powernv/setup.c14
7 files changed, 81 insertions, 20 deletions
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 06eb62b0fd9..1b8a9c905cf 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 c7a3202d10a..749de00a02d 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 7cf796fa03f..6587ec7bc6e 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 dea8191253d..06c7251c1bf 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 5b3e98e0315..35f948203ec 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 8d5510784cc..7887733b9b3 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 b6e5ff85cc6..07ba1ecd180 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)