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.3550.1668157960197213090 for ; Fri, 11 Nov 2022 01:12:40 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lixianglai@loongson.cn) Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8DxndoGEm5jhxMGAA--.19241S3; Fri, 11 Nov 2022 17:12:38 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxFlcAEm5jXc0QAA--.27651S8; Fri, 11 Nov 2022 17:12:38 +0800 (CST) From: "xianglai" To: devel@edk2.groups.io Cc: Bibo Mao , Chao Li , Leif Lindholm , Liming Gao , Michael D Kinney Subject: [edk2-platforms][PATCH V5 06/15] Platform/Loongson: Add StableTimerLib. Date: Fri, 11 Nov 2022 17:12:21 +0800 Message-Id: <7831d165809e5e96efbf9e78d3538ded0f4543a2.1668157715.git.lixianglai@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxFlcAEm5jXc0QAA--.27651S8 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvJXoW3Kw45ZF4rGw1xKryDCF4DJwb_yoWDKw13pr sxZa47Kr18Gr45Aw13t3WjgFy5Aw43Cr98GF45Cr18A3yDA3s3Ww1ktFW0qFyfZrW3Wry0 q3yIga1UuF48J3DanT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU bFAFc2x0x2IEx4CE42xK8VAvwI8IcIk0rVWrJVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4 AK67xGY2AK021l84ACjcxK6xIIjxv20xvE14v26ryj6F1UM28EF7xvwVC0I7IYx2IY6xkF 7I0E14v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x 0267AKxVWxJr0_GcWln4kS14v26r1Y6r17M2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF 6xkI12xvs2x26I8E6xACxx1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x8ErcxFaVAv8V WrMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwCF04k20xvY0x0EwIxGrwCF 04k20xvE74AGY7Cv6cx26rWl4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1l4IxYO2xFxVAFwI0_Jr v_JF1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY 17CE14v26r126r1DMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Xr0_Ar1lIxAIcV C0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY 6I8E87Iv67AKxVWxJVW8Jr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2Kf nxnUUI43ZEXa7xRihFxUUUUUU== Content-Transfer-Encoding: quoted-printable This library provides a delay interface and a timing interface.=0D =0D REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054=0D =0D Cc: Bibo Mao =0D Cc: Chao Li =0D Cc: Leif Lindholm =0D Cc: Liming Gao =0D Cc: Michael D Kinney =0D Signed-off-by: xianglai li =0D ---=0D .../Include/Library/StableTimer.h | 59 +++++=0D .../Library/StableTimerLib/Count.S | 52 ++++=0D .../Library/StableTimerLib/TimerLib.c | 236 ++++++++++++++++++=0D .../Library/StableTimerLib/TimerLib.inf | 32 +++=0D 4 files changed, 379 insertions(+)=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/Library/Stab= leTimer.h=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/Count.S=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/TimerLib.c=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/StableTimerL= ib/TimerLib.inf=0D =0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer= .h b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h=0D new file mode 100644=0D index 0000000000..93f5b66c34=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Include/Library/StableTimer.h=0D @@ -0,0 +1,59 @@=0D +/** @file=0D +=0D + Copyright (c) 2022 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 +=0D +/*=0D + Reads data from the specified CPUCFG register.=0D +=0D + @param[OUT] Val Pointer to the variable used to store the CPUCFG regi= ster value.=0D + @param[IN] reg Specifies the register number of the CPUCFG to read t= he data.=0D +=0D + @retval none=0D + */=0D +extern=0D +VOID=0D +LoongArchReadCpuCfg (=0D + UINT64 *Val,=0D + UINT64 reg=0D + );=0D +=0D +#endif // STABLE_TIMER_H_=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Coun= t.S b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S=0D new file mode 100644=0D index 0000000000..4e0e718381=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/Count.S=0D @@ -0,0 +1,52 @@=0D +#-------------------------------------------------------------------------= -----=0D +#=0D +# Count for LoongArch=0D +#=0D +# Copyright (c) 2022 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 +=0D +ASM_GLOBAL ASM_PFX(CpuSetIP)=0D +ASM_GLOBAL ASM_PFX(LoongArchReadTime)=0D +ASM_GLOBAL ASM_PFX(LoongArchReadCpuCfg)=0D +=0D +#=0D +# Set cpu interrupts=0D +# @param A0 The interrupt number=0D +#=0D +=0D +ASM_PFX(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 +#@param[] VOID=0D +#@retval timer count value.=0D +#=0D +=0D +ASM_PFX(LoongArchReadTime):=0D + rdtime.d A0, ZERO=0D + jirl ZERO, RA, 0=0D +=0D +#=0D +# Read Csr CPUCFG register.=0D +# @param A0 Pointer to the variable used to store the CPUCFG register = value.=0D +# @param A1 Specifies the register number of the CPUCFG to read the da= ta.=0D +# @retval none=0D +#=0D +=0D +ASM_PFX(LoongArchReadCpuCfg):=0D + cpucfg T0, A1=0D + stptr.d T0, A0, 0=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=0D new file mode 100644=0D index 0000000000..135fb22611=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.c= =0D @@ -0,0 +1,236 @@=0D +/** @file=0D + Generic LoongArch implementation of TimerLib.h=0D +=0D + Copyright (c) 2022 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 + UINT64 Val;=0D +=0D + LoongArchReadCpuCfg (&Val, LOONGARCH_CPUCFG4);=0D + BaseFreq =3D (UINT32)Val;=0D + LoongArchReadCpuCfg (&Val, LOONGARCH_CPUCFG5);=0D + Result =3D (UINT32)Val;=0D + ClockMultiplier =3D Result & 0xffff;=0D + ClockDivide =3D (Result >> 16) & 0xffff;=0D +=0D + if ((!BaseFreq) || (!ClockMultiplier) || (!ClockDivide)) {=0D + return 0;=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 +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 +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 +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 +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 +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=0D new file mode 100644=0D index 0000000000..86f243998b=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.in= f=0D @@ -0,0 +1,32 @@=0D +## @file=0D +# Generic LoongArch implementation of TimerLib.h=0D +#=0D +# Copyright (c) 2022 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 +#=0D +# VALID_ARCHITECTURES =3D LOONGARCH64=0D +#=0D +=0D +[Sources]=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 -- =0D 2.31.1=0D =0D