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 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 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 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 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