ArmVirtTimerFdtClientLib.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /** @file
  2. FDT client library for ARM's TimerDxe
  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. #pragma pack (1)
  13. typedef struct {
  14. UINT32 Type;
  15. UINT32 Number;
  16. UINT32 Flags;
  17. } INTERRUPT_PROPERTY;
  18. #pragma pack ()
  19. RETURN_STATUS
  20. EFIAPI
  21. ArmVirtTimerFdtClientLibConstructor (
  22. VOID
  23. )
  24. {
  25. EFI_STATUS Status;
  26. FDT_CLIENT_PROTOCOL *FdtClient;
  27. CONST INTERRUPT_PROPERTY *InterruptProp;
  28. UINT32 PropSize;
  29. INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
  30. RETURN_STATUS PcdStatus;
  31. Status = gBS->LocateProtocol (
  32. &gFdtClientProtocolGuid,
  33. NULL,
  34. (VOID **)&FdtClient
  35. );
  36. ASSERT_EFI_ERROR (Status);
  37. Status = FdtClient->FindCompatibleNodeProperty (
  38. FdtClient,
  39. "arm,armv7-timer",
  40. "interrupts",
  41. (CONST VOID **)&InterruptProp,
  42. &PropSize
  43. );
  44. if (Status == EFI_NOT_FOUND) {
  45. Status = FdtClient->FindCompatibleNodeProperty (
  46. FdtClient,
  47. "arm,armv8-timer",
  48. "interrupts",
  49. (CONST VOID **)&InterruptProp,
  50. &PropSize
  51. );
  52. }
  53. if (EFI_ERROR (Status)) {
  54. return Status;
  55. }
  56. //
  57. // - interrupts : Interrupt list for secure, non-secure, virtual and
  58. // hypervisor timers, in that order.
  59. //
  60. ASSERT (PropSize == 36 || PropSize == 48);
  61. SecIntrNum = SwapBytes32 (InterruptProp[0].Number)
  62. + (InterruptProp[0].Type ? 16 : 0);
  63. IntrNum = SwapBytes32 (InterruptProp[1].Number)
  64. + (InterruptProp[1].Type ? 16 : 0);
  65. VirtIntrNum = SwapBytes32 (InterruptProp[2].Number)
  66. + (InterruptProp[2].Type ? 16 : 0);
  67. HypIntrNum = PropSize < 48 ? 0 : SwapBytes32 (InterruptProp[3].Number)
  68. + (InterruptProp[3].Type ? 16 : 0);
  69. DEBUG ((
  70. DEBUG_INFO,
  71. "Found Timer interrupts %d, %d, %d, %d\n",
  72. SecIntrNum,
  73. IntrNum,
  74. VirtIntrNum,
  75. HypIntrNum
  76. ));
  77. PcdStatus = PcdSet32S (PcdArmArchTimerSecIntrNum, SecIntrNum);
  78. ASSERT_RETURN_ERROR (PcdStatus);
  79. PcdStatus = PcdSet32S (PcdArmArchTimerIntrNum, IntrNum);
  80. ASSERT_RETURN_ERROR (PcdStatus);
  81. PcdStatus = PcdSet32S (PcdArmArchTimerVirtIntrNum, VirtIntrNum);
  82. ASSERT_RETURN_ERROR (PcdStatus);
  83. PcdStatus = PcdSet32S (PcdArmArchTimerHypIntrNum, HypIntrNum);
  84. ASSERT_RETURN_ERROR (PcdStatus);
  85. return EFI_SUCCESS;
  86. }