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 #include "io.h" 18 19 extern void halt(int code); 20 21 /* 22 * Use this guess for the pl011 base in order to make an attempt at 23 * having earlier printf support. We'll overwrite it with the real 24 * base address that we read from the device tree later. This is 25 * the address we expect QEMU's mach-virt machine type to put in 26 * its generated device tree. 27 */ 28 #define UART_EARLY_BASE 0x09000000UL 29 30 static struct spinlock uart_lock; 31 static volatile u8 *uart0_base = (u8 *)UART_EARLY_BASE; 32 33 static void uart0_init(void) 34 { 35 const char *compatible = "arm,pl011"; 36 struct dt_pbus_reg base; 37 int ret; 38 39 ret = dt_get_default_console_node(); 40 assert(ret >= 0 || ret == -FDT_ERR_NOTFOUND); 41 42 if (ret == -FDT_ERR_NOTFOUND) { 43 44 ret = dt_pbus_get_base_compatible(compatible, &base); 45 assert(ret == 0 || ret == -FDT_ERR_NOTFOUND); 46 47 if (ret) { 48 printf("%s: %s not found in the device tree, " 49 "aborting...\n", 50 __func__, compatible); 51 abort(); 52 } 53 54 } else { 55 ret = dt_pbus_translate_node(ret, 0, &base); 56 assert(ret == 0); 57 } 58 59 uart0_base = ioremap(base.addr, base.size); 60 61 if (uart0_base != (u8 *)UART_EARLY_BASE) { 62 printf("WARNING: early print support may not work. " 63 "Found uart at %p, but early base is %p.\n", 64 uart0_base, (u8 *)UART_EARLY_BASE); 65 } 66 } 67 68 void io_init(void) 69 { 70 uart0_init(); 71 chr_testdev_init(); 72 } 73 74 void puts(const char *s) 75 { 76 spin_lock(&uart_lock); 77 while (*s) 78 writeb(*s++, uart0_base); 79 spin_unlock(&uart_lock); 80 } 81 82 void exit(int code) 83 { 84 chr_testdev_exit(code); 85 halt(code); 86 } 87