1 /* 2 * Copyright (c) 2016 IBM Corporation. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10 #include "ops.h" 11 #include "stdio.h" 12 #include "io.h" 13 #include <libfdt.h> 14 #include "../include/asm/opal-api.h" 15 16 #ifdef __powerpc64__ 17 18 /* Global OPAL struct used by opal-call.S */ 19 struct opal { 20 u64 base; 21 u64 entry; 22 } opal; 23 24 static u32 opal_con_id; 25 26 int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); 27 int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); 28 int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); 29 int64_t opal_console_flush(uint64_t term_number); 30 int64_t opal_poll_events(uint64_t *outstanding_event_mask); 31 32 static int opal_con_open(void) 33 { 34 return 0; 35 } 36 37 static void opal_con_putc(unsigned char c) 38 { 39 int64_t rc; 40 uint64_t olen, len; 41 42 do { 43 rc = opal_console_write_buffer_space(opal_con_id, &olen); 44 len = be64_to_cpu(olen); 45 if (rc) 46 return; 47 opal_poll_events(NULL); 48 } while (len < 1); 49 50 51 olen = cpu_to_be64(1); 52 opal_console_write(opal_con_id, &olen, &c); 53 } 54 55 static void opal_con_close(void) 56 { 57 opal_console_flush(opal_con_id); 58 } 59 60 static void opal_init(void) 61 { 62 void *opal_node; 63 64 opal_node = finddevice("/ibm,opal"); 65 if (!opal_node) 66 return; 67 if (getprop(opal_node, "opal-base-address", &opal.base, sizeof(u64)) < 0) 68 return; 69 opal.base = be64_to_cpu(opal.base); 70 if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0) 71 return; 72 opal.entry = be64_to_cpu(opal.entry); 73 } 74 75 int opal_console_init(void *devp, struct serial_console_data *scdp) 76 { 77 opal_init(); 78 79 if (devp) { 80 int n = getprop(devp, "reg", &opal_con_id, sizeof(u32)); 81 if (n != sizeof(u32)) 82 return -1; 83 opal_con_id = be32_to_cpu(opal_con_id); 84 } else 85 opal_con_id = 0; 86 87 scdp->open = opal_con_open; 88 scdp->putc = opal_con_putc; 89 scdp->close = opal_con_close; 90 91 return 0; 92 } 93 #else 94 int opal_console_init(void *devp, struct serial_console_data *scdp) 95 { 96 return -1; 97 } 98 #endif /* __powerpc64__ */ 99