EarlyFdtPL011SerialPortLib.c 9.0 KB

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