xref: /haiku/src/system/boot/platform/u-boot/serial.cpp (revision 33ee23acbe97607d0779633f46c1269ba91894c8)
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