--- /dev/null
+/** @file\r
+ FDT client library for ARM's TimerDxe\r
+\r
+ Copyright (c) 2016, 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 <Uefi.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#include <Protocol/FdtClient.h>\r
+\r
+#pragma pack (1)\r
+typedef struct {\r
+ UINT32 Type;\r
+ UINT32 Number;\r
+ UINT32 Flags;\r
+} INTERRUPT_PROPERTY;\r
+#pragma pack ()\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+ArmVirtTimerFdtClientLibConstructor (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ FDT_CLIENT_PROTOCOL *FdtClient;\r
+ CONST INTERRUPT_PROPERTY *InterruptProp;\r
+ UINT32 PropSize;\r
+ INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;\r
+\r
+ Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
+ (VOID **)&FdtClient);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = FdtClient->FindCompatibleNodeProperty (FdtClient, "arm,armv7-timer",\r
+ "interrupts", (CONST VOID **)&InterruptProp,\r
+ &PropSize);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ Status = FdtClient->FindCompatibleNodeProperty (FdtClient,\r
+ "arm,armv8-timer", "interrupts",\r
+ (CONST VOID **)&InterruptProp,\r
+ &PropSize);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // - interrupts : Interrupt list for secure, non-secure, virtual and\r
+ // hypervisor timers, in that order.\r
+ //\r
+ ASSERT (PropSize == 36 || PropSize == 48);\r
+\r
+ SecIntrNum = SwapBytes32 (InterruptProp[0].Number)\r
+ + (InterruptProp[0].Type ? 16 : 0);\r
+ IntrNum = SwapBytes32 (InterruptProp[1].Number)\r
+ + (InterruptProp[1].Type ? 16 : 0);\r
+ VirtIntrNum = SwapBytes32 (InterruptProp[2].Number)\r
+ + (InterruptProp[2].Type ? 16 : 0);\r
+ HypIntrNum = PropSize < 48 ? 0 : SwapBytes32 (InterruptProp[3].Number)\r
+ + (InterruptProp[3].Type ? 16 : 0);\r
+\r
+ DEBUG ((EFI_D_INFO, "Found Timer interrupts %d, %d, %d, %d\n",\r
+ SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum));\r
+\r
+ PcdSet32 (PcdArmArchTimerSecIntrNum, SecIntrNum);\r
+ PcdSet32 (PcdArmArchTimerIntrNum, IntrNum);\r
+ PcdSet32 (PcdArmArchTimerVirtIntrNum, VirtIntrNum);\r
+ PcdSet32 (PcdArmArchTimerHypIntrNum, HypIntrNum);\r
+\r
+ return EFI_SUCCESS;\r
+}\r