Timer library for RISC-V Signed-off-by: Abner Chang <abner.ch...@hpe.com> --- .../Library/RiscVTimerLib/BaseRiscVTimerLib.inf | 34 ++++ RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.c | 195 +++++++++++++++++++++ RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.h | 21 +++ RiscVPkg/RiscVPkg.dec | 9 + 4 files changed, 259 insertions(+) create mode 100644 RiscVPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf create mode 100644 RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.c create mode 100644 RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.h
diff --git a/RiscVPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf b/RiscVPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf new file mode 100644 index 0000000..af27049 --- /dev/null +++ b/RiscVPkg/Library/RiscVTimerLib/BaseRiscVTimerLib.inf @@ -0,0 +1,34 @@ +## @file +# RISC-V Timer Library Instance. +# +# Copyright (c) 2016 - 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001b + BASE_NAME = BaseRiscVTimerLib + FILE_GUID = FB648CF5-91BE-4737-9023-FD807AC6D96D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + +[Sources] + RiscVTimerLib.c + +[Packages] + MdePkg/MdePkg.dec + RiscVPkg/RiscVPkg.dec + +[Pcd] + gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerTickInNanoSecond + gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerFrequencyInHerz + +[LibraryClasses] + BaseLib + PcdLib + RiscVCpuLib + RiscVPlatformTimerLib + diff --git a/RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.c b/RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.c new file mode 100644 index 0000000..acb8c77 --- /dev/null +++ b/RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.c @@ -0,0 +1,195 @@ +/** @file + RISC-V instance of Timer Library. + + Copyright (c) 2016 - 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <RiscVTimerLib.h> + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param Delay A period of time to delay in ticks. + +**/ +VOID +InternalRiscVTimerDelay ( + IN UINT32 Delay + ) +{ + UINT32 Ticks; + UINT32 Times; + + Times = Delay >> (RISCV_TIMER_COMPARE_BITS - 2); + Delay &= (( 1 << (RISCV_TIMER_COMPARE_BITS - 2)) - 1); + do { + // + // The target timer count is calculated here + // + Ticks = RiscVReadMachineTimer () + Delay; + Delay = 1 << (RISCV_TIMER_COMPARE_BITS - 2); + while (((Ticks - RiscVReadMachineTimer ()) & ( 1 << (RISCV_TIMER_COMPARE_BITS - 1))) == 0) { + CpuPause (); + } + } while (Times-- > 0); +} + +/** + 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 + ) +{ + InternalRiscVTimerDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + MicroSeconds, + PcdGet64 (PcdRiscVMachineTimerFrequencyInHerz) + ), + 1000000u + ) + ); + 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 + ) +{ + InternalRiscVTimerDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + NanoSeconds, + PcdGet64 (PcdRiscVMachineTimerFrequencyInHerz) + ), + 1000000000u + ) + ); + 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 (UINT64)RiscVReadMachineTimer (); +} + +/**return + 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 = 0; + } + + if (EndValue != NULL) { + *EndValue = 32 - 1; + } + + return PcdGet64 (PcdRiscVMachineTimerFrequencyInHerz); +} + +/** + 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 NanoSeconds; + UINT32 Remainder; + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, PcdGet64 (PcdRiscVMachineTimerFrequencyInHerz), &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 (PcdRiscVMachineTimerFrequencyInHerz)); + + return NanoSeconds; +} diff --git a/RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.h b/RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.h new file mode 100644 index 0000000..bac3a70 --- /dev/null +++ b/RiscVPkg/Library/RiscVTimerLib/RiscVTimerLib.h @@ -0,0 +1,21 @@ +/** @file + RISC-V timer library definitions. + + Copyright (c) 2016 - 2019, Hewlett Packard Enterprise Development LP. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef _RISCV_TIMER_LIB_INTERNAL_H_ +#define _RISCV_TIMER_LIB_INTERNAL_H_ + +#include <Uefi.h> +#include <Library/PcdLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseLib.h> + +#include <Library/RiscVCpuLib.h> + +#endif // _RISCV_TIMER_LIB_INTERNAL_H_ diff --git a/RiscVPkg/RiscVPkg.dec b/RiscVPkg/RiscVPkg.dec index 74314e8..a91392f 100644 --- a/RiscVPkg/RiscVPkg.dec +++ b/RiscVPkg/RiscVPkg.dec @@ -23,5 +23,14 @@ [Guids] gUefiRiscVPkgTokenSpaceGuid = { 0x4261e9c8, 0x52c0, 0x4b34, { 0x85, 0x3d, 0x48, 0x46, 0xea, 0xd3, 0xb7, 0x2c}} +[PcdsFixedAtBuild] + # + # 1000000000 + # PcdRiscVMachineTimerTickInNanoSecond = --------------------------------------- + # PcdRiscVMachineTimerFrequencyInHerz + # + gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerTickInNanoSecond|100|UINT64|0x00001010 + gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerFrequencyInHerz|10000000|UINT64|0x00001011 + [UserExtensions.TianoCore."ExtraFiles"] RiscVPkgExtra.uni -- 2.7.4 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#47768): https://edk2.groups.io/g/devel/message/47768 Mute This Topic: https://groups.io/mt/34258214/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-