Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.14-rc2 109 lines 2.6 kB view raw
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 CONFIG_PPC64_BOOT_WRAPPER 17 18/* Global OPAL struct used by opal-call.S */ 19struct opal { 20 u64 base; 21 u64 entry; 22} opal; 23 24static u32 opal_con_id; 25 26/* see opal-wrappers.S */ 27int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); 28int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); 29int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); 30int64_t opal_console_flush(uint64_t term_number); 31int64_t opal_poll_events(uint64_t *outstanding_event_mask); 32 33void opal_kentry(unsigned long fdt_addr, void *vmlinux_addr); 34 35static int opal_con_open(void) 36{ 37 /* 38 * When OPAL loads the boot kernel it stashes the OPAL base and entry 39 * address in r8 and r9 so the kernel can use the OPAL console 40 * before unflattening the devicetree. While executing the wrapper will 41 * probably trash r8 and r9 so this kentry hook restores them before 42 * entering the decompressed kernel. 43 */ 44 platform_ops.kentry = opal_kentry; 45 return 0; 46} 47 48static void opal_con_putc(unsigned char c) 49{ 50 int64_t rc; 51 uint64_t olen, len; 52 53 do { 54 rc = opal_console_write_buffer_space(opal_con_id, &olen); 55 len = be64_to_cpu(olen); 56 if (rc) 57 return; 58 opal_poll_events(NULL); 59 } while (len < 1); 60 61 62 olen = cpu_to_be64(1); 63 opal_console_write(opal_con_id, &olen, &c); 64} 65 66static void opal_con_close(void) 67{ 68 opal_console_flush(opal_con_id); 69} 70 71static void opal_init(void) 72{ 73 void *opal_node; 74 75 opal_node = finddevice("/ibm,opal"); 76 if (!opal_node) 77 return; 78 if (getprop(opal_node, "opal-base-address", &opal.base, sizeof(u64)) < 0) 79 return; 80 opal.base = be64_to_cpu(opal.base); 81 if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0) 82 return; 83 opal.entry = be64_to_cpu(opal.entry); 84} 85 86int opal_console_init(void *devp, struct serial_console_data *scdp) 87{ 88 opal_init(); 89 90 if (devp) { 91 int n = getprop(devp, "reg", &opal_con_id, sizeof(u32)); 92 if (n != sizeof(u32)) 93 return -1; 94 opal_con_id = be32_to_cpu(opal_con_id); 95 } else 96 opal_con_id = 0; 97 98 scdp->open = opal_con_open; 99 scdp->putc = opal_con_putc; 100 scdp->close = opal_con_close; 101 102 return 0; 103} 104#else 105int opal_console_init(void *devp, struct serial_console_data *scdp) 106{ 107 return -1; 108} 109#endif /* __powerpc64__ */