1 /* 2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2012, Alexander von Gluck, kallisti5@unixzen.com 6 * Distributed under the terms of the MIT License. 7 */ 8 9 10 #include "serial.h" 11 12 #include <debug_uart_8250.h> 13 #if defined(__ARM__) 14 #include <arch_uart_pl011.h> 15 #endif 16 #include <board_config.h> 17 #include <boot/platform.h> 18 #include <arch/cpu.h> 19 #include <boot/stage2.h> 20 #include <new> 21 #include <string.h> 22 23 extern "C" { 24 #include <fdt.h> 25 #include <libfdt.h> 26 #include <libfdt_env.h> 27 }; 28 29 30 extern "C" DebugUART *debug_uart_from_fdt(const void *fdt); 31 32 DebugUART* gUART; 33 34 static int32 sSerialEnabled = 0; 35 static char sBuffer[16384]; 36 static uint32 sBufferPosition; 37 38 39 static void 40 serial_putc(char c) 41 { 42 gUART->PutChar(c); 43 } 44 45 46 extern "C" int 47 serial_getc(bool wait) 48 { 49 return gUART->GetChar(wait); 50 } 51 52 53 extern "C" void 54 serial_puts(const char* string, size_t size) 55 { 56 if (sSerialEnabled <= 0) 57 return; 58 59 if (sBufferPosition + size < sizeof(sBuffer)) { 60 memcpy(sBuffer + sBufferPosition, string, size); 61 sBufferPosition += size; 62 } 63 64 while (size-- != 0) { 65 char c = string[0]; 66 67 if (c == '\n') { 68 serial_putc('\r'); 69 serial_putc('\n'); 70 } else if (c != '\r') 71 serial_putc(c); 72 73 string++; 74 } 75 } 76 77 78 extern "C" void 79 serial_disable(void) 80 { 81 sSerialEnabled = 0; 82 } 83 84 85 extern "C" void 86 serial_enable(void) 87 { 88 /* should already be initialized by U-Boot */ 89 gUART->InitEarly(); 90 gUART->InitPort(115200); 91 sSerialEnabled++; 92 } 93 94 95 extern "C" void 96 serial_cleanup(void) 97 { 98 if (sSerialEnabled <= 0) 99 return; 100 101 gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); 102 if (gKernelArgs.debug_output != NULL) { 103 memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); 104 gKernelArgs.debug_size = sBufferPosition; 105 } 106 } 107 108 109 extern "C" void 110 serial_init(const void *fdt) 111 { 112 // first try with hints from the FDT 113 gUART = debug_uart_from_fdt(fdt); 114 115 #ifdef BOARD_UART_DEBUG 116 // fallback to hardcoded board UART 117 if (gUART == NULL) { 118 #if defined(BOARD_UART_PL011) 119 gUART = arch_get_uart_pl011(BOARD_UART_DEBUG, BOARD_UART_CLOCK); 120 #else 121 gUART = arch_get_uart_8250(BOARD_UART_DEBUG, BOARD_UART_CLOCK); 122 #endif 123 } 124 #endif 125 126 if (gUART == NULL) 127 return; 128 129 serial_enable(); 130 } 131