This library provides a delay interface and a timing interface. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054
Cc: Bibo Mao <maob...@loongson.cn> Cc: Chao Li <lic...@loongson.cn> Cc: Leif Lindholm <quic_llind...@quicinc.com> Cc: Liming Gao <gaolim...@byosoft.com.cn> Cc: Michael D Kinney <michael.d.kin...@intel.com> Signed-off-by: xianglai li <lixiang...@loongson.cn> --- .../Include/Library/StableTimer.h | 59 +++++ .../Library/StableTimerLib/Count.S | 52 ++++ .../Library/StableTimerLib/TimerLib.c | 236 ++++++++++++++++++ .../Library/StableTimerLib/TimerLib.inf | 32 +++ 4 files changed, 379 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h new file mode 100644 index 0000000000..93f5b66c34 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h @@ -0,0 +1,59 @@ +/** @file + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Csr - Cpu Status Register + - Calc - Calculation + - Freq - frequency +**/ + +#ifndef STABLE_TIMER_H_ +#define STABLE_TIMER_H_ +#include "Library/Cpu.h" + +/** + Gets the timer count value. + + @param[] VOID + + @retval timer count value. +**/ +extern +UINTN +EFIAPI +LoongArchReadTime ( + VOID + ); + +/** + Calculate the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +CalcConstFreq ( + VOID + ); + +/* + Reads data from the specified CPUCFG register. + + @param[OUT] Val Pointer to the variable used to store the CPUCFG register value. + @param[IN] reg Specifies the register number of the CPUCFG to read the data. + + @retval none + */ +extern +VOID +LoongArchReadCpuCfg ( + UINT64 *Val, + UINT64 reg + ); + +#endif // STABLE_TIMER_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S new file mode 100644 index 0000000000..4e0e718381 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Count for LoongArch +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "Library/Cpu.h" + +ASM_GLOBAL ASM_PFX(CpuSetIP) +ASM_GLOBAL ASM_PFX(LoongArchReadTime) +ASM_GLOBAL ASM_PFX(LoongArchReadCpuCfg) + +# +# Set cpu interrupts +# @param A0 The interrupt number +# + +ASM_PFX(CpuSetIP): + csrrd T0, LOONGARCH_CSR_ECFG + or T0, T0, A0 + csrwr T0, LOONGARCH_CSR_ECFG + jirl ZERO, RA, 0 + +# +#Gets the timer count value. +#@param[] VOID +#@retval timer count value. +# + +ASM_PFX(LoongArchReadTime): + rdtime.d A0, ZERO + jirl ZERO, RA, 0 + +# +# Read Csr CPUCFG register. +# @param A0 Pointer to the variable used to store the CPUCFG register value. +# @param A1 Specifies the register number of the CPUCFG to read the data. +# @retval none +# + +ASM_PFX(LoongArchReadCpuCfg): + cpucfg T0, A1 + stptr.d T0, A0, 0 + jirl ZERO, RA, 0 diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c new file mode 100644 index 0000000000..135fb22611 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c @@ -0,0 +1,236 @@ +/** @file + Generic LoongArch implementation of TimerLib.h + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Freq - Frequency + - Csr - Cpu Status Register + - calc - calculate +**/ + +#include <Base.h> +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include "Library/StableTimer.h" +#include "Library/Cpu.h" + +UINT32 StableTimerFreq = 0; + +/** + Calculate the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +CalcConstFreq ( + VOID + ) +{ + UINT32 Result; + UINT32 BaseFreq; + UINT32 ClockMultiplier; + UINT32 ClockDivide; + UINT64 Val; + + LoongArchReadCpuCfg (&Val, LOONGARCH_CPUCFG4); + BaseFreq = (UINT32)Val; + LoongArchReadCpuCfg (&Val, LOONGARCH_CPUCFG5); + Result = (UINT32)Val; + ClockMultiplier = Result & 0xffff; + ClockDivide = (Result >> 16) & 0xffff; + + if ((!BaseFreq) || (!ClockMultiplier) || (!ClockDivide)) { + return 0; + } else { + return (BaseFreq * ClockMultiplier / ClockDivide); + } +} +/** + Get the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +GetFreq ( + VOID + ) +{ + if (StableTimerFreq) { + } else { + StableTimerFreq = CalcConstFreq (); + } + + return StableTimerFreq; +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + + UINTN Count; + UINTN Ticks; + UINTN Start; + UINTN End; + + Count = GetFreq (); + Count = (Count * MicroSeconds) / 1000000; + Start = LoongArchReadTime (); + End = Start + Count; + + do { + Ticks = LoongArchReadTime (); + } while (Ticks < End); + + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + UINT32 MicroSeconds; + + if (NanoSeconds % 1000 == 0) { + MicroSeconds = NanoSeconds/1000; + } else { + MicroSeconds = NanoSeconds/1000 + 1; + } + MicroSecondDelay (MicroSeconds); + + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties (). + + @return The current value of the free running performance counter. +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return LoongArchReadTime (); +} +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + *StartValue = BIT2; + } + + if (EndValue != NULL) { + *EndValue = BIT48 - 1; + } + + return GetFreq (); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency = GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, + // i.e. highest bit set in Remainder should <= 33. + // + Shift = MAX (0, HighBitSet64 (Remainder) - 33); + Remainder = RShiftU64 (Remainder, (UINTN) Shift); + Frequency = RShiftU64 (Frequency, (UINTN) Shift); + NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); + + return NanoSeconds; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf new file mode 100644 index 0000000000..86f243998b --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf @@ -0,0 +1,32 @@ +## @file +# Generic LoongArch implementation of TimerLib.h +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TimerLib + FILE_GUID = 740389C7-CC44-4A2F-88DC-89D97D312E7C + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + +# +# VALID_ARCHITECTURES = LOONGARCH64 +# + +[Sources] + TimerLib.c + Count.S + +[Packages] + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + IoLib -- 2.31.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#96259): https://edk2.groups.io/g/devel/message/96259 Mute This Topic: https://groups.io/mt/94954838/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-