From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=T8nNdX4R; spf=pass (domain: linaro.org, ip: 209.85.128.65, mailfrom: leif.lindholm@linaro.org) Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by groups.io with SMTP; Thu, 03 Oct 2019 10:30:09 -0700 Received: by mail-wm1-f65.google.com with SMTP id y21so2964878wmi.0 for ; Thu, 03 Oct 2019 10:30:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=3MVn8vSkyzwG7rckWu5f5pAVROSsI3+MlWxxgbgt7qE=; b=T8nNdX4RDb0yWK9pHu8iCJoLu/sKfbFc0349zQ8h7IXXpsWA1WM6/e4tQ0C2nFL5Ba nG9cyMODjViLESM7wE6jPZefnN3F+OVj1vZptq4grU+q+VEAQ6d41Hb+E3rN8m96Hs+h 3xFXBPQNHF5LuEfxJNlCFxqBy5UQVS9Whw829VsB5Vm56RJMNvI/ensEw3MoxEi4Ws+B li3MzLeLdX11WSQFGyg60y9M4yI7j/2L5i4hjl/N2JLRuwkcR+c/GKFypJkrAtJUSVsh /W7Sir9gYFt/90dldPK0tDPy5Wb/aXpQ6s3OUI5FkYwG4nuILbmea+jDsNi3ULqLFFgq J51A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=3MVn8vSkyzwG7rckWu5f5pAVROSsI3+MlWxxgbgt7qE=; b=fb2WVpOCr/cCAqE8i2y0x3JMJtlAkCPUsFpIrKONQAF/pEdsciZIz5tJl3mY68WJQa 0XRWnDlsHKSQ/GkK0YXu23XYDEeTc4VIHFvH/Oumg+oLpwZrvXiNwJbVOE6AlrCJUO3p xSrcQaT7RHVaHTyPWcyXA8anmZdQGIbJxrxNszCrql+t1C3sz+qwCAi9YREPs2dqcbtj 7eDUPjPFkhPMWny0fGAvmWszHeWiPP9bRLc63U1FQp3rHrH0vI11Fpd0O5Ql6k9skHeO dFvzJVbJB+gxyiA1J8WG2W9RlegUB0rGy814/Rr8HrHqbzI3PD3bVXTpNgjyjJOSpWRc F0pg== X-Gm-Message-State: APjAAAVDZw/MG75fnOa7ogRsNFLWeV9Nlwt/ClFHZvGGPG7KBGeo/N9V iUWKWrlqdfLiCS1SSe5nzYTCTe5uZRw= X-Google-Smtp-Source: APXvYqwKxuSxMSY7Jl/CWg1hTczt9o6CarJvynpvb0y3BVRubTfauFJAgSAdP4klthvLkW8sDgVElw== X-Received: by 2002:a1c:9988:: with SMTP id b130mr8039727wme.164.1570123806469; Thu, 03 Oct 2019 10:30:06 -0700 (PDT) Return-Path: Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id d78sm4123926wmd.47.2019.10.03.10.30.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Oct 2019 10:30:05 -0700 (PDT) Date: Thu, 3 Oct 2019 18:30:04 +0100 From: "Leif Lindholm" To: devel@edk2.groups.io, gilbert.chen@hpe.com Cc: Palmer Dabbelt Subject: Re: [edk2-devel] [plaforms/devel-riscv-v2 PATCHv2 12/14] U500Pkg/TimerDxe: Platform Timer DXE driver Message-ID: <20191003173004.GQ25504@bivouac.eciton.net> References: <20190919035131.4700-1-gilbert.chen@hpe.com> <20190919035131.4700-13-gilbert.chen@hpe.com> MIME-Version: 1.0 In-Reply-To: <20190919035131.4700-13-gilbert.chen@hpe.com> User-Agent: Mutt/1.10.1 (2018-07-13) Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Sep 19, 2019 at 11:51:29AM +0800, Gilbert Chen wrote: > Timer DXE driver for U500 platform based U500 platform implementation > specifc timer registers. > > Signed-off-by: Gilbert Chen > --- > .../SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.c | 311 +++++++++++++++++++++ > .../SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.h | 174 ++++++++++++ > .../U500Pkg/Universal/Dxe/TimerDxe/Timer.uni | 14 + > .../U500Pkg/Universal/Dxe/TimerDxe/TimerDxe.inf | 48 ++++ > .../U500Pkg/Universal/Dxe/TimerDxe/TimerExtra.uni | 12 + > 5 files changed, 559 insertions(+) > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.c > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.h > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.uni > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerDxe.inf > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerExtra.uni > > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.c b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.c > new file mode 100644 > index 00000000..5cb42943 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.c > @@ -0,0 +1,311 @@ > +/** @file > + RISC-V Timer Architectural Protocol for U500 platform. > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "Timer.h" > +#include > +#include > +#include > +#include > +#include > + > +#define CLINT_REG_MTIME 0x0200BFF8 > +#define CLINT_REG_MTIMECMP0 0x02004000 > +#define CLINT_REG_MTIMECMP1 0x02004008 > +#define CLINT_REG_MTIMECMP2 0x02004010 > +#define CLINT_REG_MTIMECMP3 0x02004018 > +#define CLINT_REG_MTIMECMP4 0x02004020 > + > +static volatile void * const p_mtime = (void *)CLINT_REG_MTIME; > +#define MTIME (*p_mtime) > +#define MTIMECMP(i) (p_mtimecmp[i]) > + > +// > +// The handle onto which the Timer Architectural Protocol will be installed > +// > +EFI_HANDLE mTimerHandle = NULL; This one is exported? Or can it be STATIC? > + > +// > +// The Timer Architectural Protocol that this driver produces > +// > +EFI_TIMER_ARCH_PROTOCOL mTimer = { > + TimerDriverRegisterHandler, > + TimerDriverSetTimerPeriod, > + TimerDriverGetTimerPeriod, > + TimerDriverGenerateSoftInterrupt > +}; > + > +// > +// Pointer to the CPU Architectural Protocol instance > +// > +EFI_CPU_ARCH_PROTOCOL *mCpu; But this is only for internal use surely? STATIC? > + > +// > +// The notification function to call on every timer interrupt. > +// A bug in the compiler prevents us from initializing this here. > +// > +EFI_TIMER_NOTIFY mTimerNotifyFunction; STATIC? > + > +// > +// The current period of the timer interrupt > +// > +volatile UINT64 mTimerPeriod = 0; This would be VOLATILE, but I dont think it has the effect you think it does. > + > + > +/** > + 8254 Timer #0 Interrupt Handler. > + > + @param InterruptType The type of interrupt that occured > + @param SystemContext A pointer to the system context when the interrupt occured > +**/ > + > +VOID > +EFIAPI > +TimerInterruptHandler ( > + IN EFI_EXCEPTION_TYPE InterruptType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + EFI_TPL OriginalTPL; > + UINT64 RiscvTimer; > + > + csr_clear(CSR_SIE, MIP_STIP); // enable timer int > + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); > + if (mTimerPeriod == 0) { > + gBS->RestoreTPL (OriginalTPL); > + mCpu->DisableInterrupt(mCpu); > + return; > + } > + if (mTimerNotifyFunction != NULL) { > + mTimerNotifyFunction (mTimerPeriod); > + } > + gBS->RestoreTPL (OriginalTPL); > + > + > + RiscvTimer = readq_relaxed(p_mtime); > + sbi_set_timer(RiscvTimer += mTimerPeriod); > + csr_set(CSR_SIE, MIP_STIP); // enable timer int > + > +} > + > +/** > + > + This function registers the handler NotifyFunction so it is called every time > + the timer interrupt fires. It also passes the amount of time since the last > + handler call to the NotifyFunction. If NotifyFunction is NULL, then the > + handler is unregistered. If the handler is registered, then EFI_SUCCESS is > + returned. If the CPU does not support registering a timer interrupt handler, > + then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler > + when a handler is already registered, then EFI_ALREADY_STARTED is returned. > + If an attempt is made to unregister a handler when a handler is not registered, > + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to > + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR > + is returned. > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param NotifyFunction The function to call when a timer interrupt fires. This > + function executes at TPL_HIGH_LEVEL. The DXE Core will > + register a handler for the timer interrupt, so it can know > + how much time has passed. This information is used to > + signal timer based events. NULL will unregister the handler. > + > + @retval EFI_SUCCESS The timer handler was registered. > + @retval EFI_UNSUPPORTED The platform does not support timer interrupts. > + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already > + registered. > + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not > + previously registered. > + @retval EFI_DEVICE_ERROR The timer handler could not be registered. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverRegisterHandler ( > + IN EFI_TIMER_ARCH_PROTOCOL *This, > + IN EFI_TIMER_NOTIFY NotifyFunction > + ) > +{ > + DEBUG ((DEBUG_INFO, "TimerDriverRegisterHandler(0x%lx) called\n", NotifyFunction)); > + mTimerNotifyFunction = NotifyFunction; > + return EFI_SUCCESS; > +} > + > +/** > + > + This function adjusts the period of timer interrupts to the value specified > + by TimerPeriod. If the timer period is updated, then the selected timer > + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If > + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. > + If an error occurs while attempting to update the timer period, then the > + timer hardware will be put back in its state prior to this call, and > + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt > + is disabled. This is not the same as disabling the CPU's interrupts. > + Instead, it must either turn off the timer hardware, or it must adjust the > + interrupt controller so that a CPU interrupt is not generated when the timer > + interrupt fires. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If > + the timer hardware is not programmable, then EFI_UNSUPPORTED is > + returned. If the timer is programmable, then the timer period > + will be rounded up to the nearest timer period that is supported > + by the timer hardware. If TimerPeriod is set to 0, then the > + timer interrupts will be disabled. > + > + @retval EFI_SUCCESS The timer period was changed. > + @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. > + @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverSetTimerPeriod ( > + IN EFI_TIMER_ARCH_PROTOCOL *This, > + IN UINT64 TimerPeriod > + ) > +{ > + UINT64 RiscvTimer; > + > + DEBUG ((DEBUG_INFO, "TimerDriverSetTimerPeriod(0x%lx)\n", TimerPeriod)); > + > + if (TimerPeriod == 0) { > + mTimerPeriod = 0; > + mCpu->DisableInterrupt(mCpu); > + csr_clear(CSR_SIE, MIP_STIP); // disable timer int > + return EFI_SUCCESS; > + } > + > + mTimerPeriod = TimerPeriod / 10; // convert unit from 100ns to 1us > + > + mCpu->EnableInterrupt(mCpu); > + csr_set(CSR_SIE, MIP_STIP); // enable timer int > + > + RiscvTimer = readq_relaxed(p_mtime); > + sbi_set_timer(RiscvTimer + mTimerPeriod); > + return EFI_SUCCESS; > +} > + > +/** > + > + This function retrieves the period of timer interrupts in 100 ns units, > + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod > + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is > + returned, then the timer is currently disabled. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If > + 0 is returned, then the timer is currently disabled. > + > + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. > + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverGetTimerPeriod ( > + IN EFI_TIMER_ARCH_PROTOCOL *This, > + OUT UINT64 *TimerPeriod > + ) > +{ > + *TimerPeriod = mTimerPeriod; > + return EFI_SUCCESS; > +} > + > +/** > + > + This function generates a soft timer interrupt. If the platform does not support soft > + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. > + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() > + service, then a soft timer interrupt will be generated. If the timer interrupt is > + enabled when this service is called, then the registered handler will be invoked. The > + registered handler should not be able to distinguish a hardware-generated timer > + interrupt from a software-generated timer interrupt. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + > + @retval EFI_SUCCESS The soft timer interrupt was generated. > + @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverGenerateSoftInterrupt ( > + IN EFI_TIMER_ARCH_PROTOCOL *This > + ) > +{ > + return EFI_SUCCESS; > +} > + > +/** > + Initialize the Timer Architectural Protocol driver > + > + @param ImageHandle ImageHandle of the loaded driver > + @param SystemTable Pointer to the System Table > + > + @retval EFI_SUCCESS Timer Architectural Protocol created > + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver. > + @retval EFI_DEVICE_ERROR A device error occured attempting to initialize the driver. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + // > + // Initialize the pointer to our notify function. > + // > + mTimerNotifyFunction = NULL; > + > + // > + // Make sure the Timer Architectural Protocol is not already installed in the system > + // > + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid); > + > + // > + // Find the CPU architectural protocol. > + // > + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &mCpu); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Force the timer to be disabled > + // > + Status = TimerDriverSetTimerPeriod (&mTimer, 0); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Install interrupt handler for RISC-V Timer. > + // > + Status = mCpu->RegisterInterruptHandler (mCpu, EXCEPT_RISCV_TIMER_INT, TimerInterruptHandler); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Force the timer to be enabled at its default period > + // > + Status = TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION); > + ASSERT_EFI_ERROR (Status); > + > + // > + // Install the Timer Architectural Protocol onto a new handle > + // > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &mTimerHandle, > + &gEfiTimerArchProtocolGuid, &mTimer, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + return Status; > +} > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.h b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.h > new file mode 100644 > index 00000000..3bfc415d > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.h > @@ -0,0 +1,174 @@ > +/** @file > + RISC-V Timer Architectural Protocol definitions for U500 platform, > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _TIMER_H_ > +#define _TIMER_H_ Please drop leading _. But also, TIMER_H_ is a bit too generic for an include guard. U500_TIMER_H_? > + > +#include > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +// > +// RISC-V use 100us timer. > +// The default timer tick duration is set to 10 ms = 10 * 1000 * 10 100 ns units > +// > +#define DEFAULT_TIMER_TICK_DURATION 100000 > + > +extern VOID RiscvSetTimerPeriod (UINT32 TimerPeriod); > + > +// > +// Function Prototypes > +// > +/** > + Initialize the Timer Architectural Protocol driver > + > + @param ImageHandle ImageHandle of the loaded driver > + @param SystemTable Pointer to the System Table > + > + @retval EFI_SUCCESS Timer Architectural Protocol created > + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver. > + @retval EFI_DEVICE_ERROR A device error occured attempting to initialize the driver. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +; > + > +/** > + > + This function adjusts the period of timer interrupts to the value specified > + by TimerPeriod. If the timer period is updated, then the selected timer > + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If > + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. > + If an error occurs while attempting to update the timer period, then the > + timer hardware will be put back in its state prior to this call, and > + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt > + is disabled. This is not the same as disabling the CPU's interrupts. > + Instead, it must either turn off the timer hardware, or it must adjust the > + interrupt controller so that a CPU interrupt is not generated when the timer > + interrupt fires. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param NotifyFunction The rate to program the timer interrupt in 100 nS units. If > + the timer hardware is not programmable, then EFI_UNSUPPORTED is > + returned. If the timer is programmable, then the timer period > + will be rounded up to the nearest timer period that is supported > + by the timer hardware. If TimerPeriod is set to 0, then the > + timer interrupts will be disabled. > + > + @retval EFI_SUCCESS The timer period was changed. > + @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. > + @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverRegisterHandler ( > + IN EFI_TIMER_ARCH_PROTOCOL *This, > + IN EFI_TIMER_NOTIFY NotifyFunction > + ) > +; > + > +/** > + > + This function adjusts the period of timer interrupts to the value specified > + by TimerPeriod. If the timer period is updated, then the selected timer > + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If > + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. > + If an error occurs while attempting to update the timer period, then the > + timer hardware will be put back in its state prior to this call, and > + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt > + is disabled. This is not the same as disabling the CPU's interrupts. > + Instead, it must either turn off the timer hardware, or it must adjust the > + interrupt controller so that a CPU interrupt is not generated when the timer > + interrupt fires. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If > + the timer hardware is not programmable, then EFI_UNSUPPORTED is > + returned. If the timer is programmable, then the timer period > + will be rounded up to the nearest timer period that is supported > + by the timer hardware. If TimerPeriod is set to 0, then the > + timer interrupts will be disabled. > + > + @retval EFI_SUCCESS The timer period was changed. > + @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. > + @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverSetTimerPeriod ( > + IN EFI_TIMER_ARCH_PROTOCOL *This, > + IN UINT64 TimerPeriod > + ) > +; > + > +/** > + > + This function retrieves the period of timer interrupts in 100 ns units, > + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod > + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is > + returned, then the timer is currently disabled. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If > + 0 is returned, then the timer is currently disabled. > + > + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. > + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverGetTimerPeriod ( > + IN EFI_TIMER_ARCH_PROTOCOL *This, > + OUT UINT64 *TimerPeriod > + ) > +; > + > +/** > + > + This function generates a soft timer interrupt. If the platform does not support soft > + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. > + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() > + service, then a soft timer interrupt will be generated. If the timer interrupt is > + enabled when this service is called, then the registered handler will be invoked. The > + registered handler should not be able to distinguish a hardware-generated timer > + interrupt from a software-generated timer interrupt. > + > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + > + @retval EFI_SUCCESS The soft timer interrupt was generated. > + @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts. > + > +**/ > +EFI_STATUS > +EFIAPI > +TimerDriverGenerateSoftInterrupt ( > + IN EFI_TIMER_ARCH_PROTOCOL *This > + ) > +; > + > +#endif > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.uni b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.uni > new file mode 100644 > index 00000000..38302244 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/Timer.uni > @@ -0,0 +1,14 @@ > +// /** @file > +// > +// RISC-V Timer Arch protocol strings. > +// > +// Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.
> +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "RISC-V timer driver that provides Timer Arch protocol" > + > +#string STR_MODULE_DESCRIPTION #language en-US "RISC-V timer driver that provides Timer Arch protocol." > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerDxe.inf b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerDxe.inf > new file mode 100644 > index 00000000..f8af6889 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerDxe.inf > @@ -0,0 +1,48 @@ > +## @file > +# RISC-V Timer Arch protocol module for U500 platform > +# > +# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 Please bump specification version. > + BASE_NAME = Timer > + MODULE_UNI_FILE = Timer.uni > + FILE_GUID = 3F75D495-23FF-46B6-9D19-0DECC8A4EA91 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + > + ENTRY_POINT = TimerDriverInitialize > + > +[Packages] > + MdePkg/MdePkg.dec > + RiscVPkg/RiscVPkg.dec > + > +[LibraryClasses] > + UefiBootServicesTableLib > + BaseLib > + DebugLib > + UefiDriverEntryPoint > + IoLib > + RiscVCpuLib > + RiscVOpensbiLib Please sort alphabetically. / Leif > + > +[Sources] > + Timer.h > + Timer.c > + > +[Protocols] > + gEfiCpuArchProtocolGuid ## CONSUMES > + gEfiTimerArchProtocolGuid ## PRODUCES > + > +[Pcd] > + gUefiRiscVPkgTokenSpaceGuid.PcdRiscVMachineTimerFrequencyInHerz > + > +[Depex] > + gEfiCpuArchProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + TimerExtra.uni > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerExtra.uni b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerExtra.uni > new file mode 100644 > index 00000000..cf25ff14 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/TimerDxe/TimerExtra.uni > @@ -0,0 +1,12 @@ > +// /** @file > +// Timer Localized Strings and Content > +// > +// Copyright (c) 2016, Hewlett Packard Enterprise Development LP. All rights reserved.
> +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US > +"RISC-V Timer DXE Driver" > -- > 2.12.0.windows.1 > > > >