1 /* 2 * Each architecture must implement puts() and exit() with the I/O 3 * devices exposed from QEMU, e.g. pl011 and chr-testdev. That's 4 * what's done here, along with initialization functions for those 5 * devices. 6 * 7 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2. 10 */ 11 #include "libcflat.h" 12 #include "devicetree.h" 13 #include "chr-testdev.h" 14 #include "asm/spinlock.h" 15 #include "asm/io.h" 16 17 extern void halt(int code); 18 19 /* 20 * Use this guess for the pl011 base in order to make an attempt at 21 * having earlier printf support. We'll overwrite it with the real 22 * base address that we read from the device tree later. 23 */ 24 #define QEMU_MACH_VIRT_PL011_BASE 0x09000000UL 25 26 static struct spinlock uart_lock; 27 static volatile u8 *uart0_base = (u8 *)QEMU_MACH_VIRT_PL011_BASE; 28 29 static void uart0_init(void) 30 { 31 const char *compatible = "arm,pl011"; 32 struct dt_pbus_reg base; 33 int ret; 34 35 ret = dt_pbus_get_base_compatible(compatible, &base); 36 assert(ret == 0 || ret == -FDT_ERR_NOTFOUND); 37 38 if (ret) { 39 printf("%s: %s not found in the device tree, aborting...\n", 40 __func__, compatible); 41 abort(); 42 } 43 44 uart0_base = ioremap(base.addr, base.size); 45 } 46 47 void io_init(void) 48 { 49 uart0_init(); 50 chr_testdev_init(); 51 } 52 53 void puts(const char *s) 54 { 55 spin_lock(&uart_lock); 56 while (*s) 57 writeb(*s++, uart0_base); 58 spin_unlock(&uart_lock); 59 } 60 61 void exit(int code) 62 { 63 chr_testdev_exit(code); 64 halt(code); 65 } 66