andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 1 | /** @file
|
| 2 | *
|
oliviermartin | 5e77314 | 2012-03-26 11:03:36 +0000 | [diff] [blame] | 3 | * Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 4 | *
|
| 5 | * This program and the accompanying materials
|
| 6 | * are licensed and made available under the terms and conditions of the BSD License
|
| 7 | * which accompanies this distribution. The full text of the license may be found at
|
| 8 | * http://opensource.org/licenses/bsd-license.php
|
| 9 | *
|
| 10 | * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 11 | * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 12 | *
|
| 13 | **/
|
| 14 |
|
oliviermartin | 9253410 | 2012-03-26 10:45:27 +0000 | [diff] [blame] | 15 | #include <Base.h>
|
oliviermartin | 5e77314 | 2012-03-26 11:03:36 +0000 | [diff] [blame] | 16 | #include <Library/ArmLib.h>
|
oliviermartin | 9253410 | 2012-03-26 10:45:27 +0000 | [diff] [blame] | 17 | #include <Library/DebugLib.h>
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 18 | #include <Library/IoLib.h>
|
oliviermartin | 55a0d64 | 2011-09-22 22:59:52 +0000 | [diff] [blame] | 19 | #include <Library/ArmGicLib.h>
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 20 |
|
| 21 | /*
|
| 22 | * This function configures the all interrupts to be Non-secure.
|
| 23 | *
|
| 24 | */
|
| 25 | VOID
|
| 26 | EFIAPI
|
oliviermartin | 55a0d64 | 2011-09-22 22:59:52 +0000 | [diff] [blame] | 27 | ArmGicSetupNonSecure (
|
oliviermartin | 5e77314 | 2012-03-26 11:03:36 +0000 | [diff] [blame] | 28 | IN UINTN MpId,
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 29 | IN INTN GicDistributorBase,
|
| 30 | IN INTN GicInterruptInterfaceBase
|
| 31 | )
|
| 32 | {
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 33 | UINTN InterruptId;
|
| 34 | UINTN CachedPriorityMask;
|
oliviermartin | 9253410 | 2012-03-26 10:45:27 +0000 | [diff] [blame] | 35 | UINTN Index;
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 36 |
|
| 37 | CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 38 |
|
oliviermartin | 9e2b420 | 2011-06-11 11:15:55 +0000 | [diff] [blame] | 39 | // Set priority Mask so that no interrupts get through to CPU
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 40 | MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 41 |
|
oliviermartin | 9e2b420 | 2011-06-11 11:15:55 +0000 | [diff] [blame] | 42 | // Check if there are any pending interrupts
|
oliviermartin | 55a0d64 | 2011-09-22 22:59:52 +0000 | [diff] [blame] | 43 | //TODO: could be extended to take Peripheral interrupts into consideration, but at the moment only SGI's are taken into consideration.
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 44 | while(0 != (MmioRead32 (GicDistributorBase + ARM_GIC_ICDICPR) & 0xF)) {
|
oliviermartin | 9e2b420 | 2011-06-11 11:15:55 +0000 | [diff] [blame] | 45 | // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 46 | InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 47 |
|
oliviermartin | 9e2b420 | 2011-06-11 11:15:55 +0000 | [diff] [blame] | 48 | // Write to End of interrupt signal
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 49 | MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, InterruptId);
|
oliviermartin | 9e2b420 | 2011-06-11 11:15:55 +0000 | [diff] [blame] | 50 | }
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 51 |
|
oliviermartin | 5e77314 | 2012-03-26 11:03:36 +0000 | [diff] [blame] | 52 | // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt).
|
| 53 | if (IS_PRIMARY_CORE(MpId)) {
|
| 54 | // Ensure all GIC interrupts are Non-Secure
|
oliviermartin | e9f7c58 | 2012-05-02 19:48:00 +0000 | [diff] [blame] | 55 | for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) {
|
oliviermartin | 5e77314 | 2012-03-26 11:03:36 +0000 | [diff] [blame] | 56 | MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff);
|
| 57 | }
|
| 58 | } else {
|
| 59 | // The secondary cores only set the Non Secure bit to their banked PPIs
|
| 60 | MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff);
|
oliviermartin | 9253410 | 2012-03-26 10:45:27 +0000 | [diff] [blame] | 61 | }
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 62 |
|
| 63 | // Ensure all interrupts can get through the priority mask
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 64 | MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 65 | }
|
| 66 |
|
oliviermartin | 9253410 | 2012-03-26 10:45:27 +0000 | [diff] [blame] | 67 | /*
|
| 68 | * This function configures the interrupts set by the mask to be secure.
|
| 69 | *
|
| 70 | */
|
| 71 | VOID
|
| 72 | EFIAPI
|
| 73 | ArmGicSetSecureInterrupts (
|
| 74 | IN UINTN GicDistributorBase,
|
| 75 | IN UINTN* GicSecureInterruptMask,
|
| 76 | IN UINTN GicSecureInterruptMaskSize
|
| 77 | )
|
| 78 | {
|
| 79 | UINTN Index;
|
| 80 | UINT32 InterruptStatus;
|
| 81 |
|
| 82 | // We must not have more interrupts defined by the mask than the number of available interrupts
|
oliviermartin | e9f7c58 | 2012-05-02 19:48:00 +0000 | [diff] [blame] | 83 | ASSERT(GicSecureInterruptMaskSize <= (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32));
|
oliviermartin | 9253410 | 2012-03-26 10:45:27 +0000 | [diff] [blame] | 84 |
|
| 85 | // Set all the interrupts defined by the mask as Secure
|
| 86 | for (Index = 0; Index < GicSecureInterruptMaskSize; Index++) {
|
| 87 | InterruptStatus = MmioRead32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4));
|
| 88 | MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), InterruptStatus & (~GicSecureInterruptMask[Index]));
|
| 89 | }
|
| 90 | }
|
| 91 |
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 92 | VOID
|
| 93 | EFIAPI
|
oliviermartin | 55a0d64 | 2011-09-22 22:59:52 +0000 | [diff] [blame] | 94 | ArmGicEnableInterruptInterface (
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 95 | IN INTN GicInterruptInterfaceBase
|
| 96 | )
|
| 97 | {
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 98 | // Set Priority Mask to allow interrupts
|
| 99 | MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000FF);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 100 |
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 101 | // Enable CPU interface in Secure world
|
| 102 | // Enable CPU inteface in Non-secure World
|
| 103 | // Signal Secure Interrupts to CPU using FIQ line *
|
| 104 | MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR,
|
oliviermartin | 55a0d64 | 2011-09-22 22:59:52 +0000 | [diff] [blame] | 105 | ARM_GIC_ICCICR_ENABLE_SECURE |
|
| 106 | ARM_GIC_ICCICR_ENABLE_NS |
|
| 107 | ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 108 | }
|
| 109 |
|
| 110 | VOID
|
| 111 | EFIAPI
|
oliviermartin | 55a0d64 | 2011-09-22 22:59:52 +0000 | [diff] [blame] | 112 | ArmGicEnableDistributor (
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 113 | IN INTN GicDistributorBase
|
| 114 | )
|
| 115 | {
|
oliviermartin | 886f97c | 2011-09-27 16:42:47 +0000 | [diff] [blame] | 116 | // Turn on the GIC distributor
|
| 117 | MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1);
|
andrewfish | 1bfda05 | 2011-02-02 22:35:30 +0000 | [diff] [blame] | 118 | }
|