xref: /kvm-unit-tests/lib/ppc64/opal.c (revision 610c5a9c11fc1e8fe936925b8a4975015ffe4b5e)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * OPAL call helpers
4  */
5 #include <asm/opal.h>
6 #include <libcflat.h>
7 #include <libfdt/libfdt.h>
8 #include <devicetree.h>
9 #include <asm/io.h>
10 #include "../powerpc/io.h"
11 
12 struct opal {
13 	uint64_t base;
14 	uint64_t entry;
15 } opal;
16 
17 extern int64_t opal_call(int64_t token, int64_t arg1, int64_t arg2, int64_t arg3);
18 
opal_init(void)19 int opal_init(void)
20 {
21 	const struct fdt_property *prop;
22 	int node, len;
23 
24 	node = fdt_path_offset(dt_fdt(), "/ibm,opal");
25 	if (node < 0)
26 		return -1;
27 
28 	prop = fdt_get_property(dt_fdt(), node, "opal-base-address", &len);
29 	if (!prop)
30 		return -1;
31 	opal.base = fdt64_to_cpu(*(uint64_t *)prop->data);
32 
33 	prop = fdt_get_property(dt_fdt(), node, "opal-entry-address", &len);
34 	if (!prop)
35 		return -1;
36 	opal.entry = fdt64_to_cpu(*(uint64_t *)prop->data);
37 
38 #if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
39 	if (opal_call(OPAL_REINIT_CPUS, OPAL_REINIT_CPUS_HILE_LE, 0, 0) != OPAL_SUCCESS)
40 		return -1;
41 #endif
42 
43 	return 0;
44 }
45 
opal_power_off(void)46 extern void opal_power_off(void)
47 {
48 	opal_call(OPAL_CEC_POWER_DOWN, 0, 0, 0);
49 	while (true)
50 		opal_call(OPAL_POLL_EVENTS, 0, 0, 0);
51 }
52 
opal_putchar(int c)53 void opal_putchar(int c)
54 {
55 	unsigned long vty = 0;		/* 0 == default */
56 	unsigned long nr_chars = cpu_to_be64(1);
57 	char ch = c;
58 
59 	opal_call(OPAL_CONSOLE_WRITE, (int64_t)vty, (int64_t)&nr_chars, (int64_t)&ch);
60 }
61 
__opal_getchar(void)62 int __opal_getchar(void)
63 {
64 	unsigned long vty = 0;		/* 0 == default */
65 	unsigned long nr_chars = cpu_to_be64(1);
66 	char ch;
67 	int rc;
68 
69 	rc = opal_call(OPAL_CONSOLE_READ, (int64_t)vty, (int64_t)&nr_chars, (int64_t)&ch);
70 	if (rc != OPAL_SUCCESS)
71 		return -1;
72 	if (nr_chars == 0)
73 		return -1;
74 
75 	return ch;
76 }
77