diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index 1d896892dafc..9229c07df53c 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -136,6 +136,8 @@
   # Maximum file size for TFTP servers that do not support 'tsize' extension
   gArmTokenSpaceGuid.PcdMaxTftpFileSize|0x01000000|UINT32|0x00000000
 
+
+[PcdsFixedAtBuild.common,PcdsDynamic.common]
   #
   # ARM Architectural Timer
   #
diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.c b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
index be346bf89c51..670c4431e5a1 100644
--- a/ArmPkg/Drivers/TimerDxe/TimerDxe.c
+++ b/ArmPkg/Drivers/TimerDxe/TimerDxe.c
@@ -36,6 +36,8 @@ EFI_EVENT             EfiExitBootServicesEvent = (EFI_EVENT)NULL;
 // The current period of the timer interrupt
 UINT64 mTimerPeriod = 0;
 
+UINTN mArmArchTimerTimerFreq = 0;
+
 // Cached copy of the Hardware Interrupt protocol instance
 EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
 
@@ -144,7 +146,7 @@ TimerDriverSetTimerPeriod (
     // Convert TimerPeriod to micro sec units
     TimerTicks = DivU64x32 (TimerPeriod, 10);
 
-    TimerTicks = MultU64x32 (TimerTicks, (PcdGet32(PcdArmArchTimerFreqInHz)/1000000));
+    TimerTicks = MultU64x32 (TimerTicks, mArmArchTimerTimerFreq);
 
     ArmArchTimerSetTimerVal((UINTN)TimerTicks);
 
@@ -343,6 +345,8 @@ TimerInitialize (
   Status = TimerDriverSetTimerPeriod (&gTimer, 0);
   ASSERT_EFI_ERROR (Status);
 
+  mArmArchTimerTimerFreq = ArmArchTimerGetTimerFreq() / 1000000;
+
   // Install secure and Non-secure interrupt handlers
   // Note: Because it is not possible to determine the security state of the
   // CPU dynamically, we just install interrupt handler for both sec and non-sec
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c b/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c
index 232d745b3d06..6487dcc441e4 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64ArchTimer.c
@@ -175,7 +175,7 @@ ArmArchTimerEnableTimer (
 {
   UINTN TimerCtrlReg;
 
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerReadReg (CntvCtl, (VOID *)&TimerCtrlReg);
     /* FIXME: We need to clear IMASK when under KVM because KVM sets it. Unclear if this is a bug ... */
     TimerCtrlReg |= ARM_ARCH_TIMER_ENABLE;
@@ -196,7 +196,7 @@ ArmArchTimerDisableTimer (
 {
   UINTN TimerCtrlReg;
 
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerReadReg (CntvCtl, (VOID *)&TimerCtrlReg);
     TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
     ArmArchTimerWriteReg (CntvCtl, (VOID *)&TimerCtrlReg);
@@ -234,7 +234,7 @@ ArmArchTimerGetTimerVal (
     )
 {
   UINTN ArchTimerVal;
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerReadReg (CntvTval, (VOID *)&ArchTimerVal);
   } else {
     ArmArchTimerReadReg (CntpTval, (VOID *)&ArchTimerVal);
@@ -250,7 +250,7 @@ ArmArchTimerSetTimerVal (
     IN   UINTN   Val
     )
 {
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerWriteReg (CntvTval, (VOID *)&Val);
   } else {
     ArmArchTimerWriteReg (CntpTval, (VOID *)&Val);
@@ -264,7 +264,7 @@ ArmArchTimerGetSystemCount (
     )
 {
   UINT64 SystemCount;
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerReadReg (CntvCt, (VOID *)&SystemCount);
   } else {
     ArmArchTimerReadReg (CntPct, (VOID *)&SystemCount);
@@ -281,7 +281,7 @@ ArmArchTimerGetTimerCtrlReg (
 {
   UINTN  Val;
 
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerReadReg (CntvCtl, (VOID *)&Val);
   } else {
     ArmArchTimerReadReg (CntpCtl, (VOID *)&Val);
@@ -296,7 +296,7 @@ ArmArchTimerSetTimerCtrlReg (
     UINTN Val
     )
 {
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerWriteReg (CntvCtl, (VOID *)&Val);
   } else {
     ArmArchTimerWriteReg (CntpCtl, (VOID *)&Val);
@@ -309,7 +309,7 @@ ArmArchTimerSetCompareVal (
     IN   UINT64   Val
     )
 {
-  if (PcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
+  if (FixedPcdGetBool(PcdArmArchTimerUseVirtual) == TRUE) {
     ArmArchTimerWriteReg (CntvCval, (VOID *)&Val);
   } else {
     ArmArchTimerWriteReg (CntpCval, (VOID *)&Val);
