1 /** @file
2 
3   Generic Timer Description Table (GTDT)
4 
5   Copyright (c) 2012 - 2014, ARM Ltd. All rights reserved.<BR>
6   Copyright (c) 2014 - 2016, AMD Inc. All rights reserved.<BR>
7 
8   This program and the accompanying materials
9   are licensed and made available under the terms and conditions of the BSD License
10   which accompanies this distribution.  The full text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 /**
18 
19   Derived from:
20    ArmPlatformPkg/ArmJunoPkg/AcpiTables/Gtdt.aslc
21 
22 **/
23 
24 #include <AmdStyxAcpiLib.h>
25 
26 #pragma pack(push, 1)
27 
28 #define CNT_CONTROL_BASE_ADDRESS      FixedPcdGet64(PcdCntControlBase)
29 #define CNT_READ_BASE_ADDRESS         FixedPcdGet64(PcdCntReadBase)
30 #define CNT_CTL_BASE_ADDRESS          FixedPcdGet64(PcdCntCTLBase)
31 #define CNT_BASE0_ADDRESS             FixedPcdGet64(PcdCntBase0)
32 #define CNT_EL0_BASE0_ADDRESS         FixedPcdGet64(PcdCntEL0Base0)
33 #define SBSA_WATCHDOG_REFRESH_BASE    FixedPcdGet64(PcdSbsaWatchDogRefreshBase)
34 #define SBSA_WATCHDOG_CONTROL_BASE    FixedPcdGet64(PcdSbsaWatchDogControlBase)
35 #define SBSA_WAKEUP_GSIV              FixedPcdGet64(PcdSbsaWakeUpGSIV)
36 #define SBSA_WATCHDOG_GSIV            FixedPcdGet64(PcdSbsaWatchDogGSIV)
37 
38 
39 /*
40  * Section 8.2.3 of Cortex-A15 r2p1 TRM
41  */
42 #define CP15_TIMER_SEC_INTR    29
43 #define CP15_TIMER_NS_INTR     30
44 #define CP15_TIMER_VIRT_INTR   27
45 #define CP15_TIMER_NSHYP_INTR  26
46 
47 /* SBSA Timers */
48   #define PLATFORM_TIMER_COUNT          2
49   #define PLATFORM_TIMER_OFFSET         sizeof (EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE)
50 
51 /*
52 // GTDT Table timer flags.
53 
54 Bit 0: Timer interrupt Mode
55   This bit indicates the mode of the timer interrupt
56     1: Interrupt is Edge triggered
57     0: Interrupt is Level triggered
58 Timer Interrupt polarity
59   This bit indicates the polarity of the timer interrupt
60     1: Interrupt is Active low
61     0: Interrupt is Active high
62 Reserved 2 30 Reserved, must be zero.
63 
64 From A15 TRM:
65    9.2 Generic Timer functional description
66     ...
67     Each timer provides an active-LOW interrupt output that is an external pin to the SoC and is
68     sent to the GIC as a Private Peripheral Interrupt (PPI). See Interrupt sources on page 8-4 for
69     the ID and PPI allocation of the Timer interrupts.
70       PPI6 Virtual Maintenance Interrupt.
71       PPI5 Hypervisor timer event.
72       PPI4 Virtual timer event.
73       PPI3 nIRQ.
74       PPI2 Non-secure physical timer event.
75       PPI1 Secure physical timer event.
76       PPI0-5 Active-LOW level-sensitive.
77       PPI6 Active-HIGH level-sensitive.*/
78 
79 #define GTDT_TIMER_EDGE_TRIGGERED   EFI_ACPI_5_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE
80 #define GTDT_TIMER_LEVEL_TRIGGERED  0
81 #define GTDT_TIMER_ACTIVE_LOW       EFI_ACPI_5_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY
82 #define GTDT_TIMER_ACTIVE_HIGH      0
83 #define GTDT_TIMER_SECURE           EFI_ACPI_5_1_GTDT_TIMER_FLAG_ALWAYS_ON_CAPABILITY
84 #define GTDT_TIMER_NON_SECURE       0
85 #define GTDT_GTIMER_FLAGS           (GTDT_TIMER_NON_SECURE | GTDT_TIMER_ACTIVE_HIGH | GTDT_TIMER_LEVEL_TRIGGERED)
86 
87 #define GTX_TIMER_EDGE_TRIGGERED    EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_MODE
88 #define GTX_TIMER_LEVEL_TRIGGERED   0
89 #define GTX_TIMER_ACTIVE_LOW        EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_POLARITY
90 #define GTX_TIMER_ACTIVE_HIGH       0
91 #define GTX_TIMER_FLAGS             (GTX_TIMER_ACTIVE_HIGH | GTX_TIMER_LEVEL_TRIGGERED)
92 
93 #define GTX_TIMER_SECURE            EFI_ACPI_5_1_GTDT_GT_BLOCK_COMMON_FLAG_SECURE_TIMER
94 #define GTX_TIMER_NON_SECURE        0
95 #define GTX_TIMER_SAVE_CONTEXT      EFI_ACPI_5_1_GTDT_GT_BLOCK_COMMON_FLAG_ALWAYS_ON_CAPABILITY
96 #define GTX_TIMER_LOSE_CONTEXT      0
97 #define GTX_COMMON_FLAGS            (GTX_TIMER_SAVE_CONTEXT | GTX_TIMER_NON_SECURE)
98 
99 #define SBSA_WATCHDOG_EDGE_TRIGGERED   EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_MODE
100 #define SBSA_WATCHDOG_LEVEL_TRIGGERED  0
101 #define SBSA_WATCHDOG_ACTIVE_LOW       EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_POLARITY
102 #define SBSA_WATCHDOG_ACTIVE_HIGH      0
103 #define SBSA_WATCHDOG_SECURE           EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_SECURE_TIMER
104 #define SBSA_WATCHDOG_NON_SECURE       0
105 #define SBSA_WATCHDOG_FLAGS            (SBSA_WATCHDOG_NON_SECURE | SBSA_WATCHDOG_ACTIVE_HIGH | SBSA_WATCHDOG_LEVEL_TRIGGERED)
106 
107 
108 #define AMD_SBSA_GTX {                                                                     \
109    EFI_ACPI_5_1_GTDT_GT_BLOCK,                           /* UINT8  Type */                 \
110    sizeof (EFI_ACPI_5_1_GTDT_GT_BLOCK_STRUCTURE) +                                         \
111    sizeof (EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_STRUCTURE),  /* UINT16 Length */               \
112    EFI_ACPI_RESERVED_BYTE,                               /* UINT8  Reserved */             \
113    CNT_CTL_BASE_ADDRESS,                                 /* UINT64 CntCtlBase */           \
114    1,                                                    /* UINT32 GTBlockTimerCount */    \
115    sizeof (EFI_ACPI_5_1_GTDT_GT_BLOCK_STRUCTURE)         /* UINT32 GTBlockTimerOffset */   \
116   }
117 
118 #define AMD_SBSA_GTX_TIMER {                                                                  \
119    0,                                                    /* UINT8  GTFrameNumber */           \
120    {0, 0, 0},                                            /* UINT8  Reserved[3] */             \
121    CNT_BASE0_ADDRESS,                                    /* UINT64 CntBaseX */                \
122    CNT_EL0_BASE0_ADDRESS,                                /* UINT64 CntEL0BaseX */             \
123    SBSA_WAKEUP_GSIV,                                     /* UINT32 GTxPhysicalTimerGSIV */    \
124    GTX_TIMER_FLAGS,                                      /* UINT32 GTxPhysicalTimerFlags */   \
125    0,                                                    /* UINT32 GTxVirtualTimerGSIV */     \
126    GTX_TIMER_FLAGS,                                      /* UINT32 GTxVirtualTimerFlags */    \
127    GTX_COMMON_FLAGS                                      /* UINT32 GTxCommonFlags */          \
128   }
129 
130 #define AMD_SBSA_WATCHDOG {                                                                                        \
131    EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG,                     /* UINT8  Type */                                  \
132    sizeof (EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE),  /* UINT16 Length */                                \
133    EFI_ACPI_RESERVED_BYTE,                                      /* UINT8  Reserved */                              \
134    SBSA_WATCHDOG_REFRESH_BASE,                                  /* UINT64 RefreshFramePhysicalAddress */           \
135    SBSA_WATCHDOG_CONTROL_BASE,                                  /* UINT64 WatchdogControlFramePhysicalAddress */   \
136    SBSA_WATCHDOG_GSIV,                                          /* UINT32 WatchdogTimerGSIV */                     \
137    SBSA_WATCHDOG_FLAGS                                          /* UINT32 WatchdogTimerFlags */                    \
138   }
139 
140 typedef struct {
141   EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE      Gtdt;
142   EFI_ACPI_5_1_GTDT_GT_BLOCK_STRUCTURE              GTxBlock;
143   EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_STRUCTURE        GTxTimer;
144   EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE WatchDog;
145 } AMD_ACPI_5_1_ARM_GTDT_STRUCTURE;
146 
147 STATIC AMD_ACPI_5_1_ARM_GTDT_STRUCTURE AcpiGtdt = {
148   {
149     AMD_ACPI_HEADER(EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
150                     AMD_ACPI_5_1_ARM_GTDT_STRUCTURE,
151                     EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION),
152     CNT_CONTROL_BASE_ADDRESS,     // UINT64  PhysicalAddress
153     0,                            // UINT32  Reserved
154     CP15_TIMER_SEC_INTR,          // UINT32  SecureEL1TimerGSIV
155     GTDT_GTIMER_FLAGS,            // UINT32  SecureEL1TimerFlags
156     CP15_TIMER_NS_INTR,           // UINT32  NonSecureEL1TimerGSIV
157     GTDT_GTIMER_FLAGS,            // UINT32  NonSecureEL1TimerFlags
158     CP15_TIMER_VIRT_INTR,         // UINT32  VirtualTimerGSIV
159     GTDT_GTIMER_FLAGS,            // UINT32  VirtualTimerFlags
160     CP15_TIMER_NSHYP_INTR,        // UINT32  NonSecureEL2TimerGSIV
161     GTDT_GTIMER_FLAGS,            // UINT32  NonSecureEL2TimerFlags
162     CNT_READ_BASE_ADDRESS,        // UINT64  CntReadBaseAddress
163     PLATFORM_TIMER_COUNT,         // UINT32  PlatformTimerCount
164     PLATFORM_TIMER_OFFSET         // UINT32  PlatformTimerOffset
165   },
166   AMD_SBSA_GTX,
167   AMD_SBSA_GTX_TIMER,
168   AMD_SBSA_WATCHDOG,
169 };
170 
171 #pragma pack(pop)
172 
173 
174 EFI_ACPI_DESCRIPTION_HEADER *
GtdtHeader(VOID)175 GtdtHeader (
176   VOID
177   )
178 {
179   UINT32 CpuId = PcdGet32 (PcdSocCpuId);
180 
181   // Check BaseModel and Stepping: Styx-B0 or prior?
182   if (((CpuId & 0xFF0) == 0) || ((CpuId & 0x00F) == 0)) {
183     AcpiGtdt.Gtdt.Header.Length = sizeof (EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE);
184     AcpiGtdt.Gtdt.PlatformTimerCount = 0;
185     AcpiGtdt.Gtdt.PlatformTimerOffset = 0;
186   }
187 
188   return (EFI_ACPI_DESCRIPTION_HEADER *) &AcpiGtdt.Gtdt.Header;
189 }
190