]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c
ArmPlatformPkg: Consume MdeLibs.dsc.inc for RegisterFilterLib
[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
77 for (Prev = 0;; Prev = Node) {\r
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
92 CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) {\r
93\r
94 if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {\r
b1f3e48e
AB
95 NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len);\r
96 if (NodeStatus != NULL && AsciiStrCmp (NodeStatus, "okay") != 0) {\r
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
104 UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));\r
105\r
106 BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);\r
107 ReceiveFifoDepth = 0; // Use the default value for Fifo depth\r
108 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
109 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
110 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);\r
111\r
112 Status = PL011UartInitializePort (\r
113 UartBase,\r
090916d8
EL
114 FixedPcdGet32 (PL011UartClkInHz),\r
115 &BaudRate,\r
116 &ReceiveFifoDepth,\r
117 &Parity,\r
118 &DataBits,\r
119 &StopBits\r
120 );\r
f1f0ba19
LE
121 if (!EFI_ERROR (Status)) {\r
122 return UartBase;\r
123 }\r
124 }\r
125 }\r
126 }\r
127 return 0;\r
128}\r
129\r
130/**\r
131 Write data to serial device.\r
132\r
133 @param Buffer Point of data buffer which need to be written.\r
134 @param NumberOfBytes Number of output bytes which are cached in Buffer.\r
135\r
136 @retval 0 Write data failed.\r
137 @retval !0 Actual number of bytes written to serial device.\r
138\r
139**/\r
140UINTN\r
141EFIAPI\r
142SerialPortWrite (\r
143 IN UINT8 *Buffer,\r
144 IN UINTN NumberOfBytes\r
145 )\r
146{\r
147 UINT64 SerialRegisterBase;\r
148\r
149 SerialRegisterBase = SerialPortGetBaseAddress ();\r
150 if (SerialRegisterBase != 0) {\r
151 return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes);\r
152 }\r
153 return 0;\r
154}\r
155\r
156/**\r
157 Read data from serial device and save the data in buffer.\r
158\r
159 @param Buffer Point of data buffer which need to be written.\r
160 @param NumberOfBytes Size of Buffer[].\r
161\r
162 @retval 0 Read data failed.\r
163 @retval !0 Actual number of bytes read from serial device.\r
164\r
165**/\r
166UINTN\r
167EFIAPI\r
168SerialPortRead (\r
169 OUT UINT8 *Buffer,\r
170 IN UINTN NumberOfBytes\r
171)\r
172{\r
173 return 0;\r
174}\r
175\r
176/**\r
177 Check to see if any data is available to be read from the debug device.\r
178\r
179 @retval TRUE At least one byte of data is available to be read\r
180 @retval FALSE No data is available to be read\r
181\r
182**/\r
183BOOLEAN\r
184EFIAPI\r
185SerialPortPoll (\r
186 VOID\r
187 )\r
188{\r
189 return FALSE;\r
190}\r
ad7f6bc2
SZ
191\r
192/**\r
193 Sets the control bits on a serial device.\r
194\r
195 @param[in] Control Sets the bits of Control that are settable.\r
196\r
197 @retval RETURN_SUCCESS The new control bits were set on the serial device.\r
198 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
199 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
200\r
201**/\r
202RETURN_STATUS\r
203EFIAPI\r
204SerialPortSetControl (\r
205 IN UINT32 Control\r
206 )\r
207{\r
208 return RETURN_UNSUPPORTED;\r
209}\r
210\r
211/**\r
212 Retrieve the status of the control bits on a serial device.\r
213\r
214 @param[out] Control A pointer to return the current control signals from the serial device.\r
215\r
216 @retval RETURN_SUCCESS The control bits were read from the serial device.\r
217 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
218 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
219\r
220**/\r
221RETURN_STATUS\r
222EFIAPI\r
223SerialPortGetControl (\r
224 OUT UINT32 *Control\r
225 )\r
226{\r
227 return RETURN_UNSUPPORTED;\r
228}\r
229\r
230/**\r
7a908953 231 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,\r
ad7f6bc2
SZ
232 data bits, and stop bits on a serial device.\r
233\r
234 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the\r
235 device's default interface speed.\r
236 On output, the value actually set.\r
7a908953 237 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the\r
ad7f6bc2
SZ
238 serial interface. A ReceiveFifoDepth value of 0 will use\r
239 the device's default FIFO depth.\r
240 On output, the value actually set.\r
241 @param Timeout The requested time out for a single character in microseconds.\r
242 This timeout applies to both the transmit and receive side of the\r
243 interface. A Timeout value of 0 will use the device's default time\r
244 out value.\r
245 On output, the value actually set.\r
246 @param Parity The type of parity to use on this serial device. A Parity value of\r
247 DefaultParity will use the device's default parity value.\r
248 On output, the value actually set.\r
249 @param DataBits The number of data bits to use on the serial device. A DataBits\r
7a908953 250 value of 0 will use the device's default data bit setting.\r
ad7f6bc2
SZ
251 On output, the value actually set.\r
252 @param StopBits The number of stop bits to use on this serial device. A StopBits\r
253 value of DefaultStopBits will use the device's default number of\r
254 stop bits.\r
255 On output, the value actually set.\r
256\r
257 @retval RETURN_SUCCESS The new attributes were set on the serial device.\r
258 @retval RETURN_UNSUPPORTED The serial device does not support this operation.\r
259 @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.\r
260 @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.\r
261\r
262**/\r
263RETURN_STATUS\r
264EFIAPI\r
265SerialPortSetAttributes (\r
266 IN OUT UINT64 *BaudRate,\r
267 IN OUT UINT32 *ReceiveFifoDepth,\r
268 IN OUT UINT32 *Timeout,\r
269 IN OUT EFI_PARITY_TYPE *Parity,\r
270 IN OUT UINT8 *DataBits,\r
271 IN OUT EFI_STOP_BITS_TYPE *StopBits\r
272 )\r
273{\r
274 return RETURN_UNSUPPORTED;\r
275}\r
276\r