EarlyFdtPL011SerialPortLib.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. {
  82. if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {
  83. NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len);
  84. if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
  85. continue;
  86. }
  87. RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
  88. if (Len != 16) {
  89. return 0;
  90. }
  91. UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));
  92. BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
  93. ReceiveFifoDepth = 0; // Use the default value for Fifo depth
  94. Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
  95. DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
  96. StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
  97. Status = PL011UartInitializePort (
  98. UartBase,
  99. FixedPcdGet32 (PL011UartClkInHz),
  100. &BaudRate,
  101. &ReceiveFifoDepth,
  102. &Parity,
  103. &DataBits,
  104. &StopBits
  105. );
  106. if (!EFI_ERROR (Status)) {
  107. return UartBase;
  108. }
  109. }
  110. }
  111. }
  112. return 0;
  113. }
  114. /**
  115. Write data to serial device.
  116. @param Buffer Point of data buffer which need to be written.
  117. @param NumberOfBytes Number of output bytes which are cached in Buffer.
  118. @retval 0 Write data failed.
  119. @retval !0 Actual number of bytes written to serial device.
  120. **/
  121. UINTN
  122. EFIAPI
  123. SerialPortWrite (
  124. IN UINT8 *Buffer,
  125. IN UINTN NumberOfBytes
  126. )
  127. {
  128. UINT64 SerialRegisterBase;
  129. SerialRegisterBase = SerialPortGetBaseAddress ();
  130. if (SerialRegisterBase != 0) {
  131. return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes);
  132. }
  133. return 0;
  134. }
  135. /**
  136. Read data from serial device and save the data in buffer.
  137. @param Buffer Point of data buffer which need to be written.
  138. @param NumberOfBytes Size of Buffer[].
  139. @retval 0 Read data failed.
  140. @retval !0 Actual number of bytes read from serial device.
  141. **/
  142. UINTN
  143. EFIAPI
  144. SerialPortRead (
  145. OUT UINT8 *Buffer,
  146. IN UINTN NumberOfBytes
  147. )
  148. {
  149. return 0;
  150. }
  151. /**
  152. Check to see if any data is available to be read from the debug device.
  153. @retval TRUE At least one byte of data is available to be read
  154. @retval FALSE No data is available to be read
  155. **/
  156. BOOLEAN
  157. EFIAPI
  158. SerialPortPoll (
  159. VOID
  160. )
  161. {
  162. return FALSE;
  163. }
  164. /**
  165. Sets the control bits on a serial device.
  166. @param[in] Control Sets the bits of Control that are settable.
  167. @retval RETURN_SUCCESS The new control bits were set on the serial device.
  168. @retval RETURN_UNSUPPORTED The serial device does not support this operation.
  169. @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
  170. **/
  171. RETURN_STATUS
  172. EFIAPI
  173. SerialPortSetControl (
  174. IN UINT32 Control
  175. )
  176. {
  177. return RETURN_UNSUPPORTED;
  178. }
  179. /**
  180. Retrieve the status of the control bits on a serial device.
  181. @param[out] Control A pointer to return the current control signals from the serial device.
  182. @retval RETURN_SUCCESS The control bits were read from the serial device.
  183. @retval RETURN_UNSUPPORTED The serial device does not support this operation.
  184. @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
  185. **/
  186. RETURN_STATUS
  187. EFIAPI
  188. SerialPortGetControl (
  189. OUT UINT32 *Control
  190. )
  191. {
  192. return RETURN_UNSUPPORTED;
  193. }
  194. /**
  195. Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
  196. data bits, and stop bits on a serial device.
  197. @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
  198. device's default interface speed.
  199. On output, the value actually set.
  200. @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
  201. serial interface. A ReceiveFifoDepth value of 0 will use
  202. the device's default FIFO depth.
  203. On output, the value actually set.
  204. @param Timeout The requested time out for a single character in microseconds.
  205. This timeout applies to both the transmit and receive side of the
  206. interface. A Timeout value of 0 will use the device's default time
  207. out value.
  208. On output, the value actually set.
  209. @param Parity The type of parity to use on this serial device. A Parity value of
  210. DefaultParity will use the device's default parity value.
  211. On output, the value actually set.
  212. @param DataBits The number of data bits to use on the serial device. A DataBits
  213. value of 0 will use the device's default data bit setting.
  214. On output, the value actually set.
  215. @param StopBits The number of stop bits to use on this serial device. A StopBits
  216. value of DefaultStopBits will use the device's default number of
  217. stop bits.
  218. On output, the value actually set.
  219. @retval RETURN_SUCCESS The new attributes were set on the serial device.
  220. @retval RETURN_UNSUPPORTED The serial device does not support this operation.
  221. @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value.
  222. @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly.
  223. **/
  224. RETURN_STATUS
  225. EFIAPI
  226. SerialPortSetAttributes (
  227. IN OUT UINT64 *BaudRate,
  228. IN OUT UINT32 *ReceiveFifoDepth,
  229. IN OUT UINT32 *Timeout,
  230. IN OUT EFI_PARITY_TYPE *Parity,
  231. IN OUT UINT8 *DataBits,
  232. IN OUT EFI_STOP_BITS_TYPE *StopBits
  233. )
  234. {
  235. return RETURN_UNSUPPORTED;
  236. }