]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c
ArmVirtPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmVirtPkg / Library / FdtPL011SerialPortLib / EarlyFdtPL011SerialPortLib.c
CommitLineData
f1f0ba19
LE
1/** @file\r
2 Serial I/O Port library functions with base address discovered from FDT\r
3\r
4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
5 Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>\r
6 Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>\r
ad7f6bc2 7 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
f1f0ba19 8\r
9792fb0e 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
f1f0ba19
LE
10\r
11**/\r
12\r
13#include <Base.h>\r
14\r
15#include <Library/PcdLib.h>\r
1195b857 16#include <Library/PL011UartLib.h>\r
f1f0ba19 17#include <Library/SerialPortLib.h>\r
f1f0ba19
LE
18#include <libfdt.h>\r
19\r
f1f0ba19
LE
20RETURN_STATUS\r
21EFIAPI\r
22SerialPortInitialize (\r
23 VOID\r
24 )\r
25{\r
26 //\r
27 // This SerialPortInitialize() function is completely empty, for a number of\r
28 // reasons:\r
29 // - if we are executing from flash, it is hard to keep state (i.e., store the\r
30 // discovered base address in a global), and the most robust way to deal\r
31 // with this is to discover the base address at every Write ();\r
32 // - calls to the Write() function in this module may be issued before this\r
33 // initialization function is called: this is not a problem when the base\r
34 // address of the UART is hardcoded, and only the baud rate may be wrong,\r
35 // but if we don't know the base address yet, we may be poking into memory\r
36 // that does not tolerate being poked into;\r
37 // - SEC and PEI phases produce debug output only, so with debug disabled, no\r
38 // initialization (or device tree parsing) is performed at all.\r
39 //\r
40 // Note that this means that on *every* Write () call, the device tree will be\r
41 // parsed and the UART re-initialized. However, this is a small price to pay\r
42 // for having serial debug output on a UART with no fixed base address.\r
43 //\r
44 return RETURN_SUCCESS;\r
45}\r
46\r
47STATIC\r
48UINT64\r
49SerialPortGetBaseAddress (\r
50 VOID\r
51 )\r
52{\r
53 UINT64 BaudRate;\r
54 UINT32 ReceiveFifoDepth;\r
55 EFI_PARITY_TYPE Parity;\r
56 UINT8 DataBits;\r
57 EFI_STOP_BITS_TYPE StopBits;\r
58 VOID *DeviceTreeBase;\r
59 INT32 Node, Prev;\r
60 INT32 Len;\r
61 CONST CHAR8 *Compatible;\r
b1f3e48e 62 CONST CHAR8 *NodeStatus;\r
f1f0ba19
LE
63 CONST CHAR8 *CompatibleItem;\r
64 CONST UINT64 *RegProperty;\r
65 UINTN UartBase;\r
66 RETURN_STATUS Status;\r
67\r
ff05707e 68 DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);\r
f1f0ba19
LE
69\r
70 if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) {\r
71 return 0;\r
72 }\r
73\r
74 //\r
75 // Enumerate all FDT nodes looking for a PL011 and capture its base address\r
76 //\r
2b16a4fb 77 for (Prev = 0; ; Prev = Node) {\r
f1f0ba19
LE
78 Node = fdt_next_node (DeviceTreeBase, Prev, NULL);\r
79 if (Node < 0) {\r
80 break;\r
81 }\r
82\r
83 Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);\r
84 if (Compatible == NULL) {\r
85 continue;\r
86 }\r
87\r
88 //\r
89 // Iterate over the NULL-separated items in the compatible string\r
90 //\r
91 for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;\r
2b16a4fb
MK
92 CompatibleItem += 1 + AsciiStrLen (CompatibleItem))\r
93 {\r
f1f0ba19 94 if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {\r
b1f3e48e 95 NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len);\r
2b16a4fb 96 if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {\r
b1f3e48e
AB
97 continue;\r
98 }\r
99\r
f1f0ba19
LE
100 RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);\r
101 if (Len != 16) {\r
102 return 0;\r
103 }\r
2b16a4fb 104\r
f1f0ba19
LE
105 UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));\r
106\r
2b16a4fb 107 BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);\r
f1f0ba19 108 ReceiveFifoDepth = 0; // Use the default value for Fifo depth\r
2b16a4fb
MK
109 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
110 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
111 StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);\r
f1f0ba19
LE
112\r
113 Status = PL011UartInitializePort (\r
114 UartBase,\r
090916d8
EL
115 FixedPcdGet32 (PL011UartClkInHz),\r
116 &BaudRate,\r
117 &ReceiveFifoDepth,\r
118 &Parity,\r
119 &DataBits,\r
120 &StopBits\r
121 );\r
f1f0ba19
LE
122 if (!EFI_ERROR (Status)) {\r
123 return UartBase;\r
124 }\r
125 }\r
126 }\r
127 }\r
2b16a4fb 128\r
f1f0ba19
LE
129 return 0;\r
130}\r
131\r
132/**\r
133 Write data to serial device.\r
134\r
135 @param Buffer Point of data buffer which need to be written.\r
136 @param NumberOfBytes Number of output bytes which are cached in Buffer.\r
137\r
138 @retval 0 Write data failed.\r
139 @retval !0 Actual number of bytes written to serial device.\r
140\r
141**/\r
142UINTN\r
143EFIAPI\r
144SerialPortWrite (\r
2b16a4fb
MK
145 IN UINT8 *Buffer,\r
146 IN UINTN NumberOfBytes\r
f1f0ba19
LE
147 )\r
148{\r
2b16a4fb 149 UINT64 SerialRegisterBase;\r
f1f0ba19
LE
150\r
151 SerialRegisterBase = SerialPortGetBaseAddress ();\r
152 if (SerialRegisterBase != 0) {\r
153 return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes);\r
154 }\r
2b16a4fb 155\r
f1f0ba19
LE
156 return 0;\r
157}\r
158\r
159/**\r
160 Read data from serial device and save the data in buffer.\r
161\r
162 @param Buffer Point of data buffer which need to be written.\r
163 @param NumberOfBytes Size of Buffer[].\r
164\r
165 @retval 0 Read data failed.\r
166 @retval !0 Actual number of bytes read from serial device.\r
167\r
168**/\r
169UINTN\r
170EFIAPI\r
171SerialPortRead (\r
2b16a4fb
MK
172 OUT UINT8 *Buffer,\r
173 IN UINTN NumberOfBytes\r
174 )\r
f1f0ba19
LE
175{\r
176 return 0;\r
177}\r
178\r
179/**\r
180 Check to see if any data is available to be read from the debug device.\r
181\r
182 @retval TRUE At least one byte of data is available to be read\r
183 @retval FALSE No data is available to be read\r
184\r
185**/\r
186BOOLEAN\r
187EFIAPI\r
188SerialPortPoll (\r
189 VOID\r
190 )\r
191{\r
192 return FALSE;\r
193}\r
ad7f6bc2
SZ
194\r
195/**\r
196 Sets the control bits on a serial device.\r
197\r
198 @param[in] Control Sets the bits of Control that are settable.\r
199\r
200 @retval RETURN_SUCCESS The new control bits were set on the serial device.\r
201 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
202 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
203\r
204**/\r
205RETURN_STATUS\r
206EFIAPI\r
207SerialPortSetControl (\r
2b16a4fb 208 IN UINT32 Control\r
ad7f6bc2
SZ
209 )\r
210{\r
211 return RETURN_UNSUPPORTED;\r
212}\r
213\r
214/**\r
215 Retrieve the status of the control bits on a serial device.\r
216\r
217 @param[out] Control A pointer to return the current control signals from the serial device.\r
218\r
219 @retval RETURN_SUCCESS The control bits were read from the serial device.\r
220 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
221 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
222\r
223**/\r
224RETURN_STATUS\r
225EFIAPI\r
226SerialPortGetControl (\r
2b16a4fb 227 OUT UINT32 *Control\r
ad7f6bc2
SZ
228 )\r
229{\r
230 return RETURN_UNSUPPORTED;\r
231}\r
232\r
233/**\r
7a908953 234 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,\r
ad7f6bc2
SZ
235 data bits, and stop bits on a serial device.\r
236\r
237 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the\r
238 device's default interface speed.\r
239 On output, the value actually set.\r
7a908953 240 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the\r
ad7f6bc2
SZ
241 serial interface. A ReceiveFifoDepth value of 0 will use\r
242 the device's default FIFO depth.\r
243 On output, the value actually set.\r
244 @param Timeout The requested time out for a single character in microseconds.\r
245 This timeout applies to both the transmit and receive side of the\r
246 interface. A Timeout value of 0 will use the device's default time\r
247 out value.\r
248 On output, the value actually set.\r
249 @param Parity The type of parity to use on this serial device. A Parity value of\r
250 DefaultParity will use the device's default parity value.\r
251 On output, the value actually set.\r
252 @param DataBits The number of data bits to use on the serial device. A DataBits\r
7a908953 253 value of 0 will use the device's default data bit setting.\r
ad7f6bc2
SZ
254 On output, the value actually set.\r
255 @param StopBits The number of stop bits to use on this serial device. A StopBits\r
256 value of DefaultStopBits will use the device's default number of\r
257 stop bits.\r
258 On output, the value actually set.\r
259\r
260 @retval RETURN_SUCCESS The new attributes were set on the serial device.\r
261 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
262 @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.\r
263 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
264\r
265**/\r
266RETURN_STATUS\r
267EFIAPI\r
268SerialPortSetAttributes (\r
2b16a4fb
MK
269 IN OUT UINT64 *BaudRate,\r
270 IN OUT UINT32 *ReceiveFifoDepth,\r
271 IN OUT UINT32 *Timeout,\r
272 IN OUT EFI_PARITY_TYPE *Parity,\r
273 IN OUT UINT8 *DataBits,\r
274 IN OUT EFI_STOP_BITS_TYPE *StopBits\r
ad7f6bc2
SZ
275 )\r
276{\r
277 return RETURN_UNSUPPORTED;\r
278}\r