From nobody Sat Nov 2 16:26:05 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1486668402306337.32364508602984; Thu, 9 Feb 2017 11:26:42 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id DF72182001; Thu, 9 Feb 2017 11:26:34 -0800 (PST) Received: from cam-smtp0.cambridge.arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 063FA81F4B for ; Thu, 9 Feb 2017 11:26:31 -0800 (PST) Received: from E107800.Emea.Arm.com (e107800.emea.arm.com [10.1.31.76]) by cam-smtp0.cambridge.arm.com (8.13.8/8.13.8) with ESMTP id v19JQSoj006780; Thu, 9 Feb 2017 19:26:30 GMT X-Original-To: edk2-devel@ml01.01.org From: evan.lloyd@arm.com To: edk2-devel@ml01.01.org Date: Thu, 9 Feb 2017 19:26:23 +0000 Message-Id: <20170209192623.262044-5-evan.lloyd@arm.com> X-Mailer: git-send-email 2.8.3 In-Reply-To: <20170209192623.262044-1-evan.lloyd@arm.com> References: <20170209192623.262044-1-evan.lloyd@arm.com> Subject: [edk2] [PATCH 4/4] ArmPkg:Provide GetTriggerType/SetTriggerType functions X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ryan Harkin , Leif Lindholm , Ard Biesheuvel MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Girish Pathak This change implements GetTriggerType and SetTriggerType functions in ArmGicV2Dxe (GicV2GetTriggerType/GicV2SetTriggerType) and ArmGicV3Dxe (GicV3GetTriggerType/GicV3SetTriggerType) SetTriggerType configures the interrupt mode of an interrupt as edge sensitive or level sensitive. GetTriggerType function returns the mode of an interrupt. The requirement for this change derives from a problem detected on ARM Juno boards, but the change is of generic relevance. NOTE: At this point the GICv3 code is not tested. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Girish Pathak Signed-off-by: Evan Lloyd Tested-by: Girish Pathak --- ArmPkg/Include/Library/ArmGicLib.h | 4 + ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c | 165 ++++++++++++++++++-- ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c | 159 +++++++++++++++++-- 3 files changed, 308 insertions(+), 20 deletions(-) diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/Ar= mGicLib.h index 4364f3ffef464596f64cf59881d703cf54cf0ddd..6610f356c20e73d84ff3ba51995= 6b426d97ef1eb 100644 --- a/ArmPkg/Include/Library/ArmGicLib.h +++ b/ArmPkg/Include/Library/ArmGicLib.h @@ -51,6 +51,10 @@ #define ARM_GIC_ICDDCR_ARE (1 << 4) // Affinity Routing Enable (ARE) #define ARM_GIC_ICDDCR_DS (1 << 6) // Disable Security (DS) =20 +// GICD_ICDICFR bits +#define ARM_GIC_ICDICFR_LEVEL_TRIGGERED 0x0 // Level triggered interrupt +#define ARM_GIC_ICDICFR_EDGE_TRIGGERED 0x1 // Edge triggered interrupt + // // GIC Redistributor // diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c b/ArmPkg/Drivers/Arm= Gic/GicV2/ArmGicV2Dxe.c index 8c4d66125e2e8c7af9898f336ee742ed0aebf058..1f47403c6cdc7e8c0f6ac65d3b9= 5a562da6a2d32 100644 --- a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c @@ -29,6 +29,7 @@ Abstract: #define ARM_GIC_DEFAULT_PRIORITY 0x80 =20 extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol; +extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol; =20 STATIC UINT32 mGicInterruptInterfaceBase; STATIC UINT32 mGicDistributorBase; @@ -193,19 +194,95 @@ EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2P= rotocol =3D { GicV2EndOfInterrupt }; =20 +/** + Calculate GICD_ICFGRn base address and corresponding bit + field Int_config[1] of the GIC distributor register. + + @param Source Hardware source of the interrupt. + @param RegAddress Corresponding GICD_ICFGRn base address. + @param BitNumber Bit number in the register to set/reset. + + @retval EFI_SUCCESS Source interrupt supported. + @retval EFI_UNSUPPORTED Source interrupt is not supported. +**/ STATIC EFI_STATUS +GicGetDistributorIntrCfgBaseAndBitField ( + IN HARDWARE_INTERRUPT_SOURCE Source, + OUT UINTN *RegAddress, + OUT UINTN *BitNumber + ) +{ + UINTN RegOffset; + UINTN Field; + + if (Source >=3D mGicNumInterrupts) { + ASSERT(Source < mGicNumInterrupts); + return EFI_UNSUPPORTED; + } + + RegOffset =3D Source / 16; + Field =3D Source % 16; + *RegAddress =3D PcdGet64 (PcdGicDistributorBase) + + ARM_GIC_ICDICFR + + (4 * RegOffset); + *BitNumber =3D (Field * 2) + 1; + + return EFI_SUCCESS; +} + +/** + Get interrupt trigger type of an interrupt + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt. + @param TriggerType Returns interrupt trigger type. + + @retval EFI_SUCCESS Source interrupt supported. + @retval EFI_UNSUPPORTED Source interrupt is not supported. +**/ +EFI_STATUS EFIAPI GicV2GetTriggerType ( IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This, - IN HARDWARE_INTERRUPT_SOURCE Source, + IN HARDWARE_INTERRUPT_SOURCE Source, OUT EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE *TriggerType ) { + UINTN RegAddress; + UINTN BitNumber; + EFI_STATUS Status; + + RegAddress =3D 0; + BitNumber =3D 0; + + Status =3D GicGetDistributorIntrCfgBaseAndBitField ( + Source, + &RegAddress, + &BitNumber + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + *TriggerType =3D (MmioBitFieldRead32 (RegAddress, BitNumber, BitNumber) = =3D=3D 0) + ? EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH + : EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING; + return EFI_SUCCESS; } =20 -STATIC +/** + Set interrupt trigger type of an interrupt + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt. + @param TriggerType Interrupt trigger type. + + @retval EFI_SUCCESS Source interrupt supported. + @retval EFI_UNSUPPORTED Source interrupt is not supported. +**/ EFI_STATUS EFIAPI GicV2SetTriggerType ( @@ -214,20 +291,83 @@ GicV2SetTriggerType ( IN EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE TriggerType ) { + UINTN RegAddress =3D 0; + UINTN BitNumber =3D 0; + UINT32 Value; + EFI_STATUS Status; + BOOLEAN IntrSourceEnabled; + + if (TriggerType !=3D EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING + && TriggerType !=3D EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH) { + DEBUG ((EFI_D_ERROR, "Invalid interrupt trigger type: %d\n", \ + TriggerType)); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + Status =3D GicGetDistributorIntrCfgBaseAndBitField ( + Source, + &RegAddress, + &BitNumber + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D GicV2GetInterruptSourceState ( + (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This, + Source, + &IntrSourceEnabled + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Value =3D (TriggerType =3D=3D EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISIN= G) + ? ARM_GIC_ICDICFR_EDGE_TRIGGERED + : ARM_GIC_ICDICFR_LEVEL_TRIGGERED; + + // + // Before changing the value, we must disable the interrupt, + // otherwise GIC behavior is UNPREDICTABLE. + // + if (IntrSourceEnabled) { + GicV2DisableInterruptSource ( + (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This, + Source + ); + } + + MmioAndThenOr32 ( + RegAddress, + ~(0x1 << BitNumber), + Value << BitNumber + ); + // + // Restore interrupt state + // + if (IntrSourceEnabled) { + GicV2EnableInterruptSource ( + (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This, + Source + ); + } + return EFI_SUCCESS; } =20 -STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol =3D { - (HARDWARE_INTERRUPT2_REGISTER)RegisterInterruptSource, - (HARDWARE_INTERRUPT2_ENABLE)GicV2EnableInterruptSource, - (HARDWARE_INTERRUPT2_DISABLE)GicV2DisableInterruptSource, - (HARDWARE_INTERRUPT2_INTERRUPT_STATE)GicV2GetInterruptSourceState, - (HARDWARE_INTERRUPT2_END_OF_INTERRUPT)GicV2EndOfInterrupt, +EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol =3D { + (HARDWARE_INTERRUPT2_REGISTER) RegisterInterruptSource, + (HARDWARE_INTERRUPT2_ENABLE) GicV2EnableInterruptSource, + (HARDWARE_INTERRUPT2_DISABLE) GicV2DisableInterruptSource, + (HARDWARE_INTERRUPT2_INTERRUPT_STATE) GicV2GetInterruptSourceState, + (HARDWARE_INTERRUPT2_END_OF_INTERRUPT) GicV2EndOfInterrupt, GicV2GetTriggerType, GicV2SetTriggerType }; =20 - /** Shutdown our hardware =20 @@ -346,8 +486,11 @@ GicV2DxeInitialize ( ArmGicEnableDistributor (mGicDistributorBase); =20 Status =3D InstallAndRegisterInterruptService ( - &gHardwareInterruptV2Protocol, &gHardwareInterrupt2V2Protocol, - GicV2IrqInterruptHandler, GicV2ExitBootServicesEvent); + &gHardwareInterruptV2Protocol, + &gHardwareInterrupt2V2Protocol, + GicV2IrqInterruptHandler, + GicV2ExitBootServicesEvent + ); =20 return Status; } diff --git a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c b/ArmPkg/Drivers/Arm= Gic/GicV3/ArmGicV3Dxe.c index 02deeef78b6d7737172a5992c6decac43cfdd64a..a0383ecd7738750f73a22538114= 03d6ed0d2fd51 100644 --- a/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c +++ b/ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c @@ -19,6 +19,7 @@ #define ARM_GIC_DEFAULT_PRIORITY 0x80 =20 extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol; +extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol; =20 STATIC UINTN mGicDistributorBase; STATIC UINTN mGicRedistributorsBase; @@ -184,8 +185,54 @@ EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Pr= otocol =3D { GicV3EndOfInterrupt }; =20 +/** + Calculate GICD_ICFGRn base address and corresponding bit + field Int_config[1] in the GIC distributor register. + + @param Source Hardware source of the interrupt. + @param RegAddress Corresponding GICD_ICFGRn base address. + @param BitNumber Bit number in the register to set/reset. + + @retval EFI_SUCCESS Source interrupt supported. + @retval EFI_UNSUPPORTED Source interrupt is not supported. +**/ STATIC EFI_STATUS +GicGetDistributorIntrCfgBaseAndBitField ( + IN HARDWARE_INTERRUPT_SOURCE Source, + OUT UINTN *RegAddress, + OUT UINTN *BitNumber + ) +{ + UINTN RegOffset; + UINTN Field; + + if (Source >=3D mGicNumInterrupts) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + RegOffset =3D Source / 16; + Field =3D Source % 16; + *RegAddress =3D PcdGet64 (PcdGicDistributorBase) + + ARM_GIC_ICDICFR + + (4 * RegOffset); + *BitNumber =3D (Field * 2) + 1; + + return EFI_SUCCESS; +} + +/** + Get interrupt trigger type of an interrupt + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt. + @param TriggerType Returns interrupt trigger type. + + @retval EFI_SUCCESS Source interrupt supported. + @retval EFI_UNSUPPORTED Source interrupt is not supported. +**/ +EFI_STATUS EFIAPI GicV3GetTriggerType ( IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This, @@ -193,10 +240,37 @@ GicV3GetTriggerType ( OUT EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE *TriggerType ) { + UINTN RegAddress =3D 0; + UINTN BitNumber =3D 0; + EFI_STATUS Status; + + Status =3D GicGetDistributorIntrCfgBaseAndBitField ( + Source, + &RegAddress, + &BitNumber + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + *TriggerType =3D (MmioBitFieldRead32 (RegAddress, BitNumber, BitNumber) = =3D=3D 0) + ? EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH + : EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING; + return EFI_SUCCESS; } =20 -STATIC +/** + Set interrupt trigger type of an interrupt + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt. + @param TriggerType Interrupt trigger type. + + @retval EFI_SUCCESS Source interrupt supported. + @retval EFI_UNSUPPORTED Source interrupt is not supported. +**/ EFI_STATUS EFIAPI GicV3SetTriggerType ( @@ -205,15 +279,79 @@ GicV3SetTriggerType ( IN EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE TriggerType ) { + UINTN RegAddress; + UINTN BitNumber; + UINT32 Value; + EFI_STATUS Status; + BOOLEAN IntrSourceEnabled; + + if (TriggerType !=3D EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING + && TriggerType !=3D EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH) { + DEBUG ((EFI_D_ERROR, "Invalid interrupt trigger type: %d\n", \ + TriggerType)); + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + Status =3D GicGetDistributorIntrCfgBaseAndBitField ( + Source, + &RegAddress, + &BitNumber + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D GicV3GetInterruptSourceState ( + (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This, + Source, + &IntrSourceEnabled + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Value =3D (TriggerType =3D=3D EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISIN= G) + ? ARM_GIC_ICDICFR_EDGE_TRIGGERED + : ARM_GIC_ICDICFR_LEVEL_TRIGGERED; + + // + // Before changing the value, we must disable the interrupt, + // otherwise GIC behavior is UNPREDICTABLE. + // + if (IntrSourceEnabled) { + GicV3DisableInterruptSource ( + (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This, + Source + ); + } + + MmioAndThenOr32 ( + RegAddress, + ~(0x1 << BitNumber), + Value << BitNumber + ); + // + // Restore interrupt state + // + if (IntrSourceEnabled) { + GicV3EnableInterruptSource ( + (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This, + Source + ); + } + return EFI_SUCCESS; } =20 -STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol =3D { - (HARDWARE_INTERRUPT2_REGISTER)RegisterInterruptSource, - (HARDWARE_INTERRUPT2_ENABLE)GicV3EnableInterruptSource, - (HARDWARE_INTERRUPT2_DISABLE)GicV3DisableInterruptSource, - (HARDWARE_INTERRUPT2_INTERRUPT_STATE)GicV3GetInterruptSourceState, - (HARDWARE_INTERRUPT2_END_OF_INTERRUPT)GicV3EndOfInterrupt, +EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol =3D { + (HARDWARE_INTERRUPT2_REGISTER) RegisterInterruptSource, + (HARDWARE_INTERRUPT2_ENABLE) GicV3EnableInterruptSource, + (HARDWARE_INTERRUPT2_DISABLE) GicV3DisableInterruptSource, + (HARDWARE_INTERRUPT2_INTERRUPT_STATE) GicV3GetInterruptSourceState, + (HARDWARE_INTERRUPT2_END_OF_INTERRUPT) GicV3EndOfInterrupt, GicV3GetTriggerType, GicV3SetTriggerType }; @@ -365,8 +503,11 @@ GicV3DxeInitialize ( ArmGicEnableDistributor (mGicDistributorBase); =20 Status =3D InstallAndRegisterInterruptService ( - &gHardwareInterruptV3Protocol, &gHardwareInterrupt2V3Protocol, - GicV3IrqInterruptHandler, GicV3ExitBootServicesEvent); + &gHardwareInterruptV3Protocol, + &gHardwareInterrupt2V3Protocol, + GicV3IrqInterruptHandler, + GicV3ExitBootServicesEvent + ); =20 return Status; } --=20 Guid("CE165669-3EF3-493F-B85D-6190EE5B9759") _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel