From 67b744697c0780cce462560ab2d5d1c7fc18ecaf Mon Sep 17 00:00:00 2001 From: Akshay Behl Date: Sun, 8 Jun 2025 22:49:22 +0530 Subject: [PATCH] UefiCpuPkg: TimerLib support to fetch freq from DT On RISC-V platforms, just like other platforms, we need to pass various information from one stage to another (hartid/cmo operations etc). Also there are some settings like Timer freq which are platform dependent which use PCDs. Today hartid is extracted through Firmware Context (custom in mem structure passed from one stage to another). For CMO we have a features HOB. Going forward we would like to have a standard mechanism to pass on such information and DT is handy as it can easily carry all this information (in some cases nodes already exists). This patch implement timebase frequency extraction from DT. Signed-off-by: Akshay Behl Co-authored-by: Dhaval Sharma --- .../BaseRiscV64CpuTimerLib.inf | 6 +- .../BaseRiscV64CpuTimerLib/CpuTimerLib.c | 57 +++++++++++++++++-- 2 files changed, 56 insertions(+), 7 deletions(-) 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; }