This library provides a delay interface and a timing interface. Signed-off-by: xianglai li <lixiang...@loongson.cn> --- .../Include/Library/StableTimer.h | 42 +++ .../Library/StableTimerLib/Count.S | 26 ++ .../Library/StableTimerLib/TimerLib.c | 262 ++++++++++++++++++ .../Library/StableTimerLib/TimerLib.inf | 28 ++ 4 files changed, 358 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..bd6a1eb90f --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h @@ -0,0 +1,42 @@ +/** @file + + Copyright (c) 2021 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. +**/ +UINTN +EFIAPI +CsrReadTime ( + VOID + ); + +/** + Calculate the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +CalcConstFreq ( + VOID + ); +#endif diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S new file mode 100644 index 0000000000..42f878caf8 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S @@ -0,0 +1,26 @@ +#------------------------------------------------------------------------------ +# +# Count for LoongArch +# +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#------------------------------------------------------------------------------ + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "Library/Cpu.h" +#include "LoongArchAsmMacro.h" +# +# Set cpu interrupts +# @param A0 The interrupt number +# +ASM_FUNC(CpuSetIP) + csrrd T0, LOONGARCH_CSR_ECFG + or T0, T0, A0 + csrwr T0, LOONGARCH_CSR_ECFG + 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..21e3749ee6 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c @@ -0,0 +1,262 @@ +/** @file + Generic LoongArch implementation of TimerLib.h + + Copyright (c) 2021 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; + +/** + Gets the timer count value. + + @param[] VOID + + @retval timer count value. +**/ +UINTN +EFIAPI +CsrReadTime ( + VOID + ) +{ + UINTN Value = 0; + __asm__ __volatile__( + " rdtime.d %0, $r0\n" + : "=r" (Value)); + return Value; +} + +/** + Calculate the timer frequency. + + @param[] VOID + + @retval Timer frequency. +**/ +UINT32 +EFIAPI +CalcConstFreq ( + VOID + ) +{ + UINT32 Result; + UINT32 BaseFreq; + UINT32 ClockMultiplier; + UINT32 ClockDivide; + + LOONGARCH_GET_CPUCFG (BaseFreq, LOONGARCH_CPUCFG4); + LOONGARCH_GET_CPUCFG (Result, LOONGARCH_CPUCFG5); + 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 = CsrReadTime (); + End = Start + Count; + + do { + Ticks = CsrReadTime (); + } 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 CsrReadTime (); +} +/** + 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..fef0fac08c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf @@ -0,0 +1,28 @@ +## @file +# Generic LoongArch implementation of TimerLib.h +# +# Copyright (c) 2021 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 + +[Sources.common] + 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 (#87999): https://edk2.groups.io/g/devel/message/87999 Mute This Topic: https://groups.io/mt/90014668/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-