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 <cap2k4@rivosinc.com> Co-authored-by: Dhaval Sharma <dhaval@rivosinc.com>
This commit is contained in:
committed by
mergify[bot]
parent
5ea0be305a
commit
67b744697c
@@ -28,6 +28,8 @@
|
||||
BaseLib
|
||||
PcdLib
|
||||
DebugLib
|
||||
FdtLib
|
||||
HobLib
|
||||
|
||||
[Pcd]
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES
|
||||
[Guids]
|
||||
gFdtHobGuid
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Register/RiscV64/RiscVImpl.h>
|
||||
#include <Pi/PiBootMode.h>
|
||||
#include <Pi/PiHob.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/FdtLib.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user