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