libfdt       := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 libfdtheader := fdt.h libfdt.h libfdt_internal.h
 
-$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o opal.o): \
        $(addprefix $(obj)/,$(libfdtheader))
 
 src-wlib-y := string.S crt0.S crtsavres.S stdio.c main.c \
                ns16550.c serial.c simple_alloc.c div64.S util.S \
                gunzip_util.c elf_util.c $(zlib) devtree.c stdlib.c \
                oflib.c ofconsole.c cuboot.c mpsc.c cpm-serial.c \
-               uartlite.c mpc52xx-psc.c
+               uartlite.c mpc52xx-psc.c opal.c opal-calls.S
 src-wlib-$(CONFIG_40x) += 4xx.c planetcore.c
 src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c
 src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c fsl-soc.c
 
--- /dev/null
+/*
+ * Copyright (c) 2016 IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "ppc_asm.h"
+#include "../include/asm/opal-api.h"
+
+       .text
+
+#define OPAL_CALL(name, token)                         \
+       .globl name;                                    \
+name:                                                  \
+       li      r0, token;                              \
+       b       opal_call;
+
+opal_call:
+       mflr    r11
+       std     r11,16(r1)
+       mfcr    r12
+       stw     r12,8(r1)
+       mr      r13,r2
+
+       /* Set opal return address */
+       ld      r11,opal_return@got(r2)
+       mtlr    r11
+       mfmsr   r12
+
+       /* switch to BE when we enter OPAL */
+       li      r11,MSR_LE
+       andc    r12,r12,r11
+       mtspr   SPRN_HSRR1,r12
+
+       /* load the opal call entry point and base */
+       ld      r11,opal@got(r2)
+       ld      r12,8(r11)
+       ld      r2,0(r11)
+       mtspr   SPRN_HSRR0,r12
+       hrfid
+
+opal_return:
+       FIXUP_ENDIAN
+       mr      r2,r13;
+       lwz     r11,8(r1);
+       ld      r12,16(r1)
+       mtcr    r11;
+       mtlr    r12
+       blr
+
+OPAL_CALL(opal_console_write,                  OPAL_CONSOLE_WRITE);
+OPAL_CALL(opal_console_read,                   OPAL_CONSOLE_READ);
+OPAL_CALL(opal_console_write_buffer_space,     OPAL_CONSOLE_WRITE_BUFFER_SPACE);
+OPAL_CALL(opal_poll_events,                    OPAL_POLL_EVENTS);
+OPAL_CALL(opal_console_flush,                  OPAL_CONSOLE_FLUSH);
 
--- /dev/null
+/*
+ * Copyright (c) 2016 IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "io.h"
+#include <libfdt.h>
+#include "../include/asm/opal-api.h"
+
+#ifdef __powerpc64__
+
+/* Global OPAL struct used by opal-call.S */
+struct opal {
+       u64 base;
+       u64 entry;
+} opal;
+
+static u32 opal_con_id;
+
+int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer);
+int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer);
+int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length);
+int64_t opal_console_flush(uint64_t term_number);
+int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+
+static int opal_con_open(void)
+{
+       return 0;
+}
+
+static void opal_con_putc(unsigned char c)
+{
+       int64_t rc;
+       uint64_t olen, len;
+
+       do {
+               rc = opal_console_write_buffer_space(opal_con_id, &olen);
+               len = be64_to_cpu(olen);
+               if (rc)
+                       return;
+               opal_poll_events(NULL);
+       } while (len < 1);
+
+
+       olen = cpu_to_be64(1);
+       opal_console_write(opal_con_id, &olen, &c);
+}
+
+static void opal_con_close(void)
+{
+       opal_console_flush(opal_con_id);
+}
+
+static void opal_init(void)
+{
+       void *opal_node;
+
+       opal_node = finddevice("/ibm,opal");
+       if (!opal_node)
+               return;
+       if (getprop(opal_node, "opal-base-address", &opal.base, sizeof(u64)) < 0)
+               return;
+       opal.base = be64_to_cpu(opal.base);
+       if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0)
+               return;
+       opal.entry = be64_to_cpu(opal.entry);
+}
+
+int opal_console_init(void *devp, struct serial_console_data *scdp)
+{
+       opal_init();
+
+       if (devp) {
+               int n = getprop(devp, "reg", &opal_con_id, sizeof(u32));
+               if (n != sizeof(u32))
+                       return -1;
+               opal_con_id = be32_to_cpu(opal_con_id);
+       } else
+               opal_con_id = 0;
+
+       scdp->open = opal_con_open;
+       scdp->putc = opal_con_putc;
+       scdp->close = opal_con_close;
+
+       return 0;
+}
+#else
+int opal_console_init(void *devp, struct serial_console_data *scdp)
+{
+       return -1;
+}
+#endif /* __powerpc64__ */
 
 int cpm_console_init(void *devp, struct serial_console_data *scdp);
 int mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp);
 int uartlite_console_init(void *devp, struct serial_console_data *scdp);
+int opal_console_init(void *devp, struct serial_console_data *scdp);
 void *simple_alloc_init(char *base, unsigned long heap_size,
                        unsigned long granularity, unsigned long max_allocs);
 extern void flush_cache(void *, unsigned long);
 
 
 #define SPRN_TBRL      268
 #define SPRN_TBRU      269
+#define SPRN_HSRR0     0x13A   /* Hypervisor Save/Restore 0 */
+#define SPRN_HSRR1     0x13B   /* Hypervisor Save/Restore 1 */
+
+#define MSR_LE         0x0000000000000001
 
 #define FIXUP_ENDIAN                                              \
        tdi   0, 0, 0x48; /* Reverse endian of b . + 8          */ \
 
        else if (dt_is_compatible(devp, "xlnx,opb-uartlite-1.00.b") ||
                 dt_is_compatible(devp, "xlnx,xps-uartlite-1.00.a"))
                rc = uartlite_console_init(devp, &serial_cd);
+       else if (dt_is_compatible(devp, "ibm,opal-console-raw"))
+               rc = opal_console_init(devp, &serial_cd);
 
        /* Add other serial console driver calls here */
 
 
 typedef int                    s32;
 typedef long long              s64;
 
+/* required for opal-api.h */
+typedef u8  uint8_t;
+typedef u16 uint16_t;
+typedef u32 uint32_t;
+typedef u64 uint64_t;
+typedef s8  int8_t;
+typedef s16 int16_t;
+typedef s32 int32_t;
+typedef s64 int64_t;
+
 #define min(x,y) ({ \
        typeof(x) _x = (x);     \
        typeof(y) _y = (y);     \