ArmVirtPL031FdtClientLib.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /** @file
  2. FDT client library for ARM's PL031 RTC driver
  3. Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Uefi.h>
  7. #include <Library/BaseLib.h>
  8. #include <Library/DebugLib.h>
  9. #include <Library/PcdLib.h>
  10. #include <Library/UefiBootServicesTableLib.h>
  11. #include <Protocol/FdtClient.h>
  12. RETURN_STATUS
  13. EFIAPI
  14. ArmVirtPL031FdtClientLibConstructor (
  15. VOID
  16. )
  17. {
  18. EFI_STATUS Status;
  19. FDT_CLIENT_PROTOCOL *FdtClient;
  20. INT32 Node;
  21. CONST UINT64 *Reg;
  22. UINT32 RegSize;
  23. UINT64 RegBase;
  24. RETURN_STATUS PcdStatus;
  25. Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
  26. (VOID **)&FdtClient);
  27. ASSERT_EFI_ERROR (Status);
  28. Status = FdtClient->FindCompatibleNode (FdtClient, "arm,pl031", &Node);
  29. if (EFI_ERROR (Status)) {
  30. DEBUG ((EFI_D_WARN, "%a: No 'arm,pl031' compatible DT node found\n",
  31. __FUNCTION__));
  32. return EFI_SUCCESS;
  33. }
  34. Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg",
  35. (CONST VOID **)&Reg, &RegSize);
  36. if (EFI_ERROR (Status)) {
  37. DEBUG ((EFI_D_WARN,
  38. "%a: No 'reg' property found in 'arm,pl031' compatible DT node\n",
  39. __FUNCTION__));
  40. return EFI_SUCCESS;
  41. }
  42. ASSERT (RegSize == 16);
  43. RegBase = SwapBytes64 (Reg[0]);
  44. ASSERT (RegBase < MAX_UINT32);
  45. PcdStatus = PcdSet32S (PcdPL031RtcBase, (UINT32)RegBase);
  46. ASSERT_RETURN_ERROR (PcdStatus);
  47. DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase));
  48. //
  49. // UEFI takes ownership of the RTC hardware, and exposes its functionality
  50. // through the UEFI Runtime Services GetTime, SetTime, etc. This means we
  51. // need to disable it in the device tree to prevent the OS from attaching
  52. // its device driver as well.
  53. //
  54. Status = FdtClient->SetNodeProperty (FdtClient, Node, "status",
  55. "disabled", sizeof ("disabled"));
  56. if (EFI_ERROR (Status)) {
  57. DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n"));
  58. }
  59. return EFI_SUCCESS;
  60. }