From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web08.3621.1665720096306239810 for ; Thu, 13 Oct 2022 21:01:36 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Bx32sZ30hjMt8tAA--.26776S8; Fri, 14 Oct 2022 12:01:35 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: quic_llindhol@quicinc.com, michael.d.kinney@intel.com, kraxel@redhat.com, ardb@kernel.org, maobibo@loongson.cn Subject: [edk2-platforms][PATCH V3 06/16] Platform/Loongson: Add StableTimerLib. Date: Fri, 14 Oct 2022 12:01:19 +0800 Message-Id: <6fc736d0eb2dfed114a7daa7d411950cf4fedd62.1665719826.git.lixianglai@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8Bx32sZ30hjMt8tAA--.26776S8 X-Coremail-Antispam: 1UD129KBjvJXoW3WryDur1fWrWrtFWfCry8Krg_yoWDGF17pr sxZFy7Gr18Jr15A345Ja1YgFy5AwsxCrZ8WF45Cr1xA3yDA3s3Ww1ktr40qFyfZrW3Wry0 q3yIga1UuF4rJ3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UUUUUUUUU== X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ Content-Transfer-Encoding: quoted-printable This library provides a delay interface and a timing interface. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Signed-off-by: xianglai li --- .../Include/Library/StableTimer.h | 43 ++++ .../Library/StableTimerLib/Count.S | 35 +++ .../Library/StableTimerLib/TimerLib.c | 242 ++++++++++++++++++ .../Library/StableTimerLib/TimerLib.inf | 28 ++ 4 files changed, 348 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Stab= leTimer.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/Count.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/TimerLib.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/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..09a2d07404 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h @@ -0,0 +1,43 @@ +/** @file=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Csr - Cpu Status Register=0D + - Calc - Calculation=0D + - Freq - frequency=0D +**/=0D +=0D +#ifndef STABLE_TIMER_H_=0D +#define STABLE_TIMER_H_=0D +#include "Library/Cpu.h"=0D +=0D +/**=0D + Gets the timer count value.=0D +=0D + @param[] VOID=0D +=0D + @retval timer count value.=0D +**/=0D +extern=0D +UINTN=0D +EFIAPI=0D +LoongArchReadTime (=0D + VOID=0D + );=0D +=0D +/**=0D + Calculate the timer frequency.=0D +=0D + @param[] VOID=0D +=0D + @retval Timer frequency.=0D +**/=0D +UINT32=0D +EFIAPI=0D +CalcConstFreq (=0D + VOID=0D + );=0D +#endif=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Coun= t.S b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S new file mode 100644 index 0000000000..f22635712c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S @@ -0,0 +1,35 @@ +#-------------------------------------------------------------------------= -----=0D +#=0D +# Count for LoongArch=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +#-------------------------------------------------------------------------= -----=0D +=0D +#ifndef __ASSEMBLY__=0D +#define __ASSEMBLY__=0D +#endif=0D +=0D +#include "Library/Cpu.h"=0D +#include "LoongArchAsmMacro.h"=0D +#=0D +# Set cpu interrupts=0D +# @param A0 The interrupt number=0D +#=0D +ASM_FUNC(CpuSetIP)=0D + csrrd T0, LOONGARCH_CSR_ECFG=0D + or T0, T0, A0=0D + csrwr T0, LOONGARCH_CSR_ECFG=0D + jirl ZERO, RA,0=0D +=0D +#=0D +#Gets the timer count value.=0D +#=0D +#@param[] VOID=0D +#=0D +#@retval timer count value.=0D +ASM_FUNC(LoongArchReadTime)=0D + rdtime.d A0, ZERO=0D + jirl ZERO, RA,0=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Time= rLib.c b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib= .c new file mode 100644 index 0000000000..660a5d8b0b --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c @@ -0,0 +1,242 @@ +/** @file=0D + Generic LoongArch implementation of TimerLib.h=0D +=0D + Copyright (c) 2021 Loongson Technology Corporation Limited. All rights r= eserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Freq - Frequency=0D + - Csr - Cpu Status Register=0D + - calc - calculate=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "Library/StableTimer.h"=0D +#include "Library/Cpu.h"=0D +=0D +UINT32 StableTimerFreq =3D 0;=0D +=0D +/**=0D + Calculate the timer frequency.=0D +=0D + @param[] VOID=0D +=0D + @retval Timer frequency.=0D +**/=0D +UINT32=0D +EFIAPI=0D +CalcConstFreq (=0D + VOID=0D + )=0D +{=0D + UINT32 Result;=0D + UINT32 BaseFreq;=0D + UINT32 ClockMultiplier;=0D + UINT32 ClockDivide;=0D +=0D + LOONGARCH_GET_CPUCFG (BaseFreq, LOONGARCH_CPUCFG4);=0D + LOONGARCH_GET_CPUCFG (Result, LOONGARCH_CPUCFG5);=0D + ClockMultiplier =3D Result & 0xffff;=0D + ClockDivide =3D (Result >> 16) & 0xffff;=0D +=0D + if ((!BaseFreq)=0D + || (!ClockMultiplier)=0D + || (!ClockDivide))=0D + {=0D + return 0;=0D + }=0D + else {=0D + return (BaseFreq * ClockMultiplier / ClockDivide);=0D + }=0D +}=0D +/**=0D + Get the timer frequency.=0D +=0D + @param[] VOID=0D +=0D + @retval Timer frequency.=0D +**/=0D +UINT32=0D +EFIAPI=0D +GetFreq (=0D + VOID=0D + )=0D +{=0D + if (StableTimerFreq) {=0D + } else {=0D + StableTimerFreq =3D CalcConstFreq ();=0D + }=0D +=0D + return StableTimerFreq;=0D +}=0D +=0D +/**=0D + Stalls the CPU for at least the given number of microseconds.=0D +=0D + Stalls the CPU for the number of microseconds specified by MicroSeconds.= =0D +=0D + @param MicroSeconds The minimum number of microseconds to delay.=0D +=0D + @return MicroSeconds=0D +=0D +**/=0D +UINTN=0D +EFIAPI=0D +MicroSecondDelay (=0D + IN UINTN MicroSeconds=0D + )=0D +{=0D +=0D + UINTN Count;=0D + UINTN Ticks;=0D + UINTN Start;=0D + UINTN End;=0D +=0D + Count =3D GetFreq ();=0D + Count =3D (Count * MicroSeconds) / 1000000;=0D + Start =3D LoongArchReadTime ();=0D + End =3D Start + Count;=0D +=0D + do {=0D + Ticks =3D LoongArchReadTime ();=0D + } while (Ticks < End);=0D +=0D + return MicroSeconds;=0D +}=0D +=0D +/**=0D + Stalls the CPU for at least the given number of nanoseconds.=0D +=0D + Stalls the CPU for the number of nanoseconds specified by NanoSeconds.=0D +=0D + @param NanoSeconds The minimum number of nanoseconds to delay.=0D +=0D + @return NanoSeconds=0D +=0D +**/=0D +UINTN=0D +EFIAPI=0D +NanoSecondDelay (=0D + IN UINTN NanoSeconds=0D + )=0D +{=0D + UINT32 MicroSeconds;=0D +=0D + if (NanoSeconds % 1000 =3D=3D 0) {=0D + MicroSeconds =3D NanoSeconds/1000;=0D + }else {=0D + MicroSeconds =3D NanoSeconds/1000 + 1;=0D + }=0D + MicroSecondDelay (MicroSeconds);=0D +=0D + return NanoSeconds;=0D +}=0D +=0D +/**=0D + Retrieves the current value of a 64-bit free running performance counter= .=0D +=0D + Retrieves the current value of a 64-bit free running performance counter= . The=0D + counter can either count up by 1 or count down by 1. If the physical=0D + performance counter counts by a larger increment, then the counter value= s=0D + must be translated. The properties of the counter can be retrieved from= =0D + GetPerformanceCounterProperties ().=0D +=0D + @return The current value of the free running performance counter.=0D +=0D +**/=0D +UINT64=0D +EFIAPI=0D +GetPerformanceCounter (=0D + VOID=0D + )=0D +{=0D + return LoongArchReadTime ();=0D +}=0D +/**=0D + Retrieves the 64-bit frequency in Hz and the range of performance counte= r=0D + values.=0D +=0D + If StartValue is not NULL, then the value that the performance counter s= tarts=0D + with immediately after is it rolls over is returned in StartValue. If=0D + EndValue is not NULL, then the value that the performance counter end wi= th=0D + immediately before it rolls over is returned in EndValue. The 64-bit=0D + frequency of the performance counter in Hz is always returned. If StartV= alue=0D + is less than EndValue, then the performance counter counts up. If StartV= alue=0D + is greater than EndValue, then the performance counter counts down. For= =0D + example, a 64-bit free running counter that counts up would have a Start= Value=0D + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counte= r=0D + that counts down would have a StartValue of 0xFFFFFF and an EndValue of = 0.=0D +=0D + @param StartValue The value the performance counter starts with when i= t=0D + rolls over.=0D + @param EndValue The value that the performance counter ends with bef= ore=0D + it rolls over.=0D +=0D + @return The frequency in Hz.=0D +=0D +**/=0D +UINT64=0D +EFIAPI=0D +GetPerformanceCounterProperties (=0D + OUT UINT64 *StartValue, OPTIONAL=0D + OUT UINT64 *EndValue OPTIONAL=0D + )=0D +{=0D + if (StartValue !=3D NULL) {=0D + *StartValue =3D BIT2;=0D + }=0D +=0D + if (EndValue !=3D NULL) {=0D + *EndValue =3D BIT48 - 1;=0D + }=0D +=0D + return GetFreq ();=0D +}=0D +=0D +/**=0D + Converts elapsed ticks of performance counter to time in nanoseconds.=0D +=0D + This function converts the elapsed ticks of running performance counter = to=0D + time value in unit of nanoseconds.=0D +=0D + @param Ticks The number of elapsed ticks of running performance cou= nter.=0D +=0D + @return The elapsed time in nanoseconds.=0D +=0D +**/=0D +UINT64=0D +EFIAPI=0D +GetTimeInNanoSecond (=0D + IN UINT64 Ticks=0D + )=0D +{=0D + UINT64 Frequency;=0D + UINT64 NanoSeconds;=0D + UINT64 Remainder;=0D + INTN Shift;=0D +=0D + Frequency =3D GetPerformanceCounterProperties (NULL, NULL);=0D +=0D + //=0D + // Ticks=0D + // Time =3D --------- x 1,000,000,000=0D + // Frequency=0D + //=0D + NanoSeconds =3D MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remai= nder), 1000000000u);=0D +=0D + //=0D + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.=0D + // Since 2^29 < 1,000,000,000 =3D 0x3B9ACA00 < 2^30, Remainder should < = 2^(64-30) =3D 2^34,=0D + // i.e. highest bit set in Remainder should <=3D 33.=0D + //=0D + Shift =3D MAX (0, HighBitSet64 (Remainder) - 33);=0D + Remainder =3D RShiftU64 (Remainder, (UINTN) Shift);=0D + Frequency =3D RShiftU64 (Frequency, (UINTN) Shift);=0D + NanoSeconds +=3D DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u)= , Frequency, NULL);=0D +=0D + return NanoSeconds;=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Time= rLib.inf b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerL= ib.inf new file mode 100644 index 0000000000..fef0fac08c --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf @@ -0,0 +1,28 @@ +## @file=0D +# Generic LoongArch implementation of TimerLib.h=0D +#=0D +# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D TimerLib=0D + FILE_GUID =3D 740389C7-CC44-4A2F-88DC-89D97D312E= 7C=0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D TimerLib=0D +=0D +[Sources.common]=0D + TimerLib.c=0D + Count.S=0D +=0D +[Packages]=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=0D + MdePkg/MdePkg.dec=0D +=0D +[LibraryClasses]=0D + DebugLib=0D + IoLib=0D --=20 2.31.1