1 /* 2 * Each architecture must implement puts() and exit(). 3 * 4 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8 #include <libcflat.h> 9 #include <asm/spinlock.h> 10 #include <asm/rtas.h> 11 #include <asm/setup.h> 12 #include <asm/processor.h> 13 #include <asm/atomic.h> 14 #include "io.h" 15 16 static struct spinlock print_lock; 17 18 void putchar(int c) 19 { 20 if (machine_is_powernv()) 21 opal_putchar(c); 22 else 23 papr_putchar(c); 24 } 25 26 int __getchar(void) 27 { 28 if (machine_is_powernv()) 29 return __opal_getchar(); 30 else 31 return __papr_getchar(); 32 } 33 34 void io_init(void) 35 { 36 if (machine_is_powernv()) 37 assert(!opal_init()); 38 else 39 rtas_init(); 40 } 41 42 void puts(const char *s) 43 { 44 spin_lock(&print_lock); 45 while (*s) 46 putchar(*s++); 47 spin_unlock(&print_lock); 48 } 49 50 /* 51 * Defining halt to take 'code' as an argument guarantees that it will 52 * be in r3 when we halt. That gives us a final chance to see the exit 53 * status while inspecting the halted unit test state. 54 */ 55 extern void halt(int code); 56 57 void exit(int code) 58 { 59 static int exited = 0; 60 61 // FIXME: change this print-exit/rtas-poweroff to chr_testdev_exit(), 62 // maybe by plugging chr-testdev into a spapr-vty. 63 if (atomic_fetch_inc(&exited) == 0) { 64 printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1); 65 if (machine_is_powernv()) 66 opal_power_off(); 67 else 68 rtas_power_off(); 69 } 70 halt(code); 71 __builtin_unreachable(); 72 } 73