1 /** @file
2 FDT client library for ARM's TimerDxe
3
4 Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <Uefi.h>
17
18 #include <Library/BaseLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22
23 #include <Protocol/FdtClient.h>
24
25 #pragma pack (1)
26 typedef struct {
27 UINT32 Type;
28 UINT32 Number;
29 UINT32 Flags;
30 } INTERRUPT_PROPERTY;
31 #pragma pack ()
32
33 RETURN_STATUS
34 EFIAPI
ArmVirtTimerFdtClientLibConstructor(VOID)35 ArmVirtTimerFdtClientLibConstructor (
36 VOID
37 )
38 {
39 EFI_STATUS Status;
40 FDT_CLIENT_PROTOCOL *FdtClient;
41 CONST INTERRUPT_PROPERTY *InterruptProp;
42 UINT32 PropSize;
43 INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
44 RETURN_STATUS PcdStatus;
45
46 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
47 (VOID **)&FdtClient);
48 ASSERT_EFI_ERROR (Status);
49
50 Status = FdtClient->FindCompatibleNodeProperty (FdtClient, "arm,armv7-timer",
51 "interrupts", (CONST VOID **)&InterruptProp,
52 &PropSize);
53 if (Status == EFI_NOT_FOUND) {
54 Status = FdtClient->FindCompatibleNodeProperty (FdtClient,
55 "arm,armv8-timer", "interrupts",
56 (CONST VOID **)&InterruptProp,
57 &PropSize);
58 }
59
60 if (EFI_ERROR (Status)) {
61 return Status;
62 }
63
64 //
65 // - interrupts : Interrupt list for secure, non-secure, virtual and
66 // hypervisor timers, in that order.
67 //
68 ASSERT (PropSize == 36 || PropSize == 48);
69
70 SecIntrNum = SwapBytes32 (InterruptProp[0].Number)
71 + (InterruptProp[0].Type ? 16 : 0);
72 IntrNum = SwapBytes32 (InterruptProp[1].Number)
73 + (InterruptProp[1].Type ? 16 : 0);
74 VirtIntrNum = SwapBytes32 (InterruptProp[2].Number)
75 + (InterruptProp[2].Type ? 16 : 0);
76 HypIntrNum = PropSize < 48 ? 0 : SwapBytes32 (InterruptProp[3].Number)
77 + (InterruptProp[3].Type ? 16 : 0);
78
79 DEBUG ((EFI_D_INFO, "Found Timer interrupts %d, %d, %d, %d\n",
80 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum));
81
82 PcdStatus = PcdSet32S (PcdArmArchTimerSecIntrNum, SecIntrNum);
83 ASSERT_RETURN_ERROR (PcdStatus);
84 PcdStatus = PcdSet32S (PcdArmArchTimerIntrNum, IntrNum);
85 ASSERT_RETURN_ERROR (PcdStatus);
86 PcdStatus = PcdSet32S (PcdArmArchTimerVirtIntrNum, VirtIntrNum);
87 ASSERT_RETURN_ERROR (PcdStatus);
88 PcdStatus = PcdSet32S (PcdArmArchTimerHypIntrNum, HypIntrNum);
89 ASSERT_RETURN_ERROR (PcdStatus);
90
91 return EFI_SUCCESS;
92 }
93