blob: 63fe42ae62b86798d5a105f3e94be072302044a8 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* OPAL call helpers
*/
#include <asm/opal.h>
#include <libcflat.h>
#include <libfdt/libfdt.h>
#include <devicetree.h>
#include <asm/io.h>
#include "../powerpc/io.h"
struct opal {
uint64_t base;
uint64_t entry;
} opal;
extern int64_t opal_call(int64_t token, int64_t arg1, int64_t arg2, int64_t arg3);
int opal_init(void)
{
const struct fdt_property *prop;
int node, len;
node = fdt_path_offset(dt_fdt(), "/ibm,opal");
if (node < 0)
return -1;
prop = fdt_get_property(dt_fdt(), node, "opal-base-address", &len);
if (!prop)
return -1;
opal.base = fdt64_to_cpu(*(uint64_t *)prop->data);
prop = fdt_get_property(dt_fdt(), node, "opal-entry-address", &len);
if (!prop)
return -1;
opal.entry = fdt64_to_cpu(*(uint64_t *)prop->data);
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
if (opal_call(OPAL_REINIT_CPUS, OPAL_REINIT_CPUS_HILE_LE, 0, 0) != OPAL_SUCCESS)
return -1;
#endif
return 0;
}
extern void opal_power_off(void)
{
opal_call(OPAL_CEC_POWER_DOWN, 0, 0, 0);
while (true)
opal_call(OPAL_POLL_EVENTS, 0, 0, 0);
}
void opal_putchar(int c)
{
unsigned long vty = 0; /* 0 == default */
unsigned long nr_chars = cpu_to_be64(1);
char ch = c;
opal_call(OPAL_CONSOLE_WRITE, (int64_t)vty, (int64_t)&nr_chars, (int64_t)&ch);
}
int __opal_getchar(void)
{
unsigned long vty = 0; /* 0 == default */
unsigned long nr_chars = cpu_to_be64(1);
char ch;
int rc;
rc = opal_call(OPAL_CONSOLE_READ, (int64_t)vty, (int64_t)&nr_chars, (int64_t)&ch);
if (rc != OPAL_SUCCESS)
return -1;
if (nr_chars == 0)
return -1;
return ch;
}