diff --git a/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf b/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf index 3d5eaa4171..b7ae1e86b7 100644 --- a/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf +++ b/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/BaseRiscV64CpuTimerLib.inf @@ -28,6 +28,8 @@ BaseLib PcdLib DebugLib + FdtLib + HobLib -[Pcd] - gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES +[Guids] + gFdtHobGuid diff --git a/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/CpuTimerLib.c b/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/CpuTimerLib.c index 27d7276aaa..080e229c40 100644 --- a/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/CpuTimerLib.c +++ b/UefiCpuPkg/Library/BaseRiscV64CpuTimerLib/CpuTimerLib.c @@ -12,6 +12,12 @@ #include #include #include +#include +#include +#include +#include + +STATIC UINT64 mTimeBase; /** Stalls the CPU for at least the given number of ticks. @@ -57,7 +63,7 @@ MicroSecondDelay ( DivU64x32 ( MultU64x32 ( MicroSeconds, - PcdGet64 (PcdCpuCoreCrystalClockFrequency) + mTimeBase ), 1000000u ) @@ -85,7 +91,7 @@ NanoSecondDelay ( DivU64x32 ( MultU64x32 ( NanoSeconds, - PcdGet64 (PcdCpuCoreCrystalClockFrequency) + mTimeBase ), 1000000000u ) @@ -152,7 +158,48 @@ GetPerformanceCounterProperties ( *EndValue = 32 - 1; } - return PcdGet64 (PcdCpuCoreCrystalClockFrequency); + if (mTimeBase != 0) { + return mTimeBase; + } + + // + // Locate the FDT HOB and validate header + // + CONST EFI_HOB_GUID_TYPE *Hob = GetFirstGuidHob (&gFdtHobGuid); + + ASSERT (Hob != NULL); + + CONST VOID *DeviceTreeBase = + (CONST VOID *)(UINTN)*(CONST UINT64 *)GET_GUID_HOB_DATA (Hob); + + ASSERT (FdtCheckHeader (DeviceTreeBase) == 0); + + // + // /cpus node + // + INT32 Node = FdtSubnodeOffsetNameLen ( + DeviceTreeBase, + 0, + "cpus", + sizeof ("cpus") - 1 + ); + + ASSERT (Node >= 0); + + // + // timebase-frequency property + // + INT32 Len; + CONST FDT_PROPERTY *Prop = + FdtGetProperty (DeviceTreeBase, Node, "timebase-frequency", &Len); + + ASSERT (Prop != NULL && Len == sizeof (UINT32)); + + // + // Device-tree cells are big-endian + // + mTimeBase = SwapBytes32 (*(CONST UINT32 *)Prop->Data); + return mTimeBase; } /** @@ -180,13 +227,13 @@ GetTimeInNanoSecond ( // Time = --------- x 1,000,000,000 // Frequency // - NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, PcdGet64 (PcdCpuCoreCrystalClockFrequency), &Remainder), 1000000000u); + NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, mTimeBase, &Remainder), 1000000000u); // // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000) // will not overflow 64-bit. // - NanoSeconds += DivU64x32 (MultU64x32 ((UINT64)Remainder, 1000000000u), PcdGet64 (PcdCpuCoreCrystalClockFrequency)); + NanoSeconds += DivU64x32 (MultU64x32 ((UINT64)Remainder, 1000000000u), mTimeBase); return NanoSeconds; }