ArmVirtPL031FdtClientLib.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 (
  26. &gFdtClientProtocolGuid,
  27. NULL,
  28. (VOID **)&FdtClient
  29. );
  30. ASSERT_EFI_ERROR (Status);
  31. Status = FdtClient->FindCompatibleNode (FdtClient, "arm,pl031", &Node);
  32. if (EFI_ERROR (Status)) {
  33. DEBUG ((
  34. DEBUG_WARN,
  35. "%a: No 'arm,pl031' compatible DT node found\n",
  36. __FUNCTION__
  37. ));
  38. return EFI_SUCCESS;
  39. }
  40. Status = FdtClient->GetNodeProperty (
  41. FdtClient,
  42. Node,
  43. "reg",
  44. (CONST VOID **)&Reg,
  45. &RegSize
  46. );
  47. if (EFI_ERROR (Status)) {
  48. DEBUG ((
  49. DEBUG_WARN,
  50. "%a: No 'reg' property found in 'arm,pl031' compatible DT node\n",
  51. __FUNCTION__
  52. ));
  53. return EFI_SUCCESS;
  54. }
  55. ASSERT (RegSize == 16);
  56. RegBase = SwapBytes64 (Reg[0]);
  57. ASSERT (RegBase < MAX_UINT32);
  58. PcdStatus = PcdSet32S (PcdPL031RtcBase, (UINT32)RegBase);
  59. ASSERT_RETURN_ERROR (PcdStatus);
  60. DEBUG ((DEBUG_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase));
  61. //
  62. // UEFI takes ownership of the RTC hardware, and exposes its functionality
  63. // through the UEFI Runtime Services GetTime, SetTime, etc. This means we
  64. // need to disable it in the device tree to prevent the OS from attaching
  65. // its device driver as well.
  66. //
  67. Status = FdtClient->SetNodeProperty (
  68. FdtClient,
  69. Node,
  70. "status",
  71. "disabled",
  72. sizeof ("disabled")
  73. );
  74. if (EFI_ERROR (Status)) {
  75. DEBUG ((DEBUG_WARN, "Failed to set PL031 status to 'disabled'\n"));
  76. }
  77. return EFI_SUCCESS;
  78. }