From nobody Fri Apr 26 08:26:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+96280+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+96280+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1668157966; cv=none; d=zohomail.com; s=zohoarc; b=IR3IZrOO/o9I76zRuOks50BaaJGQzCXS+/lK6UHDI8vm1J39pptXGMG+AsGPgY2/bPD1KWw9ZFZtOOnL9Wx+xZmiMLkVKZp0/+y/5BZlpVQ7kZVK+cQvqcrbGIKBKA6IHUkbl12/rxfEq8ineOTBSRDljF7dB7ga44TqGWI+x/g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1668157966; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=e0NaYR0Y6fsHOZ0aPS//exklvUcRtDZiYd8Yer/gdQ8=; b=M08euQY82V6P2dHswaqUGlXyz+blzegezi8ruWsLmM6zo+bw80uCZ+uK3ytGLftnbdqYTgMau5IF9vvftCxLKyQMwpwdS/ke7tNVc9q+HdAJBb7LohKLr47w7plMhEr5B0bBry2R/qa+p1P/PCj2wNaDTqRePGWKYdMQOOfet8o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+96280+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1668157966373471.22063598856516; Fri, 11 Nov 2022 01:12:46 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id BUtuYY1788612xZPep2hkWso; Fri, 11 Nov 2022 01:12:46 -0800 X-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 X-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) X-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-devel] [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> 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= Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lixianglai@loongson.cn X-Gm-Message-State: xo2p5DArzxgI0obpOWTaSLHVx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1668157966; bh=MOzqF7u4RJHLCQWeDtIt5JLyjdAAloJ5eBKUKDlQ9nI=; h=Cc:Date:From:Reply-To:Subject:To; b=gCacerFgr25c5Wtg2IpcZjQIDlZL+dNlXaZNeEceU0fRjAX6KPUZ5ii+d5k/McvRQyX HQ1OZzTvFjyDPpQb/NdHG70538Dq9QTsEwliWFhbuc485kW5asbrgJFzH3rBqrkcPCYvY eEKbrAEf4HrkMe1TFi6xQrRYeYKO09XPQXU= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1668157968471100044 Content-Type: text/plain; charset="utf-8" This driver produces Timer Architectural Protocol, Registers a timer interrupt and initializes the timer. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4054 Cc: Bibo Mao Cc: Chao Li Cc: Leif Lindholm Cc: Liming Gao Cc: Michael D Kinney Signed-off-by: xianglai li Reviewed-by: Chao Li --- .../Drivers/StableTimerDxe/Timer.c | 388 ++++++++++++++++++ .../Drivers/StableTimerDxe/Timer.h | 172 ++++++++ .../Drivers/StableTimerDxe/TimerConfig.S | 38 ++ .../Drivers/StableTimerDxe/TimerDxe.inf | 44 ++ 4 files changed, 642 insertions(+) create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/Timer.c create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/Timer.h create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/TimerConfig.S create mode 100644 Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerD= xe/TimerDxe.inf diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= r.c b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.c new file mode 100644 index 0000000000..e09da71272 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.c @@ -0,0 +1,388 @@ +/** @file + Timer Architectural Protocol as defined in the DXE CIS + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "Library/Cpu.h" +#include +#include +#include "Timer.h" +#include +#include + +// +// The handle onto which the Timer Architectural Protocol will be installed +// +EFI_HANDLE mTimerHandle =3D NULL; +EFI_EVENT EfiExitBootServicesEvent =3D (EFI_EVENT)NULL; + +// +// The Timer Architectural Protocol that this driver produces +// +EFI_TIMER_ARCH_PROTOCOL mTimer =3D { + TimerDriverRegisterHandler, + TimerDriverSetTimerPeriod, + TimerDriverGetTimerPeriod, + TimerDriverGenerateSoftInterrupt +}; + +// +// Pointer to the CPU Architectural Protocol instance +// +EFI_CPU_ARCH_PROTOCOL *mCpu; + +// +// The notification function to call on every timer interrupt. +// A bug in the compiler prevents us from initializing this here. +// +EFI_TIMER_NOTIFY mTimerNotifyFunction; + +// +// The current period of the timer interrupt +// +volatile UINT64 mTimerPeriod =3D 0; +volatile UINT64 mTimerTicks =3D 0; + +// +// Const frequence in Hz +// +extern UINT32 StableTimerFreq; + +/** + Sets the counter value for timer. + + @param Count The 16-bit counter value to program into stable timer. + + @retval VOID +**/ +VOID +SetPitCount ( + IN UINT64 Count + ) +{ + if (Count <=3D 4) { + return; + } + + Count &=3D LOONGARCH_CSR_TMCFG_TIMEVAL; + Count |=3D LOONGARCH_CSR_TMCFG_EN | LOONGARCH_CSR_TMCFG_PERIOD; + LoongarchWriteqTmcfg (Count); +} + +/** + Timer Interrupt Handler. + + @param InterruptType The type of interrupt that occurred + @param SystemContext A pointer to the system context when the interru= pt occurred + + @retval VOID +**/ +VOID +EFIAPI +TimerInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_TPL OriginalTPL; + + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Clear interrupt. + // + LoongarchWriteqTintclr (0x1); + + if (mTimerNotifyFunction !=3D NULL) { + // + // @bug : This does not handle missed timer interrupts + // + mTimerNotifyFunction (mTimerPeriod); + } + + gBS->RestoreTPL (OriginalTPL); +} + +/** + 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 han= dler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a h= andler + when a handler is already registered, then EFI_ALREADY_STARTED is return= ed. + If an attempt is made to unregister a handler when a handler is not regi= stered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ER= ROR + is returned. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when a timer interrupt fire= s. This + function executes at TPL_HIGH_LEVEL. The DXE Co= re will + register a handler for the timer interrupt, so i= t can know + how much time has passed. This information is u= sed 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 time= r interrupts. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a = handler is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a hand= ler was not + previously registered. + @retval EFI_DEVICE_ERROR The timer handler could not be reg= istered. +**/ +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +{ + // + // Check for invalid parameters + // + if ((NotifyFunction =3D=3D NULL) + && (mTimerNotifyFunction =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + if ((NotifyFunction !=3D NULL) + && mTimerNotifyFunction !=3D NULL) + { + return EFI_ALREADY_STARTED; + } + + mTimerNotifyFunction =3D NotifyFunction; + + return EFI_SUCCESS; +} + +/** + This function adjusts the period of timer interrupts to the value specif= ied + 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 inter= rupt + 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 t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + 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 th= at 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 o= f the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue to a device error. +**/ +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +{ + UINT64 TimerCount; + + if (TimerPeriod =3D=3D 0) { + // + // Disable timer interrupt for a TimerPeriod of 0 + // + mCpu->DisableInterrupt (mCpu); + } else { + + TimerCount =3D TimerPeriod * StableTimerFreq / 10000000ULL; + + if (TimerCount >=3D BIT48) { + TimerCount =3D 0; + } + + // + // Program the stable timer with the new count value + // + mTimerTicks =3D TimerCount; + SetPitCount (TimerCount); + + // + // Enable timer interrupt + // + mCpu->EnableInterrupt (mCpu); + } + + // + // Save the new timer period + // + mTimerPeriod =3D TimerPeriod; + + 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 TimerPer= iod + 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 disabl= ed. + + @retval EFI_SUCCESS The timer period was returned in TimerPer= iod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. +**/ +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +{ + if (TimerPeriod =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod =3D mTimerPeriod; + + return EFI_SUCCESS; +} + +/** + Disable the timer + DXE Core will disable the timer after all the event handlers have run. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +ExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + /* + * Disable timer interrupt when exiting boot service + */ + LoongarchWriteqTmcfg (0); +} + +/** + This function generates a soft timer interrupt. If the platform does not= support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler () + service, then a soft timer interrupt will be generated. If the timer int= errupt 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-generate= d 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_UNSUPPORTED The platform does not support the generation o= f soft timer interrupts. +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +{ + return EFI_UNSUPPORTED; +} + +/** + 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 initial= ize driver. + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize the driver. +**/ +EFI_STATUS +EFIAPI +StableTimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 TimerVector; + + // + // Initialize the pointer to our notify function. + // + mTimerNotifyFunction =3D NULL; + + // + // Make sure the Timer Architectural Protocol is not already installed i= n the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid); + + // + // Find the CPU architectural protocol. + // + Status =3D gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **= ) &mCpu); + ASSERT_EFI_ERROR (Status); + + // + // Force the timer to be disabled + // + Status =3D TimerDriverSetTimerPeriod (&mTimer, 0); + ASSERT_EFI_ERROR (Status); + + // + // Calculate const frequence + // + StableTimerFreq =3D CalcConstFreq (); + 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)); + + // + // Install interrupt handler for Stable Timer #0 (ISA IRQ0) + // + TimerVector =3D EXCEPT_LOONGARCH_INT_TIMER; + Status =3D mCpu->RegisterInterruptHandler (mCpu, TimerVector, TimerInter= ruptHandler); + ASSERT_EFI_ERROR (Status); + + // + // Enable TI local timer interrupt + // + CpuSetIP (1 << 11); + + // + // Force the timer to be enabled at its default period + // + Status =3D TimerDriverSetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATI= ON); + ASSERT_EFI_ERROR (Status); + + // + // Install the Timer Architectural Protocol onto a new handle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mTimerHandle, + &gEfiTimerArchProtocolGuid, &mTimer, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + // Register for an ExitBootServicesEvent + Status =3D gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, = ExitBootServicesEvent, NULL, + &EfiExitBootServicesEvent); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= r.h b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.h new file mode 100644 index 0000000000..84036cab00 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer.h @@ -0,0 +1,172 @@ +/** @file + Private data structures + + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef TIMER_H_ +#define TIMER_H_ + +#include + +#define DEFAULT_TIMER_TICK_DURATION 100000 //10ms =3D 100000 100 ns units +#define SR_IP7 (1 << 15) +// +// Function Prototypes +// +extern UINT32 EFIAPI CpuGetCompare(VOID); +extern VOID EFIAPI CpuSetCompare(IN UINT32 val); +extern VOID EFIAPI CpuSetIP(IN UINT32 val); +extern VOID EFIAPI ClearC0Cause(IN UINT32 val); +extern VOID EFIAPI ClearC0Status(IN UINT32 val); +/** + 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 initial= ize driver. + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize 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 specif= ied + 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 inter= rupt + 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 t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + 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 th= at 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 o= f the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue 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 specif= ied + 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 inter= rupt + 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 t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + 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 th= at 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 o= f the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed d= ue 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 TimerPer= iod + 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 disabl= ed. + + @retval EFI_SUCCESS The timer period was returned in TimerPer= iod. + @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_SUCCE= SS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler() + service, then a soft timer interrupt will be generated. If the timer int= errupt 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-generate= d 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_UNSUPPORTED The platform does not support the generation o= f soft timer interrupts. +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ); + +/** + Write Csr TMCFG register. + + @param A0 The value used to write to the TMCFG register + + @retval none +**/ +extern +VOID +LoongarchWriteqTmcfg ( + IN UINT64 Val + ); + +/** + Write Csr TINTCLR register. + + @param A0 The value used to write to the TINTCLR register + + @retval none +**/ +extern +VOID +LoongarchWriteqTintclr ( + IN UINT64 Val + ); + +#endif // TIMER_H_ diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= rConfig.S b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Timer= Config.S new file mode 100644 index 0000000000..2f364c193d --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerConfig= .S @@ -0,0 +1,38 @@ +#-------------------------------------------------------------------------= ----- +# +# Timer Cfg for LoongArch +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights r= eserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#-------------------------------------------------------------------------= ----- + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#endif + +#include "Library/Cpu.h" + +ASM_GLOBAL ASM_PFX(LoongarchWriteqTmcfg) +ASM_GLOBAL ASM_PFX(LoongarchWriteqTintclr) + +# +# Write Csr TMCFG register. +# @param A0 The value used to write to the TMCFG register +# @retval none +# + +ASM_PFX(LoongarchWriteqTmcfg): + csrwr A0, LOONGARCH_CSR_TMCFG + jirl ZERO, RA,0 + +# +# Write Csr TINTCLR register. +# @param A0 The value used to write to the TINTCLR register +# @retval none +# + +ASM_PFX(LoongarchWriteqTintclr): + csrwr A0, LOONGARCH_CSR_TINTCLR + jirl ZERO, RA,0 diff --git a/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/Time= rDxe.inf b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerD= xe.inf new file mode 100644 index 0000000000..d4a07c8759 --- /dev/null +++ b/Platform/Loongson/LoongArchQemuPkg/Drivers/StableTimerDxe/TimerDxe.inf @@ -0,0 +1,44 @@ +## @file +# Stable timer driver that provides Timer Arch protocol. +# +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights = reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D Timer + MODULE_UNI_FILE =3D Timer.uni + FILE_GUID =3D AEBE2648-47A9-40FA-83FD-06AA88443BB2 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D StableTimerDriverInitialize + +# +# VALID_ARCHITECTURES =3D LOONGARCH64 +# + +[Sources] + Timer.h + Timer.c + TimerConfig.S + +[Packages] + MdePkg/MdePkg.dec + Platform/Loongson/LoongArchQemuPkg/Loongson.dec + +[LibraryClasses] + UefiBootServicesTableLib + BaseLib + DebugLib + UefiDriverEntryPoint + IoLib + TimerLib + +[Protocols] + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid ## PRODUCES + +[depex] + TRUE --=20 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#96280): https://edk2.groups.io/g/devel/message/96280 Mute This Topic: https://groups.io/mt/94955177/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-