11e95c7ccSAndrew Jones /* 21e95c7ccSAndrew Jones * Each architecture must implement puts() and exit(). 31e95c7ccSAndrew Jones * 41e95c7ccSAndrew Jones * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 51e95c7ccSAndrew Jones * 61e95c7ccSAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 71e95c7ccSAndrew Jones */ 81e95c7ccSAndrew Jones #include <libcflat.h> 9e65bcc62SAndrew Jones #include <asm/spinlock.h> 102f9ce69eSAndrew Jones #include <asm/rtas.h> 114ff26ec5SThomas Huth #include <asm/setup.h> 12610c5a9cSNicholas Piggin #include <asm/processor.h> 13*c76b0d0aSNicholas Piggin #include <asm/atomic.h> 144ff26ec5SThomas Huth #include "io.h" 15e65bcc62SAndrew Jones 16e65bcc62SAndrew Jones static struct spinlock print_lock; 171e95c7ccSAndrew Jones 18610c5a9cSNicholas Piggin void putchar(int c) 19610c5a9cSNicholas Piggin { 20610c5a9cSNicholas Piggin if (machine_is_powernv()) 21610c5a9cSNicholas Piggin opal_putchar(c); 22610c5a9cSNicholas Piggin else 23610c5a9cSNicholas Piggin papr_putchar(c); 24610c5a9cSNicholas Piggin } 25610c5a9cSNicholas Piggin 26610c5a9cSNicholas Piggin int __getchar(void) 27610c5a9cSNicholas Piggin { 28610c5a9cSNicholas Piggin if (machine_is_powernv()) 29610c5a9cSNicholas Piggin return __opal_getchar(); 30610c5a9cSNicholas Piggin else 31610c5a9cSNicholas Piggin return __papr_getchar(); 32610c5a9cSNicholas Piggin } 33610c5a9cSNicholas Piggin 341e95c7ccSAndrew Jones void io_init(void) 351e95c7ccSAndrew Jones { 36610c5a9cSNicholas Piggin if (machine_is_powernv()) 37610c5a9cSNicholas Piggin assert(!opal_init()); 38610c5a9cSNicholas Piggin else 392f9ce69eSAndrew Jones rtas_init(); 401e95c7ccSAndrew Jones } 411e95c7ccSAndrew Jones 42e65bcc62SAndrew Jones void puts(const char *s) 431e95c7ccSAndrew Jones { 44e65bcc62SAndrew Jones spin_lock(&print_lock); 45e65bcc62SAndrew Jones while (*s) 46e65bcc62SAndrew Jones putchar(*s++); 47e65bcc62SAndrew Jones spin_unlock(&print_lock); 481e95c7ccSAndrew Jones } 491e95c7ccSAndrew Jones 50764aa0b8SAndrew Jones /* 51764aa0b8SAndrew Jones * Defining halt to take 'code' as an argument guarantees that it will 52764aa0b8SAndrew Jones * be in r3 when we halt. That gives us a final chance to see the exit 53764aa0b8SAndrew Jones * status while inspecting the halted unit test state. 54764aa0b8SAndrew Jones */ 55764aa0b8SAndrew Jones extern void halt(int code); 56764aa0b8SAndrew Jones 57e65bcc62SAndrew Jones void exit(int code) 581e95c7ccSAndrew Jones { 59*c76b0d0aSNicholas Piggin static int exited = 0; 60*c76b0d0aSNicholas Piggin 61f5a87330SAndrew Jones // FIXME: change this print-exit/rtas-poweroff to chr_testdev_exit(), 62f5a87330SAndrew Jones // maybe by plugging chr-testdev into a spapr-vty. 63*c76b0d0aSNicholas Piggin if (atomic_fetch_inc(&exited) == 0) { 64f5a87330SAndrew Jones printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1); 65610c5a9cSNicholas Piggin if (machine_is_powernv()) 66610c5a9cSNicholas Piggin opal_power_off(); 67610c5a9cSNicholas Piggin else 68f5a87330SAndrew Jones rtas_power_off(); 69*c76b0d0aSNicholas Piggin } 70e65bcc62SAndrew Jones halt(code); 7196d79976SAndre Przywara __builtin_unreachable(); 721e95c7ccSAndrew Jones } 73