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.web10.3566.1668157964248485765 for ; Fri, 11 Nov 2022 01:12:45 -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 _____8BxHLcLEm5jmRMGAA--.7467S3; Fri, 11 Nov 2022 17:12:43 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxFlcAEm5jXc0QAA--.27651S12; Fri, 11 Nov 2022 17:12:41 +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 10/15] Platform/Loongson: Add timer Dxe driver. Date: Fri, 11 Nov 2022 17:12:25 +0800 Message-Id: <020fd4009f60f83db22e30017009b6e4c7ed7636.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--.27651S12 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjvAXoWfKryrCr1kCF43GFWUCw1rJFb_yoW8tr4rAo W8uFZFvw18Gr18Xa98JFyxJa42qF1kuws0qr4vgFykCFnYy3Z8Kr9Fyry5Kw1fZrWrJF4D A34xWa4kJF43X3Z5n29KB7ZKAUJUUUU3529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnRJU UUkG1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64 kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY 1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVWxJr0_GcWl84ACjcxK6I8E87Iv6x kF7I0E14v26F4UJVW0owAaw2AFwI0_JF0_Jw1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAq jxCEc2xF0cIa020Ex4CE44I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E74AGY7Cv6c x26rWlOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxkF7I0En4kS14v26r12 6r1DMxAIw28IcxkI7VAKI48JMxAIw28IcVCjz48v1sIEY20_WwCFx2IqxVCFs4IE7xkEbV WUJVW8JwCFI7km07C267AKxVWUAVWUtwC20s026c02F40E14v26r1j6r18MI8I3I0E7480 Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7 IYx2IY67AKxVW7JVWDJwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k2 6cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4UJVWxJr1lIxAIcVC2z280aVCY1x 0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x0zR9iSdUUUUU= Content-Transfer-Encoding: quoted-printable This driver produces Timer Architectural Protocol,=0D Registers a timer interrupt and initializes the timer.=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 .../Drivers/StableTimerDxe/Timer.c | 388 ++++++++++++++++++=0D .../Drivers/StableTimerDxe/Timer.h | 172 ++++++++=0D .../Drivers/StableTimerDxe/TimerConfig.S | 38 ++=0D .../Drivers/StableTimerDxe/TimerDxe.inf | 44 ++=0D 4 files changed, 642 insertions(+)=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/Timer.c=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/Timer.h=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/TimerConfig.S=0D create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/TimerDxe.inf=0D =0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= r.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.c=0D new file mode 100644=0D index 0000000000..e09da71272=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.c=0D @@ -0,0 +1,388 @@=0D +/** @file=0D + Timer Architectural Protocol as defined in the DXE CIS=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 +#include =0D +#include "Library/Cpu.h"=0D +#include =0D +#include =0D +#include "Timer.h"=0D +#include =0D +#include =0D +=0D +//=0D +// The handle onto which the Timer Architectural Protocol will be installe= d=0D +//=0D +EFI_HANDLE mTimerHandle =3D NULL;=0D +EFI_EVENT EfiExitBootServicesEvent =3D (EFI_EVENT)NULL;=0D +=0D +//=0D +// The Timer Architectural Protocol that this driver produces=0D +//=0D +EFI_TIMER_ARCH_PROTOCOL mTimer =3D {=0D + TimerDriverRegisterHandler,=0D + TimerDriverSetTimerPeriod,=0D + TimerDriverGetTimerPeriod,=0D + TimerDriverGenerateSoftInterrupt=0D +};=0D +=0D +//=0D +// Pointer to the CPU Architectural Protocol instance=0D +//=0D +EFI_CPU_ARCH_PROTOCOL *mCpu;=0D +=0D +//=0D +// The notification function to call on every timer interrupt.=0D +// A bug in the compiler prevents us from initializing this here.=0D +//=0D +EFI_TIMER_NOTIFY mTimerNotifyFunction;=0D +=0D +//=0D +// The current period of the timer interrupt=0D +//=0D +volatile UINT64 mTimerPeriod =3D 0;=0D +volatile UINT64 mTimerTicks =3D 0;=0D +=0D +//=0D +// Const frequence in Hz=0D +//=0D +extern UINT32 StableTimerFreq;=0D +=0D +/**=0D + Sets the counter value for timer.=0D +=0D + @param Count The 16-bit counter value to program into stable timer.=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +SetPitCount (=0D + IN UINT64 Count=0D + )=0D +{=0D + if (Count <=3D 4) {=0D + return;=0D + }=0D +=0D + Count &=3D LOONGARCH_CSR_TMCFG_TIMEVAL;=0D + Count |=3D LOONGARCH_CSR_TMCFG_EN | LOONGARCH_CSR_TMCFG_PERIOD;=0D + LoongarchWriteqTmcfg (Count);=0D +}=0D +=0D +/**=0D + Timer Interrupt Handler.=0D +=0D + @param InterruptType The type of interrupt that occurred=0D + @param SystemContext A pointer to the system context when the interru= pt occurred=0D +=0D + @retval VOID=0D +**/=0D +VOID=0D +EFIAPI=0D +TimerInterruptHandler (=0D + IN EFI_EXCEPTION_TYPE InterruptType,=0D + IN EFI_SYSTEM_CONTEXT SystemContext=0D + )=0D +{=0D + EFI_TPL OriginalTPL;=0D +=0D + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL);=0D +=0D + //=0D + // Clear interrupt.=0D + //=0D + LoongarchWriteqTintclr (0x1);=0D +=0D + if (mTimerNotifyFunction !=3D NULL) {=0D + //=0D + // @bug : This does not handle missed timer interrupts=0D + //=0D + mTimerNotifyFunction (mTimerPeriod);=0D + }=0D +=0D + gBS->RestoreTPL (OriginalTPL);=0D +}=0D +=0D +/**=0D + This function registers the handler NotifyFunction so it is called every= time=0D + the timer interrupt fires. It also passes the amount of time since the = last=0D + handler call to the NotifyFunction. If NotifyFunction is NULL, then the= =0D + handler is unregistered. If the handler is registered, then EFI_SUCCESS= is=0D + returned. If the CPU does not support registering a timer interrupt han= dler,=0D + then EFI_UNSUPPORTED is returned. If an attempt is made to register a h= andler=0D + when a handler is already registered, then EFI_ALREADY_STARTED is return= ed.=0D + If an attempt is made to unregister a handler when a handler is not regi= stered,=0D + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting t= o=0D + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ER= ROR=0D + is returned.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D + @param NotifyFunction The function to call when a timer interrupt fire= s. This=0D + function executes at TPL_HIGH_LEVEL. The DXE Co= re will=0D + register a handler for the timer interrupt, so i= t can know=0D + how much time has passed. This information is u= sed to=0D + signal timer based events. NULL will unregister= the handler.=0D +=0D + @retval EFI_SUCCESS The timer handler was registered.= =0D + @retval EFI_UNSUPPORTED The platform does not support time= r interrupts.=0D + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a = handler is already=0D + registered.=0D + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a hand= ler was not=0D + previously registered.=0D + @retval EFI_DEVICE_ERROR The timer handler could not be reg= istered.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverRegisterHandler (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This,=0D + IN EFI_TIMER_NOTIFY NotifyFunction=0D + )=0D +{=0D + //=0D + // Check for invalid parameters=0D + //=0D + if ((NotifyFunction =3D=3D NULL)=0D + && (mTimerNotifyFunction =3D=3D NULL))=0D + {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + if ((NotifyFunction !=3D NULL)=0D + && mTimerNotifyFunction !=3D NULL)=0D + {=0D + return EFI_ALREADY_STARTED;=0D + }=0D +=0D + mTimerNotifyFunction =3D NotifyFunction;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + This function adjusts the period of timer interrupts to the value specif= ied=0D + by TimerPeriod. If the timer period is updated, then the selected timer= =0D + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If=0D + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned= .=0D + If an error occurs while attempting to update the timer period, then the= =0D + timer hardware will be put back in its state prior to this call, and=0D + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt=0D + is disabled. This is not the same as disabling the CPU's interrupts.=0D + Instead, it must either turn off the timer hardware, or it must adjust t= he=0D + interrupt controller so that a CPU interrupt is not generated when the t= imer=0D + interrupt fires.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D + @param TimerPeriod The rate to program the timer interrupt in 100 nS= units. If=0D + the timer hardware is not programmable, then EFI_= UNSUPPORTED is=0D + returned. If the timer is programmable, then the= timer period=0D + will be rounded up to the nearest timer period th= at is supported=0D + by the timer hardware. If TimerPeriod is set to = 0, then the=0D + timer interrupts will be disabled.=0D +=0D + @retval EFI_SUCCESS The timer period was changed.=0D + @retval EFI_UNSUPPORTED The platform cannot change the period o= f the timer interrupt.=0D + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverSetTimerPeriod (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This,=0D + IN UINT64 TimerPeriod=0D + )=0D +{=0D + UINT64 TimerCount;=0D +=0D + if (TimerPeriod =3D=3D 0) {=0D + //=0D + // Disable timer interrupt for a TimerPeriod of 0=0D + //=0D + mCpu->DisableInterrupt (mCpu);=0D + } else {=0D +=0D + TimerCount =3D TimerPeriod * StableTimerFreq / 10000000ULL;=0D +=0D + if (TimerCount >=3D BIT48) {=0D + TimerCount =3D 0;=0D + }=0D +=0D + //=0D + // Program the stable timer with the new count value=0D + //=0D + mTimerTicks =3D TimerCount;=0D + SetPitCount (TimerCount);=0D +=0D + //=0D + // Enable timer interrupt=0D + //=0D + mCpu->EnableInterrupt (mCpu);=0D + }=0D +=0D + //=0D + // Save the new timer period=0D + //=0D + mTimerPeriod =3D TimerPeriod;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + This function retrieves the period of timer interrupts in 100 ns units,= =0D + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPer= iod=0D + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 = is=0D + returned, then the timer is currently disabled.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D + @param TimerPeriod A pointer to the timer period to retrieve in 100 = ns units. If=0D + 0 is returned, then the timer is currently disabl= ed.=0D +=0D + @retval EFI_SUCCESS The timer period was returned in TimerPer= iod.=0D + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverGetTimerPeriod (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This,=0D + OUT UINT64 *TimerPeriod=0D + )=0D +{=0D + if (TimerPeriod =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + *TimerPeriod =3D mTimerPeriod;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Disable the timer=0D + DXE Core will disable the timer after all the event handlers have run.=0D +=0D + @param[in] Event The Event that is being processed=0D + @param[in] Context Event Context=0D +**/=0D +VOID=0D +EFIAPI=0D +ExitBootServicesEvent (=0D + IN EFI_EVENT Event,=0D + IN VOID *Context=0D + )=0D +{=0D + /*=0D + * Disable timer interrupt when exiting boot service=0D + */=0D + LoongarchWriteqTmcfg (0);=0D +}=0D +=0D +/**=0D + This function generates a soft timer interrupt. If the platform does not= support soft=0D + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned.=0D + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler ()=0D + service, then a soft timer interrupt will be generated. If the timer int= errupt is=0D + enabled when this service is called, then the registered handler will be= invoked. The=0D + registered handler should not be able to distinguish a hardware-generate= d timer=0D + interrupt from a software-generated timer interrupt.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D +=0D + @retval EFI_SUCCESS The soft timer interrupt was generated.=0D + @retval EFI_UNSUPPORTED The platform does not support the generation o= f soft timer interrupts.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverGenerateSoftInterrupt (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This=0D + )=0D +{=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Initialize the Timer Architectural Protocol driver=0D +=0D + @param ImageHandle ImageHandle of the loaded driver=0D + @param SystemTable Pointer to the System Table=0D +=0D + @retval EFI_SUCCESS Timer Architectural Protocol created=0D + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial= ize driver.=0D + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize the driver.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +StableTimerDriverInitialize (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT32 TimerVector;=0D +=0D + //=0D + // Initialize the pointer to our notify function.=0D + //=0D + mTimerNotifyFunction =3D NULL;=0D +=0D + //=0D + // Make sure the Timer Architectural Protocol is not already installed i= n the system=0D + //=0D + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid);=0D +=0D + //=0D + // Find the CPU architectural protocol.=0D + //=0D + Status =3D gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **= ) &mCpu);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Force the timer to be disabled=0D + //=0D + Status =3D TimerDriverSetTimerPeriod (&mTimer, 0);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Calculate const frequence=0D + //=0D + StableTimerFreq =3D CalcConstFreq ();=0D + DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DStable timer freq = %d Hz=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n", StableTimerFreq));=0D +=0D + //=0D + // Install interrupt handler for Stable Timer #0 (ISA IRQ0)=0D + //=0D + TimerVector =3D EXCEPT_LOONGARCH_INT_TIMER;=0D + Status =3D mCpu->RegisterInterruptHandler (mCpu, TimerVector, TimerInter= ruptHandler);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Enable TI local timer interrupt=0D + //=0D + CpuSetIP (1 << 11);=0D +=0D + //=0D + // Force the timer to be enabled at its default period=0D + //=0D + Status =3D TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATI= ON);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Install the Timer Architectural Protocol onto a new handle=0D + //=0D + Status =3D gBS->InstallMultipleProtocolInterfaces (=0D + &mTimerHandle,=0D + &gEfiTimerArchProtocolGuid, &mTimer,=0D + NULL=0D + );=0D +=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + // Register for an ExitBootServicesEvent=0D + Status =3D gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, = ExitBootServicesEvent, NULL,=0D + &EfiExitBootServicesEvent);=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + return Status;=0D +}=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= r.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.h=0D new file mode 100644=0D index 0000000000..84036cab00=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.h=0D @@ -0,0 +1,172 @@=0D +/** @file=0D + Private data structures=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 TIMER_H_=0D +#define TIMER_H_=0D +=0D +#include =0D +=0D +#define DEFAULT_TIMER_TICK_DURATION 100000 //10ms =3D 100000 100 ns units= =0D +#define SR_IP7 (1 << 15)=0D +//=0D +// Function Prototypes=0D +//=0D +extern UINT32 EFIAPI CpuGetCompare(VOID);=0D +extern VOID EFIAPI CpuSetCompare(IN UINT32 val);=0D +extern VOID EFIAPI CpuSetIP(IN UINT32 val);=0D +extern VOID EFIAPI ClearC0Cause(IN UINT32 val);=0D +extern VOID EFIAPI ClearC0Status(IN UINT32 val);=0D +/**=0D + Initialize the Timer Architectural Protocol driver=0D +=0D + @param ImageHandle ImageHandle of the loaded driver=0D + @param SystemTable Pointer to the System Table=0D +=0D + @retval EFI_SUCCESS Timer Architectural Protocol created=0D + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial= ize driver.=0D + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize the driver.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverInitialize (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + );=0D +=0D +/**=0D + This function adjusts the period of timer interrupts to the value specif= ied=0D + by TimerPeriod. If the timer period is updated, then the selected timer= =0D + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If=0D + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned= .=0D + If an error occurs while attempting to update the timer period, then the= =0D + timer hardware will be put back in its state prior to this call, and=0D + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt=0D + is disabled. This is not the same as disabling the CPU's interrupts.=0D + Instead, it must either turn off the timer hardware, or it must adjust t= he=0D + interrupt controller so that a CPU interrupt is not generated when the t= imer=0D + interrupt fires.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D + @param NotifyFunction The rate to program the timer interrupt in 100 nS= units. If=0D + the timer hardware is not programmable, then EFI_= UNSUPPORTED is=0D + returned. If the timer is programmable, then the= timer period=0D + will be rounded up to the nearest timer period th= at is supported=0D + by the timer hardware. If TimerPeriod is set to = 0, then the=0D + timer interrupts will be disabled.=0D +=0D + @retval EFI_SUCCESS The timer period was changed.=0D + @retval EFI_UNSUPPORTED The platform cannot change the period o= f the timer interrupt.=0D + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverRegisterHandler (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This,=0D + IN EFI_TIMER_NOTIFY NotifyFunction=0D + );=0D +=0D +/**=0D + This function adjusts the period of timer interrupts to the value specif= ied=0D + by TimerPeriod. If the timer period is updated, then the selected timer= =0D + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If=0D + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned= .=0D + If an error occurs while attempting to update the timer period, then the= =0D + timer hardware will be put back in its state prior to this call, and=0D + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt=0D + is disabled. This is not the same as disabling the CPU's interrupts.=0D + Instead, it must either turn off the timer hardware, or it must adjust t= he=0D + interrupt controller so that a CPU interrupt is not generated when the t= imer=0D + interrupt fires.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D + @param TimerPeriod The rate to program the timer interrupt in 100 nS= units. If=0D + the timer hardware is not programmable, then EFI_= UNSUPPORTED is=0D + returned. If the timer is programmable, then the= timer period=0D + will be rounded up to the nearest timer period th= at is supported=0D + by the timer hardware. If TimerPeriod is set to = 0, then the=0D + timer interrupts will be disabled.=0D +=0D + @retval EFI_SUCCESS The timer period was changed.=0D + @retval EFI_UNSUPPORTED The platform cannot change the period o= f the timer interrupt.=0D + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverSetTimerPeriod (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This,=0D + IN UINT64 TimerPeriod=0D + );=0D +=0D +/**=0D + This function retrieves the period of timer interrupts in 100 ns units,= =0D + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPer= iod=0D + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 = is=0D + returned, then the timer is currently disabled.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D + @param TimerPeriod A pointer to the timer period to retrieve in 100 = ns units. If=0D + 0 is returned, then the timer is currently disabl= ed.=0D +=0D + @retval EFI_SUCCESS The timer period was returned in TimerPer= iod.=0D + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverGetTimerPeriod (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This,=0D + OUT UINT64 *TimerPeriod=0D + );=0D +=0D +/**=0D + This function generates a soft timer interrupt. If the platform does not= support soft=0D + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned.=0D + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler()=0D + service, then a soft timer interrupt will be generated. If the timer int= errupt is=0D + enabled when this service is called, then the registered handler will be= invoked. The=0D + registered handler should not be able to distinguish a hardware-generate= d timer=0D + interrupt from a software-generated timer interrupt.=0D +=0D + @param This The EFI_TIMER_ARCH_PROTOCOL instance.=0D +=0D + @retval EFI_SUCCESS The soft timer interrupt was generated.=0D + @retval EFI_UNSUPPORTED The platform does not support the generation o= f soft timer interrupts.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +TimerDriverGenerateSoftInterrupt (=0D + IN EFI_TIMER_ARCH_PROTOCOL *This=0D + );=0D +=0D +/**=0D + Write Csr TMCFG register.=0D +=0D + @param A0 The value used to write to the TMCFG register=0D +=0D + @retval none=0D +**/=0D +extern=0D +VOID=0D +LoongarchWriteqTmcfg (=0D + IN UINT64 Val=0D + );=0D +=0D +/**=0D + Write Csr TINTCLR register.=0D +=0D + @param A0 The value used to write to the TINTCLR register=0D +=0D + @retval none=0D +**/=0D +extern=0D +VOID=0D +LoongarchWriteqTintclr (=0D + IN UINT64 Val=0D + );=0D +=0D +#endif // TIMER_H_=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= rConfig.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer= Config.S=0D new file mode 100644=0D index 0000000000..2f364c193d=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerConfig= .S=0D @@ -0,0 +1,38 @@=0D +#-------------------------------------------------------------------------= -----=0D +#=0D +# Timer Cfg 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(LoongarchWriteqTmcfg)=0D +ASM_GLOBAL ASM_PFX(LoongarchWriteqTintclr)=0D +=0D +#=0D +# Write Csr TMCFG register.=0D +# @param A0 The value used to write to the TMCFG register=0D +# @retval none=0D +#=0D +=0D +ASM_PFX(LoongarchWriteqTmcfg):=0D + csrwr A0, LOONGARCH_CSR_TMCFG=0D + jirl ZERO, RA,0=0D +=0D +#=0D +# Write Csr TINTCLR register.=0D +# @param A0 The value used to write to the TINTCLR register=0D +# @retval none=0D +#=0D +=0D +ASM_PFX(LoongarchWriteqTintclr):=0D + csrwr A0, LOONGARCH_CSR_TINTCLR=0D + jirl ZERO, RA,0=0D diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= rDxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerD= xe.inf=0D new file mode 100644=0D index 0000000000..d4a07c8759=0D --- /dev/null=0D +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerDxe.in= f=0D @@ -0,0 +1,44 @@=0D +## @file=0D +# Stable timer driver that provides Timer Arch protocol.=0D +#=0D +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights = reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D Timer=0D + MODULE_UNI_FILE =3D Timer.uni=0D + FILE_GUID =3D AEBE2648-47A9-40FA-83FD-06AA88443BB2= =0D + MODULE_TYPE =3D DXE_DRIVER=0D + VERSION_STRING =3D 1.0=0D + ENTRY_POINT =3D StableTimerDriverInitialize=0D +=0D +#=0D +# VALID_ARCHITECTURES =3D LOONGARCH64=0D +#=0D +=0D +[Sources]=0D + Timer.h=0D + Timer.c=0D + TimerConfig.S=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + Platform/Loongson/LoongArchQemuPkg/Loongson.dec=0D +=0D +[LibraryClasses]=0D + UefiBootServicesTableLib=0D + BaseLib=0D + DebugLib=0D + UefiDriverEntryPoint=0D + IoLib=0D + TimerLib=0D +=0D +[Protocols]=0D + gEfiCpuArchProtocolGuid ## CONSUMES=0D + gEfiTimerArchProtocolGuid ## PRODUCES=0D +=0D +[depex]=0D + TRUE=0D -- =0D 2.31.1=0D =0D