]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmVirtualizationPkg: add device tree based PL011 SerialPortLib
authorLaszlo Ersek <lersek@redhat.com>
Thu, 18 Sep 2014 18:07:52 +0000 (18:07 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 18 Sep 2014 18:07:52 +0000 (18:07 +0000)
This adds 2 implementations of SerialPortLib for device tree based platforms
using a PL011 UART:
- an 'early' one which is completely stateless and uses only fixed PCDs
- a normal one which takes its base address from a HOB containing the base
  address discovered in the PEI phase

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-with-remarks-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-By: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16140 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c [new file with mode: 0644]
ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf [new file with mode: 0644]
ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c [new file with mode: 0644]
ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf [new file with mode: 0644]

diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c
new file mode 100644 (file)
index 0000000..ba6d277
--- /dev/null
@@ -0,0 +1,185 @@
+/** @file\r
+  Serial I/O Port library functions with base address discovered from FDT\r
+\r
+  Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+  Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/PcdLib.h>\r
+#include <Library/SerialPortLib.h>\r
+#include <Library/SerialPortExtLib.h>\r
+#include <libfdt.h>\r
+\r
+#include <Drivers/PL011Uart.h>\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+SerialPortInitialize (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // This SerialPortInitialize() function is completely empty, for a number of\r
+  // reasons:\r
+  // - if we are executing from flash, it is hard to keep state (i.e., store the\r
+  //   discovered base address in a global), and the most robust way to deal\r
+  //   with this is to discover the base address at every Write ();\r
+  // - calls to the Write() function in this module may be issued before this\r
+  //   initialization function is called: this is not a problem when the base\r
+  //   address of the UART is hardcoded, and only the baud rate may be wrong,\r
+  //   but if we don't know the base address yet, we may be poking into memory\r
+  //   that does not tolerate being poked into;\r
+  // - SEC and PEI phases produce debug output only, so with debug disabled, no\r
+  //   initialization (or device tree parsing) is performed at all.\r
+  //\r
+  // Note that this means that on *every* Write () call, the device tree will be\r
+  // parsed and the UART re-initialized. However, this is a small price to pay\r
+  // for having serial debug output on a UART with no fixed base address.\r
+  //\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+STATIC\r
+UINT64\r
+SerialPortGetBaseAddress (\r
+  VOID\r
+  )\r
+{\r
+  UINT64              BaudRate;\r
+  UINT32              ReceiveFifoDepth;\r
+  EFI_PARITY_TYPE     Parity;\r
+  UINT8               DataBits;\r
+  EFI_STOP_BITS_TYPE  StopBits;\r
+  VOID                *DeviceTreeBase;\r
+  INT32               Node, Prev;\r
+  INT32               Len;\r
+  CONST CHAR8         *Compatible;\r
+  CONST CHAR8         *CompatibleItem;\r
+  CONST UINT64        *RegProperty;\r
+  UINTN               UartBase;\r
+  RETURN_STATUS       Status;\r
+\r
+  DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);\r
+\r
+  if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Enumerate all FDT nodes looking for a PL011 and capture its base address\r
+  //\r
+  for (Prev = 0;; Prev = Node) {\r
+    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);\r
+    if (Node < 0) {\r
+      break;\r
+    }\r
+\r
+    Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);\r
+    if (Compatible == NULL) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Iterate over the NULL-separated items in the compatible string\r
+    //\r
+    for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;\r
+      CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) {\r
+\r
+      if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {\r
+        RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);\r
+        if (Len != 16) {\r
+          return 0;\r
+        }\r
+        UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));\r
+\r
+        BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);\r
+        ReceiveFifoDepth = 0; // Use the default value for Fifo depth\r
+        Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);\r
+        DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);\r
+        StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);\r
+\r
+        Status = PL011UartInitializePort (\r
+                   UartBase,\r
+                   &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits);\r
+        if (!EFI_ERROR (Status)) {\r
+          return UartBase;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Write data to serial device.\r
+\r
+  @param  Buffer           Point of data buffer which need to be written.\r
+  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.\r
+\r
+  @retval 0                Write data failed.\r
+  @retval !0               Actual number of bytes written to serial device.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SerialPortWrite (\r
+  IN UINT8     *Buffer,\r
+  IN UINTN     NumberOfBytes\r
+  )\r
+{\r
+  UINT64 SerialRegisterBase;\r
+\r
+  SerialRegisterBase = SerialPortGetBaseAddress ();\r
+  if (SerialRegisterBase != 0) {\r
+    return PL011UartWrite ((UINTN)SerialRegisterBase, Buffer, NumberOfBytes);\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Read data from serial device and save the data in buffer.\r
+\r
+  @param  Buffer           Point of data buffer which need to be written.\r
+  @param  NumberOfBytes    Size of Buffer[].\r
+\r
+  @retval 0                Read data failed.\r
+  @retval !0               Actual number of bytes read from serial device.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SerialPortRead (\r
+  OUT UINT8     *Buffer,\r
+  IN  UINTN     NumberOfBytes\r
+)\r
+{\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Check to see if any data is available to be read from the debug device.\r
+\r
+  @retval TRUE       At least one byte of data is available to be read\r
+  @retval FALSE      No data is available to be read\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SerialPortPoll (\r
+  VOID\r
+  )\r
+{\r
+  return FALSE;\r
+}\r
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf
new file mode 100644 (file)
index 0000000..d62f87b
--- /dev/null
@@ -0,0 +1,45 @@
+#/** @file\r
+#\r
+#  Component description file for EarlyFdtPL011SerialPortLib module\r
+#\r
+#  Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = EarlyFdtPL011SerialPortLib\r
+  FILE_GUID                      = 0983616A-49BC-4732-B531-4AF98D2056F0\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SerialPortLib|SEC PEI_CORE PEIM\r
+\r
+[Sources.common]\r
+  EarlyFdtPL011SerialPortLib.c\r
+\r
+[LibraryClasses]\r
+  PL011UartLib\r
+  PcdLib\r
+  FdtLib\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+  ArmPlatformPkg/ArmPlatformPkg.dec\r
+  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec\r
+\r
+[FixedPcd]\r
+  gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress\r
+\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits\r
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.c
new file mode 100644 (file)
index 0000000..aced666
--- /dev/null
@@ -0,0 +1,150 @@
+/** @file\r
+  Serial I/O Port library functions with base address discovered from FDT\r
+\r
+  Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+  Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>\r
+  Copyright (c) 2014, Red Hat, Inc.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/PcdLib.h>\r
+#include <Library/SerialPortLib.h>\r
+#include <Pi/PiBootMode.h>\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Uefi/UefiMultiPhase.h>\r
+#include <Pi/PiHob.h>\r
+#include <Library/HobLib.h>\r
+#include <Guid/EarlyPL011BaseAddress.h>\r
+\r
+#include <Drivers/PL011Uart.h>\r
+\r
+STATIC UINTN mSerialBaseAddress;\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+SerialPortInitialize (\r
+  VOID\r
+  )\r
+{\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Program hardware of Serial port\r
+\r
+  @return    RETURN_NOT_FOUND if no PL011 base address could be found\r
+             Otherwise, result of PL011UartInitializePort () is returned\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+FdtPL011SerialPortLibInitialize (\r
+  VOID\r
+  )\r
+{\r
+  VOID                *Hob;\r
+  CONST UINT64        *UartBase;\r
+  UINT64              BaudRate;\r
+  UINT32              ReceiveFifoDepth;\r
+  EFI_PARITY_TYPE     Parity;\r
+  UINT8               DataBits;\r
+  EFI_STOP_BITS_TYPE  StopBits;\r
+\r
+  Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);\r
+  if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase) {\r
+    return RETURN_NOT_FOUND;\r
+  }\r
+  UartBase = GET_GUID_HOB_DATA (Hob);\r
+\r
+  mSerialBaseAddress = (UINTN)*UartBase;\r
+  if (mSerialBaseAddress == 0) {\r
+    return RETURN_NOT_FOUND;\r
+  }\r
+\r
+  BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);\r
+  ReceiveFifoDepth = 0; // Use the default value for Fifo depth\r
+  Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);\r
+  DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
+  StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);\r
+\r
+  return PL011UartInitializePort (\r
+           mSerialBaseAddress, &BaudRate, &ReceiveFifoDepth,\r
+           &Parity, &DataBits, &StopBits);\r
+}\r
+\r
+/**\r
+  Write data to serial device.\r
+\r
+  @param  Buffer           Point of data buffer which need to be written.\r
+  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.\r
+\r
+  @retval 0                Write data failed.\r
+  @retval !0               Actual number of bytes written to serial device.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SerialPortWrite (\r
+  IN UINT8     *Buffer,\r
+  IN UINTN     NumberOfBytes\r
+  )\r
+{\r
+  if (mSerialBaseAddress != 0) {\r
+    return PL011UartWrite (mSerialBaseAddress, Buffer, NumberOfBytes);\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Read data from serial device and save the data in buffer.\r
+\r
+  @param  Buffer           Point of data buffer which need to be written.\r
+  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.\r
+\r
+  @retval 0                Read data failed.\r
+  @retval !0               Actual number of bytes read from serial device.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+SerialPortRead (\r
+  OUT UINT8     *Buffer,\r
+  IN  UINTN     NumberOfBytes\r
+)\r
+{\r
+  if (mSerialBaseAddress != 0) {\r
+    return PL011UartRead (mSerialBaseAddress, Buffer, NumberOfBytes);\r
+  }\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Check to see if any data is available to be read from the debug device.\r
+\r
+  @retval TRUE       At least one byte of data is available to be read\r
+  @retval FALSE      No data is available to be read\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SerialPortPoll (\r
+  VOID\r
+  )\r
+{\r
+  if (mSerialBaseAddress != 0) {\r
+    return PL011UartPoll (mSerialBaseAddress);\r
+  }\r
+  return FALSE;\r
+}\r
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
new file mode 100644 (file)
index 0000000..178e6c4
--- /dev/null
@@ -0,0 +1,48 @@
+#/** @file\r
+#\r
+#  Component description file for PL011SerialPortLib module\r
+#\r
+#  Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution.  The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#**/\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = FdtPL011SerialPortLib\r
+  FILE_GUID                      = CB768406-7DE6-49B6-BC2C-F324E110DE5A\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = SerialPortLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER\r
+  CONSTRUCTOR                    = FdtPL011SerialPortLibInitialize\r
+\r
+[Sources.common]\r
+  FdtPL011SerialPortLib.c\r
+\r
+[LibraryClasses]\r
+  PL011UartLib\r
+  HobLib\r
+\r
+[Packages]\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  ArmPlatformPkg/ArmPlatformPkg.dec\r
+  ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec\r
+  ArmPkg/ArmPkg.dec\r
+\r
+[FixedPcd]\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity\r
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits\r
+\r
+[Guids]\r
+  gEarlyPL011BaseAddressGuid\r