+/**\r
+ Get interrupt trigger type of an interrupt\r
+\r
+ @param This Instance pointer for this protocol\r
+ @param Source Hardware source of the interrupt.\r
+ @param TriggerType Returns interrupt trigger type.\r
+\r
+ @retval EFI_SUCCESS Source interrupt supported.\r
+ @retval EFI_UNSUPPORTED Source interrupt is not supported.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+GicV3GetTriggerType (\r
+ IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,\r
+ IN HARDWARE_INTERRUPT_SOURCE Source,\r
+ OUT EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE *TriggerType\r
+ )\r
+{\r
+ UINTN RegAddress;\r
+ UINTN Config1Bit;\r
+ EFI_STATUS Status;\r
+\r
+ Status = GicGetDistributorIcfgBaseAndBit (\r
+ Source,\r
+ &RegAddress,\r
+ &Config1Bit\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((MmioRead32 (RegAddress) & (1 << Config1Bit)) == 0) {\r
+ *TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH;\r
+ } else {\r
+ *TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set interrupt trigger type of an interrupt\r
+\r
+ @param This Instance pointer for this protocol\r
+ @param Source Hardware source of the interrupt.\r
+ @param TriggerType Interrupt trigger type.\r
+\r
+ @retval EFI_SUCCESS Source interrupt supported.\r
+ @retval EFI_UNSUPPORTED Source interrupt is not supported.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+GicV3SetTriggerType (\r
+ IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,\r
+ IN HARDWARE_INTERRUPT_SOURCE Source,\r
+ IN EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE TriggerType\r
+ )\r
+{\r
+ UINTN RegAddress;\r
+ UINTN Config1Bit;\r
+ UINT32 Value;\r
+ EFI_STATUS Status;\r
+ BOOLEAN SourceEnabled;\r
+\r
+ if ( (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)\r
+ && (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH)) {\r
+ DEBUG ((DEBUG_ERROR, "Invalid interrupt trigger type: %d\n", \\r
+ TriggerType));\r
+ ASSERT (FALSE);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = GicGetDistributorIcfgBaseAndBit (\r
+ Source,\r
+ &RegAddress,\r
+ &Config1Bit\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = GicV3GetInterruptSourceState (\r
+ (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This,\r
+ Source,\r
+ &SourceEnabled\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Value = (TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)\r
+ ? ARM_GIC_ICDICFR_EDGE_TRIGGERED\r
+ : ARM_GIC_ICDICFR_LEVEL_TRIGGERED;\r
+\r
+ // Before changing the value, we must disable the interrupt,\r
+ // otherwise GIC behavior is UNPREDICTABLE.\r
+ if (SourceEnabled) {\r
+ GicV3DisableInterruptSource (\r
+ (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This,\r
+ Source\r
+ );\r
+ }\r
+\r
+ MmioAndThenOr32 (\r
+ RegAddress,\r
+ ~(0x1 << Config1Bit),\r
+ Value << Config1Bit\r
+ );\r
+ // Restore interrupt state\r
+ if (SourceEnabled) {\r
+ GicV3EnableInterruptSource (\r
+ (EFI_HARDWARE_INTERRUPT_PROTOCOL*)This,\r
+ Source\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol = {\r
+ (HARDWARE_INTERRUPT2_REGISTER)RegisterInterruptSource,\r
+ (HARDWARE_INTERRUPT2_ENABLE)GicV3EnableInterruptSource,\r
+ (HARDWARE_INTERRUPT2_DISABLE)GicV3DisableInterruptSource,\r
+ (HARDWARE_INTERRUPT2_INTERRUPT_STATE)GicV3GetInterruptSourceState,\r
+ (HARDWARE_INTERRUPT2_END_OF_INTERRUPT)GicV3EndOfInterrupt,\r
+ GicV3GetTriggerType,\r
+ GicV3SetTriggerType\r
+};\r
+\r